From 9eeafafc88a1df06cee42e3838919d83f44f16ee Mon Sep 17 00:00:00 2001
From: Matthew Vernon
Date: Mon, 31 Aug 2026 21:37:22 +0100
Subject: [PATCH] Import pcre2_10.48.orig.tar.gz
[dgit import orig pcre2_10.48.orig.tar.gz]
---
AUTHORS.md | 221 +
BUILD.bazel | 199 +
CMakeLists.txt | 1637 ++
COPYING | 5 +
ChangeLog | 3518 +++
HACKING | 924 +
INSTALL | 368 +
LICENCE.md | 104 +
MODULE.bazel | 9 +
Makefile.am | 1060 +
Makefile.in | 4199 +++
NEWS | 703 +
NON-AUTOTOOLS-BUILD | 487 +
README | 1008 +
RunGrepTest | 1366 +
RunGrepTest.bat | 1338 +
RunTest | 1041 +
RunTest.bat | 603 +
SECURITY.md | 90 +
SUPPORT-LIFECYCLE.md | 432 +
aclocal.m4 | 1599 ++
ar-lib | 271 +
build.zig | 268 +
build.zig.zon | 25 +
cmake/COPYING-CMAKE-SCRIPTS | 22 +
cmake/FindEditline.cmake | 15 +
cmake/FindReadline.cmake | 67 +
cmake/PCRE2CheckVscript.cmake | 141 +
cmake/PCRE2UseSystemExtensions.cmake | 89 +
cmake/PCRE2WarningAsError.cmake | 35 +
cmake/pcre2-config.cmake.in | 90 +
compile | 348 +
config.guess | 1754 ++
config.sub | 1890 ++
configure | 21415 ++++++++++++++
configure.ac | 1327 +
depcomp | 791 +
deps/sljit/LICENSE | 25 +
deps/sljit/README.md | 74 +
.../allocator_src/sljitExecAllocatorApple.c | 137 +
.../allocator_src/sljitExecAllocatorCore.c | 327 +
.../allocator_src/sljitExecAllocatorFreeBSD.c | 89 +
.../allocator_src/sljitExecAllocatorPosix.c | 62 +
.../allocator_src/sljitExecAllocatorWindows.c | 40 +
.../sljitProtExecAllocatorNetBSD.c | 72 +
.../sljitProtExecAllocatorPosix.c | 172 +
.../allocator_src/sljitWXExecAllocatorPosix.c | 144 +
.../sljitWXExecAllocatorWindows.c | 102 +
deps/sljit/sljit_src/sljitConfig.h | 142 +
deps/sljit/sljit_src/sljitConfigCPU.h | 265 +
deps/sljit/sljit_src/sljitConfigInternal.h | 1017 +
deps/sljit/sljit_src/sljitLir.c | 3928 +++
deps/sljit/sljit_src/sljitLir.h | 2769 ++
deps/sljit/sljit_src/sljitNativeARM_32.c | 4950 ++++
deps/sljit/sljit_src/sljitNativeARM_64.c | 3805 +++
deps/sljit/sljit_src/sljitNativeARM_T2_32.c | 4625 +++
.../sljit/sljit_src/sljitNativeLOONGARCH_64.c | 4123 +++
deps/sljit/sljit_src/sljitNativeMIPS_32.c | 467 +
deps/sljit/sljit_src/sljitNativeMIPS_64.c | 382 +
deps/sljit/sljit_src/sljitNativeMIPS_common.c | 4597 +++
deps/sljit/sljit_src/sljitNativePPC_32.c | 485 +
deps/sljit/sljit_src/sljitNativePPC_64.c | 719 +
deps/sljit/sljit_src/sljitNativePPC_common.c | 3514 +++
deps/sljit/sljit_src/sljitNativeRISCV_32.c | 154 +
deps/sljit/sljit_src/sljitNativeRISCV_64.c | 296 +
.../sljit/sljit_src/sljitNativeRISCV_common.c | 4868 ++++
deps/sljit/sljit_src/sljitNativeS390X.c | 4822 ++++
deps/sljit/sljit_src/sljitNativeX86_32.c | 1707 ++
deps/sljit/sljit_src/sljitNativeX86_64.c | 1430 +
deps/sljit/sljit_src/sljitNativeX86_common.c | 5445 ++++
deps/sljit/sljit_src/sljitSerialize.c | 585 +
deps/sljit/sljit_src/sljitUtils.c | 344 +
doc/html/NON-AUTOTOOLS-BUILD.txt | 487 +
doc/html/README.txt | 1008 +
doc/html/index.html | 346 +
doc/html/pcre2-config.html | 103 +
doc/html/pcre2.html | 214 +
doc/html/pcre2_callout_enumerate.html | 63 +
doc/html/pcre2_code_copy.html | 43 +
doc/html/pcre2_code_copy_with_tables.html | 44 +
doc/html/pcre2_code_free.html | 42 +
doc/html/pcre2_compile.html | 120 +
doc/html/pcre2_compile_context_copy.html | 41 +
doc/html/pcre2_compile_context_create.html | 42 +
doc/html/pcre2_compile_context_free.html | 41 +
doc/html/pcre2_config.html | 85 +
doc/html/pcre2_convert_context_copy.html | 40 +
doc/html/pcre2_convert_context_create.html | 41 +
doc/html/pcre2_convert_context_free.html | 40 +
doc/html/pcre2_converted_pattern_free.html | 40 +
doc/html/pcre2_dfa_match.html | 86 +
doc/html/pcre2_general_context_copy.html | 42 +
doc/html/pcre2_general_context_create.html | 44 +
doc/html/pcre2_general_context_free.html | 40 +
doc/html/pcre2_get_error_message.html | 51 +
doc/html/pcre2_get_mark.html | 47 +
.../pcre2_get_match_data_heapframes_size.html | 40 +
doc/html/pcre2_get_match_data_size.html | 39 +
doc/html/pcre2_get_ovector_count.html | 39 +
doc/html/pcre2_get_ovector_pointer.html | 40 +
doc/html/pcre2_get_startchar.html | 44 +
doc/html/pcre2_jit_compile.html | 74 +
doc/html/pcre2_jit_free_unused_memory.html | 43 +
doc/html/pcre2_jit_match.html | 70 +
doc/html/pcre2_jit_stack_assign.html | 75 +
doc/html/pcre2_jit_stack_create.html | 50 +
doc/html/pcre2_jit_stack_free.html | 43 +
doc/html/pcre2_maketables.html | 48 +
doc/html/pcre2_maketables_free.html | 44 +
doc/html/pcre2_match.html | 87 +
doc/html/pcre2_match_context_copy.html | 41 +
doc/html/pcre2_match_context_create.html | 42 +
doc/html/pcre2_match_context_free.html | 41 +
doc/html/pcre2_match_data_create.html | 50 +
.../pcre2_match_data_create_from_pattern.html | 53 +
doc/html/pcre2_match_data_free.html | 48 +
doc/html/pcre2_next_match.html | 55 +
doc/html/pcre2_pattern_convert.html | 70 +
doc/html/pcre2_pattern_info.html | 109 +
doc/html/pcre2_serialize_decode.html | 65 +
doc/html/pcre2_serialize_encode.html | 66 +
doc/html/pcre2_serialize_free.html | 41 +
.../pcre2_serialize_get_number_of_codes.html | 49 +
doc/html/pcre2_set_bsr.html | 42 +
doc/html/pcre2_set_callout.html | 43 +
doc/html/pcre2_set_character_tables.html | 45 +
doc/html/pcre2_set_compile_extra_options.html | 58 +
.../pcre2_set_compile_recursion_guard.html | 46 +
doc/html/pcre2_set_depth_limit.html | 40 +
doc/html/pcre2_set_glob_escape.html | 43 +
doc/html/pcre2_set_glob_separator.html | 42 +
doc/html/pcre2_set_heap_limit.html | 40 +
doc/html/pcre2_set_match_limit.html | 40 +
...pcre2_set_max_pattern_compiled_length.html | 44 +
doc/html/pcre2_set_max_pattern_length.html | 43 +
doc/html/pcre2_set_max_varlookbehind.html | 42 +
doc/html/pcre2_set_newline.html | 51 +
doc/html/pcre2_set_offset_limit.html | 40 +
doc/html/pcre2_set_optimize.html | 57 +
doc/html/pcre2_set_parens_nest_limit.html | 40 +
doc/html/pcre2_set_recursion_limit.html | 40 +
...pcre2_set_recursion_memory_management.html | 42 +
doc/html/pcre2_set_substitute_callout.html | 43 +
.../pcre2_set_substitute_case_callout.html | 45 +
doc/html/pcre2_substitute.html | 112 +
doc/html/pcre2_substring_copy_byname.html | 58 +
doc/html/pcre2_substring_copy_bynumber.html | 57 +
doc/html/pcre2_substring_free.html | 41 +
doc/html/pcre2_substring_get_byname.html | 60 +
doc/html/pcre2_substring_get_bynumber.html | 58 +
doc/html/pcre2_substring_length_byname.html | 48 +
doc/html/pcre2_substring_length_bynumber.html | 48 +
doc/html/pcre2_substring_list_free.html | 41 +
doc/html/pcre2_substring_list_get.html | 56 +
doc/html/pcre2_substring_nametable_scan.html | 53 +
.../pcre2_substring_number_from_name.html | 50 +
doc/html/pcre2api.html | 4649 +++
doc/html/pcre2build.html | 671 +
doc/html/pcre2callout.html | 480 +
doc/html/pcre2compat.html | 303 +
doc/html/pcre2convert.html | 191 +
doc/html/pcre2demo.html | 467 +
doc/html/pcre2grep.html | 1135 +
doc/html/pcre2jit.html | 506 +
doc/html/pcre2limits.html | 108 +
doc/html/pcre2matching.html | 262 +
doc/html/pcre2partial.html | 422 +
doc/html/pcre2pattern.html | 4192 +++
doc/html/pcre2perform.html | 280 +
doc/html/pcre2posix.html | 379 +
doc/html/pcre2sample.html | 111 +
doc/html/pcre2serialize.html | 212 +
doc/html/pcre2syntax.html | 781 +
doc/html/pcre2test.html | 2314 ++
doc/html/pcre2unicode.html | 556 +
doc/pcre2-config.1 | 87 +
doc/pcre2-config.txt | 84 +
doc/pcre2.3 | 211 +
doc/pcre2.txt | 12949 +++++++++
doc/pcre2_callout_enumerate.3 | 51 +
doc/pcre2_code_copy.3 | 31 +
doc/pcre2_code_copy_with_tables.3 | 32 +
doc/pcre2_code_free.3 | 30 +
doc/pcre2_compile.3 | 107 +
doc/pcre2_compile_context_copy.3 | 29 +
doc/pcre2_compile_context_create.3 | 30 +
doc/pcre2_compile_context_free.3 | 29 +
doc/pcre2_config.3 | 78 +
doc/pcre2_convert_context_copy.3 | 26 +
doc/pcre2_convert_context_create.3 | 27 +
doc/pcre2_convert_context_free.3 | 26 +
doc/pcre2_converted_pattern_free.3 | 26 +
doc/pcre2_dfa_match.3 | 86 +
doc/pcre2_general_context_copy.3 | 30 +
doc/pcre2_general_context_create.3 | 32 +
doc/pcre2_general_context_free.3 | 28 +
doc/pcre2_get_error_message.3 | 39 +
doc/pcre2_get_mark.3 | 34 +
doc/pcre2_get_match_data_heapframes_size.3 | 28 +
doc/pcre2_get_match_data_size.3 | 27 +
doc/pcre2_get_ovector_count.3 | 27 +
doc/pcre2_get_ovector_pointer.3 | 28 +
doc/pcre2_get_startchar.3 | 32 +
doc/pcre2_jit_compile.3 | 61 +
doc/pcre2_jit_free_unused_memory.3 | 31 +
doc/pcre2_jit_match.3 | 58 +
doc/pcre2_jit_stack_assign.3 | 59 +
doc/pcre2_jit_stack_create.3 | 40 +
doc/pcre2_jit_stack_free.3 | 33 +
doc/pcre2_maketables.3 | 37 +
doc/pcre2_maketables_free.3 | 31 +
doc/pcre2_match.3 | 86 +
doc/pcre2_match_context_copy.3 | 29 +
doc/pcre2_match_context_create.3 | 30 +
doc/pcre2_match_context_free.3 | 29 +
doc/pcre2_match_data_create.3 | 37 +
doc/pcre2_match_data_create_from_pattern.3 | 40 +
doc/pcre2_match_data_free.3 | 35 +
doc/pcre2_next_match.3 | 41 +
doc/pcre2_pattern_convert.3 | 55 +
doc/pcre2_pattern_info.3 | 108 +
doc/pcre2_serialize_decode.3 | 53 +
doc/pcre2_serialize_encode.3 | 54 +
doc/pcre2_serialize_free.3 | 29 +
doc/pcre2_serialize_get_number_of_codes.3 | 37 +
doc/pcre2_set_bsr.3 | 30 +
doc/pcre2_set_callout.3 | 31 +
doc/pcre2_set_character_tables.3 | 35 +
doc/pcre2_set_compile_extra_options.3 | 59 +
doc/pcre2_set_compile_recursion_guard.3 | 34 +
doc/pcre2_set_depth_limit.3 | 28 +
doc/pcre2_set_glob_escape.3 | 29 +
doc/pcre2_set_glob_separator.3 | 28 +
doc/pcre2_set_heap_limit.3 | 28 +
doc/pcre2_set_match_limit.3 | 28 +
doc/pcre2_set_max_pattern_compiled_length.3 | 32 +
doc/pcre2_set_max_pattern_length.3 | 31 +
doc/pcre2_set_max_varlookbehind.3 | 30 +
doc/pcre2_set_newline.3 | 39 +
doc/pcre2_set_offset_limit.3 | 28 +
doc/pcre2_set_optimize.3 | 42 +
doc/pcre2_set_parens_nest_limit.3 | 28 +
doc/pcre2_set_recursion_limit.3 | 28 +
doc/pcre2_set_recursion_memory_management.3 | 30 +
doc/pcre2_set_substitute_callout.3 | 31 +
doc/pcre2_set_substitute_case_callout.3 | 33 +
doc/pcre2_substitute.3 | 111 +
doc/pcre2_substring_copy_byname.3 | 46 +
doc/pcre2_substring_copy_bynumber.3 | 44 +
doc/pcre2_substring_free.3 | 29 +
doc/pcre2_substring_get_byname.3 | 48 +
doc/pcre2_substring_get_bynumber.3 | 45 +
doc/pcre2_substring_length_byname.3 | 36 +
doc/pcre2_substring_length_bynumber.3 | 36 +
doc/pcre2_substring_list_free.3 | 29 +
doc/pcre2_substring_list_get.3 | 44 +
doc/pcre2_substring_nametable_scan.3 | 41 +
doc/pcre2_substring_number_from_name.3 | 38 +
doc/pcre2api.3 | 4627 +++
doc/pcre2build.3 | 682 +
doc/pcre2callout.3 | 456 +
doc/pcre2compat.3 | 260 +
doc/pcre2convert.3 | 164 +
doc/pcre2demo.3 | 475 +
doc/pcre2grep.1 | 1027 +
doc/pcre2grep.txt | 1106 +
doc/pcre2jit.3 | 490 +
doc/pcre2limits.3 | 86 +
doc/pcre2matching.3 | 228 +
doc/pcre2partial.3 | 386 +
doc/pcre2pattern.3 | 4235 +++
doc/pcre2perform.3 | 260 +
doc/pcre2posix.3 | 348 +
doc/pcre2sample.3 | 100 +
doc/pcre2serialize.3 | 198 +
doc/pcre2syntax.3 | 762 +
doc/pcre2test.1 | 2282 ++
doc/pcre2test.txt | 2107 ++
doc/pcre2unicode.3 | 514 +
install-sh | 541 +
libpcre2-16.pc.in | 14 +
libpcre2-32.pc.in | 14 +
libpcre2-8.pc.in | 14 +
libpcre2-posix.pc.in | 14 +
ltmain.sh | 11436 ++++++++
m4/ax_pthread.m4 | 522 +
m4/libtool.m4 | 8427 ++++++
m4/ltoptions.m4 | 437 +
m4/ltsugar.m4 | 124 +
m4/ltversion.m4 | 24 +
m4/lt~obsolete.m4 | 99 +
m4/pcre2_check_vscript.m4 | 118 +
m4/pcre2_visibility.m4 | 85 +
m4/pcre2_zos.m4 | 50 +
missing | 215 +
patches/pcre2-10.37-Remove-real-POSIX.patch | 351 +
.../pcre2-10.39-Fix-incorrect-detection.patch | 73 +
patches/pcre2-10.40-A-Fixed-a-unicode.patch | 65 +
...re2-10.40-B-Fixed-an-issue-affecting.patch | 648 +
...pcre2-10.43-Avoid-LIMIT_HEAP-integer.patch | 128 +
.../pcre2-10.43-Fix-heapframe-overflow.patch | 167 +
.../pcre2-10.44-Fix-incorrect-compiling.patch | 74 +
patches/pcre2-10.44-Fix-locking-region.patch | 33 +
...2-10.45-Memory-reports-only-compiled.patch | 5209 ++++
patches/pcre2-10.47-Fix-for-callback.patch | 153 +
....48-Check-JIT-mode-before-validation.patch | 382 +
...e2-10.48-Fix-DFA-workspace-overflows.patch | 149 +
patches/pcre2-10.48-Fix-JIT-STR_END.patch | 34 +
...e2-10.48-Fix-JIT-match-context-reuse.patch | 480 +
...re2-10.48-Fix-allocation-byte-sizing.patch | 54 +
...2-10.48-Fix-character-list-generator.patch | 113 +
...10.48-Fix-compiler-integer-overflows.patch | 200 +
...0.48-Fix-invalid-UTF-backwards-scans.patch | 212 +
...0.48-Fix-repeated-substitute-escapes.patch | 75 +
...2-10.48-Fix-scan-prefix-repeat-reset.patch | 30 +
...-Keep-escape-error-offset-in-pattern.patch | 92 +
...e2-10.48-Write-serialization-padding.patch | 80 +
pcre2-config.in | 131 +
perltest.sh | 512 +
src/config-cmake.h.in | 56 +
src/config.h.generic | 497 +
src/config.h.in | 475 +
src/libpcre2-16.sym.in | 87 +
src/libpcre2-32.sym.in | 87 +
src/libpcre2-8.sym.in | 87 +
src/libpcre2-posix.sym.in | 12 +
src/pcre2.h.generic | 1080 +
src/pcre2.h.in | 1080 +
src/pcre2_auto_possess.c | 1416 +
src/pcre2_chartables.c.dist | 192 +
src/pcre2_chartables.c.ebcdic-1047-nl15 | 196 +
src/pcre2_chartables.c.ebcdic-1047-nl25 | 196 +
src/pcre2_chkdint.c | 94 +
src/pcre2_compile.c | 11412 ++++++++
src/pcre2_compile.h | 356 +
src/pcre2_compile_cgroup.c | 632 +
src/pcre2_compile_class.c | 2779 ++
src/pcre2_config.c | 250 +
src/pcre2_context.c | 557 +
src/pcre2_convert.c | 1263 +
src/pcre2_dfa_match.c | 4164 +++
src/pcre2_dftables.c | 326 +
src/pcre2_error.c | 386 +
src/pcre2_extuni.c | 159 +
src/pcre2_find_bracket.c | 217 +
src/pcre2_fuzzsupport.c | 844 +
src/pcre2_internal.h | 2360 ++
src/pcre2_intmodedep.h | 1116 +
src/pcre2_jit_char_inc.h | 2280 ++
src/pcre2_jit_compile.c | 14425 ++++++++++
src/pcre2_jit_match_inc.h | 213 +
src/pcre2_jit_misc_inc.h | 260 +
src/pcre2_jit_simd_inc.h | 2506 ++
src/pcre2_jit_test.c | 2548 ++
src/pcre2_maketables.c | 177 +
src/pcre2_match.c | 8231 ++++++
src/pcre2_match_data.c | 184 +
src/pcre2_match_next.c | 171 +
src/pcre2_newline.c | 239 +
src/pcre2_ord2utf.c | 118 +
src/pcre2_pattern_info.c | 430 +
src/pcre2_printint_inc.h | 1098 +
src/pcre2_script_run.c | 343 +
src/pcre2_serialize.c | 295 +
src/pcre2_string_utils.c | 199 +
src/pcre2_study.c | 2086 ++
src/pcre2_substitute.c | 1795 ++
src/pcre2_substring.c | 554 +
src/pcre2_tables.c | 310 +
src/pcre2_ucd.c | 5823 ++++
src/pcre2_ucp.h | 413 +
src/pcre2_ucptables_inc.h | 1621 ++
src/pcre2_util.h | 179 +
src/pcre2_valid_utf.c | 397 +
src/pcre2_xclass.c | 547 +
src/pcre2demo.c | 446 +
src/pcre2grep.c | 4774 ++++
src/pcre2posix.c | 438 +
src/pcre2posix.h | 184 +
src/pcre2posix_test.c | 239 +
src/pcre2test.c | 4468 +++
src/pcre2test_inc.h | 6597 +++++
test-driver | 153 +
testdata/grepbinary | Bin 0 -> 45 bytes
testdata/grepfilelist | 3 +
testdata/grepinput | 643 +
testdata/grepinput3 | 15 +
testdata/grepinput8 | 17 +
testdata/grepinputBad8 | 1 +
testdata/grepinputBad8_Trail | 1 +
testdata/grepinputC.bz2 | Bin 0 -> 315 bytes
testdata/grepinputC.gz | Bin 0 -> 313 bytes
testdata/grepinputM | 17 +
testdata/grepinputUN | 2 +
testdata/grepinputv | 10 +
testdata/grepinputx | 43 +
testdata/greplist | 7 +
testdata/grepnot.bz2 | 43 +
testdata/grepoutput | 1350 +
testdata/grepoutput8 | 174 +
testdata/grepoutputC | 74 +
testdata/grepoutputCN | 50 +
testdata/grepoutputCNU | 22 +
testdata/grepoutputCU | 34 +
testdata/grepoutputCbz2 | 6 +
testdata/grepoutputCgz | 3 +
testdata/grepoutputN | 42 +
testdata/grepoutputUN | 4 +
testdata/greppatN4 | 2 +
testdata/testbtables | Bin 0 -> 1088 bytes
testdata/testinput1 | 7196 +++++
testdata/testinput10 | 744 +
testdata/testinput11 | 504 +
testdata/testinput12 | 746 +
testdata/testinput13 | 22 +
testdata/testinput14 | 108 +
testdata/testinput15 | 257 +
testdata/testinput16 | 9 +
testdata/testinput17 | 366 +
testdata/testinput18 | 169 +
testdata/testinput19 | 27 +
testdata/testinput2 | 8387 ++++++
testdata/testinput20 | 108 +
testdata/testinput21 | 18 +
testdata/testinput22 | 107 +
testdata/testinput23 | 9 +
testdata/testinput24 | 448 +
testdata/testinput25 | 22 +
testdata/testinput26 | 2754 ++
testdata/testinput27 | 3309 +++
testdata/testinput28 | 153 +
testdata/testinput29 | 9 +
testdata/testinput3 | 113 +
testdata/testinput4 | 3119 ++
testdata/testinput5 | 3624 +++
testdata/testinput6 | 5273 ++++
testdata/testinput7 | 2745 ++
testdata/testinput8 | 189 +
testdata/testinput9 | 300 +
testdata/testinputheap | 35 +
testdata/testoutput1 | 11277 ++++++++
testdata/testoutput10 | 2083 ++
testdata/testoutput11-16 | 881 +
testdata/testoutput11-32 | 1014 +
testdata/testoutput12-16 | 2107 ++
testdata/testoutput12-32 | 2092 ++
testdata/testoutput13 | 27 +
testdata/testoutput14-16 | 167 +
testdata/testoutput14-32 | 159 +
testdata/testoutput14-8 | 175 +
testdata/testoutput15 | 548 +
testdata/testoutput16 | 18 +
testdata/testoutput17 | 646 +
testdata/testoutput18 | 271 +
testdata/testoutput19 | 33 +
testdata/testoutput2 | 23781 ++++++++++++++++
testdata/testoutput20 | 161 +
testdata/testoutput21 | 99 +
testdata/testoutput22-16 | 183 +
testdata/testoutput22-32 | 180 +
testdata/testoutput22-8 | 185 +
testdata/testoutput23 | 13 +
testdata/testoutput24 | 689 +
testdata/testoutput25 | 25 +
testdata/testoutput26 | 3515 +++
testdata/testoutput27 | 4227 +++
testdata/testoutput28 | 217 +
testdata/testoutput29 | 12 +
testdata/testoutput3 | 182 +
testdata/testoutput3A | 182 +
testdata/testoutput3B | 182 +
testdata/testoutput4 | 4991 ++++
testdata/testoutput5 | 8345 ++++++
testdata/testoutput6 | 8248 ++++++
testdata/testoutput7 | 4552 +++
testdata/testoutput8-16-2 | 1025 +
testdata/testoutput8-16-4 | 1022 +
testdata/testoutput8-32-4 | 1022 +
testdata/testoutput8-8-2 | 1025 +
testdata/testoutput8-8-3 | 1022 +
testdata/testoutput8-8-4 | 1022 +
testdata/testoutput9 | 436 +
testdata/testoutputheap-16 | 88 +
testdata/testoutputheap-32 | 88 +
testdata/testoutputheap-8 | 88 +
testdata/valgrind-jit.supp | 15 +
testdata/wintestinput3 | 113 +
testdata/wintestoutput3 | 184 +
vms/configure.com | 1133 +
vms/openvms_readme.txt | 20 +
vms/pcre2.h_patch | 12 +
vms/stdint.h | 9 +
492 files changed, 429584 insertions(+)
create mode 100644 AUTHORS.md
create mode 100644 BUILD.bazel
create mode 100644 CMakeLists.txt
create mode 100644 COPYING
create mode 100644 ChangeLog
create mode 100644 HACKING
create mode 100644 INSTALL
create mode 100644 LICENCE.md
create mode 100644 MODULE.bazel
create mode 100644 Makefile.am
create mode 100644 Makefile.in
create mode 100644 NEWS
create mode 100644 NON-AUTOTOOLS-BUILD
create mode 100644 README
create mode 100755 RunGrepTest
create mode 100644 RunGrepTest.bat
create mode 100755 RunTest
create mode 100644 RunTest.bat
create mode 100644 SECURITY.md
create mode 100644 SUPPORT-LIFECYCLE.md
create mode 100644 aclocal.m4
create mode 100755 ar-lib
create mode 100644 build.zig
create mode 100644 build.zig.zon
create mode 100644 cmake/COPYING-CMAKE-SCRIPTS
create mode 100644 cmake/FindEditline.cmake
create mode 100644 cmake/FindReadline.cmake
create mode 100644 cmake/PCRE2CheckVscript.cmake
create mode 100644 cmake/PCRE2UseSystemExtensions.cmake
create mode 100644 cmake/PCRE2WarningAsError.cmake
create mode 100644 cmake/pcre2-config.cmake.in
create mode 100755 compile
create mode 100755 config.guess
create mode 100755 config.sub
create mode 100755 configure
create mode 100644 configure.ac
create mode 100755 depcomp
create mode 100644 deps/sljit/LICENSE
create mode 100644 deps/sljit/README.md
create mode 100644 deps/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c
create mode 100644 deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c
create mode 100644 deps/sljit/sljit_src/allocator_src/sljitExecAllocatorFreeBSD.c
create mode 100644 deps/sljit/sljit_src/allocator_src/sljitExecAllocatorPosix.c
create mode 100644 deps/sljit/sljit_src/allocator_src/sljitExecAllocatorWindows.c
create mode 100644 deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorNetBSD.c
create mode 100644 deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorPosix.c
create mode 100644 deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorPosix.c
create mode 100644 deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorWindows.c
create mode 100644 deps/sljit/sljit_src/sljitConfig.h
create mode 100644 deps/sljit/sljit_src/sljitConfigCPU.h
create mode 100644 deps/sljit/sljit_src/sljitConfigInternal.h
create mode 100644 deps/sljit/sljit_src/sljitLir.c
create mode 100644 deps/sljit/sljit_src/sljitLir.h
create mode 100644 deps/sljit/sljit_src/sljitNativeARM_32.c
create mode 100644 deps/sljit/sljit_src/sljitNativeARM_64.c
create mode 100644 deps/sljit/sljit_src/sljitNativeARM_T2_32.c
create mode 100644 deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c
create mode 100644 deps/sljit/sljit_src/sljitNativeMIPS_32.c
create mode 100644 deps/sljit/sljit_src/sljitNativeMIPS_64.c
create mode 100644 deps/sljit/sljit_src/sljitNativeMIPS_common.c
create mode 100644 deps/sljit/sljit_src/sljitNativePPC_32.c
create mode 100644 deps/sljit/sljit_src/sljitNativePPC_64.c
create mode 100644 deps/sljit/sljit_src/sljitNativePPC_common.c
create mode 100644 deps/sljit/sljit_src/sljitNativeRISCV_32.c
create mode 100644 deps/sljit/sljit_src/sljitNativeRISCV_64.c
create mode 100644 deps/sljit/sljit_src/sljitNativeRISCV_common.c
create mode 100644 deps/sljit/sljit_src/sljitNativeS390X.c
create mode 100644 deps/sljit/sljit_src/sljitNativeX86_32.c
create mode 100644 deps/sljit/sljit_src/sljitNativeX86_64.c
create mode 100644 deps/sljit/sljit_src/sljitNativeX86_common.c
create mode 100644 deps/sljit/sljit_src/sljitSerialize.c
create mode 100644 deps/sljit/sljit_src/sljitUtils.c
create mode 100644 doc/html/NON-AUTOTOOLS-BUILD.txt
create mode 100644 doc/html/README.txt
create mode 100644 doc/html/index.html
create mode 100644 doc/html/pcre2-config.html
create mode 100644 doc/html/pcre2.html
create mode 100644 doc/html/pcre2_callout_enumerate.html
create mode 100644 doc/html/pcre2_code_copy.html
create mode 100644 doc/html/pcre2_code_copy_with_tables.html
create mode 100644 doc/html/pcre2_code_free.html
create mode 100644 doc/html/pcre2_compile.html
create mode 100644 doc/html/pcre2_compile_context_copy.html
create mode 100644 doc/html/pcre2_compile_context_create.html
create mode 100644 doc/html/pcre2_compile_context_free.html
create mode 100644 doc/html/pcre2_config.html
create mode 100644 doc/html/pcre2_convert_context_copy.html
create mode 100644 doc/html/pcre2_convert_context_create.html
create mode 100644 doc/html/pcre2_convert_context_free.html
create mode 100644 doc/html/pcre2_converted_pattern_free.html
create mode 100644 doc/html/pcre2_dfa_match.html
create mode 100644 doc/html/pcre2_general_context_copy.html
create mode 100644 doc/html/pcre2_general_context_create.html
create mode 100644 doc/html/pcre2_general_context_free.html
create mode 100644 doc/html/pcre2_get_error_message.html
create mode 100644 doc/html/pcre2_get_mark.html
create mode 100644 doc/html/pcre2_get_match_data_heapframes_size.html
create mode 100644 doc/html/pcre2_get_match_data_size.html
create mode 100644 doc/html/pcre2_get_ovector_count.html
create mode 100644 doc/html/pcre2_get_ovector_pointer.html
create mode 100644 doc/html/pcre2_get_startchar.html
create mode 100644 doc/html/pcre2_jit_compile.html
create mode 100644 doc/html/pcre2_jit_free_unused_memory.html
create mode 100644 doc/html/pcre2_jit_match.html
create mode 100644 doc/html/pcre2_jit_stack_assign.html
create mode 100644 doc/html/pcre2_jit_stack_create.html
create mode 100644 doc/html/pcre2_jit_stack_free.html
create mode 100644 doc/html/pcre2_maketables.html
create mode 100644 doc/html/pcre2_maketables_free.html
create mode 100644 doc/html/pcre2_match.html
create mode 100644 doc/html/pcre2_match_context_copy.html
create mode 100644 doc/html/pcre2_match_context_create.html
create mode 100644 doc/html/pcre2_match_context_free.html
create mode 100644 doc/html/pcre2_match_data_create.html
create mode 100644 doc/html/pcre2_match_data_create_from_pattern.html
create mode 100644 doc/html/pcre2_match_data_free.html
create mode 100644 doc/html/pcre2_next_match.html
create mode 100644 doc/html/pcre2_pattern_convert.html
create mode 100644 doc/html/pcre2_pattern_info.html
create mode 100644 doc/html/pcre2_serialize_decode.html
create mode 100644 doc/html/pcre2_serialize_encode.html
create mode 100644 doc/html/pcre2_serialize_free.html
create mode 100644 doc/html/pcre2_serialize_get_number_of_codes.html
create mode 100644 doc/html/pcre2_set_bsr.html
create mode 100644 doc/html/pcre2_set_callout.html
create mode 100644 doc/html/pcre2_set_character_tables.html
create mode 100644 doc/html/pcre2_set_compile_extra_options.html
create mode 100644 doc/html/pcre2_set_compile_recursion_guard.html
create mode 100644 doc/html/pcre2_set_depth_limit.html
create mode 100644 doc/html/pcre2_set_glob_escape.html
create mode 100644 doc/html/pcre2_set_glob_separator.html
create mode 100644 doc/html/pcre2_set_heap_limit.html
create mode 100644 doc/html/pcre2_set_match_limit.html
create mode 100644 doc/html/pcre2_set_max_pattern_compiled_length.html
create mode 100644 doc/html/pcre2_set_max_pattern_length.html
create mode 100644 doc/html/pcre2_set_max_varlookbehind.html
create mode 100644 doc/html/pcre2_set_newline.html
create mode 100644 doc/html/pcre2_set_offset_limit.html
create mode 100644 doc/html/pcre2_set_optimize.html
create mode 100644 doc/html/pcre2_set_parens_nest_limit.html
create mode 100644 doc/html/pcre2_set_recursion_limit.html
create mode 100644 doc/html/pcre2_set_recursion_memory_management.html
create mode 100644 doc/html/pcre2_set_substitute_callout.html
create mode 100644 doc/html/pcre2_set_substitute_case_callout.html
create mode 100644 doc/html/pcre2_substitute.html
create mode 100644 doc/html/pcre2_substring_copy_byname.html
create mode 100644 doc/html/pcre2_substring_copy_bynumber.html
create mode 100644 doc/html/pcre2_substring_free.html
create mode 100644 doc/html/pcre2_substring_get_byname.html
create mode 100644 doc/html/pcre2_substring_get_bynumber.html
create mode 100644 doc/html/pcre2_substring_length_byname.html
create mode 100644 doc/html/pcre2_substring_length_bynumber.html
create mode 100644 doc/html/pcre2_substring_list_free.html
create mode 100644 doc/html/pcre2_substring_list_get.html
create mode 100644 doc/html/pcre2_substring_nametable_scan.html
create mode 100644 doc/html/pcre2_substring_number_from_name.html
create mode 100644 doc/html/pcre2api.html
create mode 100644 doc/html/pcre2build.html
create mode 100644 doc/html/pcre2callout.html
create mode 100644 doc/html/pcre2compat.html
create mode 100644 doc/html/pcre2convert.html
create mode 100644 doc/html/pcre2demo.html
create mode 100644 doc/html/pcre2grep.html
create mode 100644 doc/html/pcre2jit.html
create mode 100644 doc/html/pcre2limits.html
create mode 100644 doc/html/pcre2matching.html
create mode 100644 doc/html/pcre2partial.html
create mode 100644 doc/html/pcre2pattern.html
create mode 100644 doc/html/pcre2perform.html
create mode 100644 doc/html/pcre2posix.html
create mode 100644 doc/html/pcre2sample.html
create mode 100644 doc/html/pcre2serialize.html
create mode 100644 doc/html/pcre2syntax.html
create mode 100644 doc/html/pcre2test.html
create mode 100644 doc/html/pcre2unicode.html
create mode 100644 doc/pcre2-config.1
create mode 100644 doc/pcre2-config.txt
create mode 100644 doc/pcre2.3
create mode 100644 doc/pcre2.txt
create mode 100644 doc/pcre2_callout_enumerate.3
create mode 100644 doc/pcre2_code_copy.3
create mode 100644 doc/pcre2_code_copy_with_tables.3
create mode 100644 doc/pcre2_code_free.3
create mode 100644 doc/pcre2_compile.3
create mode 100644 doc/pcre2_compile_context_copy.3
create mode 100644 doc/pcre2_compile_context_create.3
create mode 100644 doc/pcre2_compile_context_free.3
create mode 100644 doc/pcre2_config.3
create mode 100644 doc/pcre2_convert_context_copy.3
create mode 100644 doc/pcre2_convert_context_create.3
create mode 100644 doc/pcre2_convert_context_free.3
create mode 100644 doc/pcre2_converted_pattern_free.3
create mode 100644 doc/pcre2_dfa_match.3
create mode 100644 doc/pcre2_general_context_copy.3
create mode 100644 doc/pcre2_general_context_create.3
create mode 100644 doc/pcre2_general_context_free.3
create mode 100644 doc/pcre2_get_error_message.3
create mode 100644 doc/pcre2_get_mark.3
create mode 100644 doc/pcre2_get_match_data_heapframes_size.3
create mode 100644 doc/pcre2_get_match_data_size.3
create mode 100644 doc/pcre2_get_ovector_count.3
create mode 100644 doc/pcre2_get_ovector_pointer.3
create mode 100644 doc/pcre2_get_startchar.3
create mode 100644 doc/pcre2_jit_compile.3
create mode 100644 doc/pcre2_jit_free_unused_memory.3
create mode 100644 doc/pcre2_jit_match.3
create mode 100644 doc/pcre2_jit_stack_assign.3
create mode 100644 doc/pcre2_jit_stack_create.3
create mode 100644 doc/pcre2_jit_stack_free.3
create mode 100644 doc/pcre2_maketables.3
create mode 100644 doc/pcre2_maketables_free.3
create mode 100644 doc/pcre2_match.3
create mode 100644 doc/pcre2_match_context_copy.3
create mode 100644 doc/pcre2_match_context_create.3
create mode 100644 doc/pcre2_match_context_free.3
create mode 100644 doc/pcre2_match_data_create.3
create mode 100644 doc/pcre2_match_data_create_from_pattern.3
create mode 100644 doc/pcre2_match_data_free.3
create mode 100644 doc/pcre2_next_match.3
create mode 100644 doc/pcre2_pattern_convert.3
create mode 100644 doc/pcre2_pattern_info.3
create mode 100644 doc/pcre2_serialize_decode.3
create mode 100644 doc/pcre2_serialize_encode.3
create mode 100644 doc/pcre2_serialize_free.3
create mode 100644 doc/pcre2_serialize_get_number_of_codes.3
create mode 100644 doc/pcre2_set_bsr.3
create mode 100644 doc/pcre2_set_callout.3
create mode 100644 doc/pcre2_set_character_tables.3
create mode 100644 doc/pcre2_set_compile_extra_options.3
create mode 100644 doc/pcre2_set_compile_recursion_guard.3
create mode 100644 doc/pcre2_set_depth_limit.3
create mode 100644 doc/pcre2_set_glob_escape.3
create mode 100644 doc/pcre2_set_glob_separator.3
create mode 100644 doc/pcre2_set_heap_limit.3
create mode 100644 doc/pcre2_set_match_limit.3
create mode 100644 doc/pcre2_set_max_pattern_compiled_length.3
create mode 100644 doc/pcre2_set_max_pattern_length.3
create mode 100644 doc/pcre2_set_max_varlookbehind.3
create mode 100644 doc/pcre2_set_newline.3
create mode 100644 doc/pcre2_set_offset_limit.3
create mode 100644 doc/pcre2_set_optimize.3
create mode 100644 doc/pcre2_set_parens_nest_limit.3
create mode 100644 doc/pcre2_set_recursion_limit.3
create mode 100644 doc/pcre2_set_recursion_memory_management.3
create mode 100644 doc/pcre2_set_substitute_callout.3
create mode 100644 doc/pcre2_set_substitute_case_callout.3
create mode 100644 doc/pcre2_substitute.3
create mode 100644 doc/pcre2_substring_copy_byname.3
create mode 100644 doc/pcre2_substring_copy_bynumber.3
create mode 100644 doc/pcre2_substring_free.3
create mode 100644 doc/pcre2_substring_get_byname.3
create mode 100644 doc/pcre2_substring_get_bynumber.3
create mode 100644 doc/pcre2_substring_length_byname.3
create mode 100644 doc/pcre2_substring_length_bynumber.3
create mode 100644 doc/pcre2_substring_list_free.3
create mode 100644 doc/pcre2_substring_list_get.3
create mode 100644 doc/pcre2_substring_nametable_scan.3
create mode 100644 doc/pcre2_substring_number_from_name.3
create mode 100644 doc/pcre2api.3
create mode 100644 doc/pcre2build.3
create mode 100644 doc/pcre2callout.3
create mode 100644 doc/pcre2compat.3
create mode 100644 doc/pcre2convert.3
create mode 100644 doc/pcre2demo.3
create mode 100644 doc/pcre2grep.1
create mode 100644 doc/pcre2grep.txt
create mode 100644 doc/pcre2jit.3
create mode 100644 doc/pcre2limits.3
create mode 100644 doc/pcre2matching.3
create mode 100644 doc/pcre2partial.3
create mode 100644 doc/pcre2pattern.3
create mode 100644 doc/pcre2perform.3
create mode 100644 doc/pcre2posix.3
create mode 100644 doc/pcre2sample.3
create mode 100644 doc/pcre2serialize.3
create mode 100644 doc/pcre2syntax.3
create mode 100644 doc/pcre2test.1
create mode 100644 doc/pcre2test.txt
create mode 100644 doc/pcre2unicode.3
create mode 100755 install-sh
create mode 100644 libpcre2-16.pc.in
create mode 100644 libpcre2-32.pc.in
create mode 100644 libpcre2-8.pc.in
create mode 100644 libpcre2-posix.pc.in
create mode 100755 ltmain.sh
create mode 100644 m4/ax_pthread.m4
create mode 100644 m4/libtool.m4
create mode 100644 m4/ltoptions.m4
create mode 100644 m4/ltsugar.m4
create mode 100644 m4/ltversion.m4
create mode 100644 m4/lt~obsolete.m4
create mode 100644 m4/pcre2_check_vscript.m4
create mode 100644 m4/pcre2_visibility.m4
create mode 100644 m4/pcre2_zos.m4
create mode 100755 missing
create mode 100644 patches/pcre2-10.37-Remove-real-POSIX.patch
create mode 100644 patches/pcre2-10.39-Fix-incorrect-detection.patch
create mode 100644 patches/pcre2-10.40-A-Fixed-a-unicode.patch
create mode 100644 patches/pcre2-10.40-B-Fixed-an-issue-affecting.patch
create mode 100644 patches/pcre2-10.43-Avoid-LIMIT_HEAP-integer.patch
create mode 100644 patches/pcre2-10.43-Fix-heapframe-overflow.patch
create mode 100644 patches/pcre2-10.44-Fix-incorrect-compiling.patch
create mode 100644 patches/pcre2-10.44-Fix-locking-region.patch
create mode 100644 patches/pcre2-10.45-Memory-reports-only-compiled.patch
create mode 100644 patches/pcre2-10.47-Fix-for-callback.patch
create mode 100644 patches/pcre2-10.48-Check-JIT-mode-before-validation.patch
create mode 100644 patches/pcre2-10.48-Fix-DFA-workspace-overflows.patch
create mode 100644 patches/pcre2-10.48-Fix-JIT-STR_END.patch
create mode 100644 patches/pcre2-10.48-Fix-JIT-match-context-reuse.patch
create mode 100644 patches/pcre2-10.48-Fix-allocation-byte-sizing.patch
create mode 100644 patches/pcre2-10.48-Fix-character-list-generator.patch
create mode 100644 patches/pcre2-10.48-Fix-compiler-integer-overflows.patch
create mode 100644 patches/pcre2-10.48-Fix-invalid-UTF-backwards-scans.patch
create mode 100644 patches/pcre2-10.48-Fix-repeated-substitute-escapes.patch
create mode 100644 patches/pcre2-10.48-Fix-scan-prefix-repeat-reset.patch
create mode 100644 patches/pcre2-10.48-Keep-escape-error-offset-in-pattern.patch
create mode 100644 patches/pcre2-10.48-Write-serialization-padding.patch
create mode 100644 pcre2-config.in
create mode 100755 perltest.sh
create mode 100644 src/config-cmake.h.in
create mode 100644 src/config.h.generic
create mode 100644 src/config.h.in
create mode 100644 src/libpcre2-16.sym.in
create mode 100644 src/libpcre2-32.sym.in
create mode 100644 src/libpcre2-8.sym.in
create mode 100644 src/libpcre2-posix.sym.in
create mode 100644 src/pcre2.h.generic
create mode 100644 src/pcre2.h.in
create mode 100644 src/pcre2_auto_possess.c
create mode 100644 src/pcre2_chartables.c.dist
create mode 100644 src/pcre2_chartables.c.ebcdic-1047-nl15
create mode 100644 src/pcre2_chartables.c.ebcdic-1047-nl25
create mode 100644 src/pcre2_chkdint.c
create mode 100644 src/pcre2_compile.c
create mode 100644 src/pcre2_compile.h
create mode 100644 src/pcre2_compile_cgroup.c
create mode 100644 src/pcre2_compile_class.c
create mode 100644 src/pcre2_config.c
create mode 100644 src/pcre2_context.c
create mode 100644 src/pcre2_convert.c
create mode 100644 src/pcre2_dfa_match.c
create mode 100644 src/pcre2_dftables.c
create mode 100644 src/pcre2_error.c
create mode 100644 src/pcre2_extuni.c
create mode 100644 src/pcre2_find_bracket.c
create mode 100644 src/pcre2_fuzzsupport.c
create mode 100644 src/pcre2_internal.h
create mode 100644 src/pcre2_intmodedep.h
create mode 100644 src/pcre2_jit_char_inc.h
create mode 100644 src/pcre2_jit_compile.c
create mode 100644 src/pcre2_jit_match_inc.h
create mode 100644 src/pcre2_jit_misc_inc.h
create mode 100644 src/pcre2_jit_simd_inc.h
create mode 100644 src/pcre2_jit_test.c
create mode 100644 src/pcre2_maketables.c
create mode 100644 src/pcre2_match.c
create mode 100644 src/pcre2_match_data.c
create mode 100644 src/pcre2_match_next.c
create mode 100644 src/pcre2_newline.c
create mode 100644 src/pcre2_ord2utf.c
create mode 100644 src/pcre2_pattern_info.c
create mode 100644 src/pcre2_printint_inc.h
create mode 100644 src/pcre2_script_run.c
create mode 100644 src/pcre2_serialize.c
create mode 100644 src/pcre2_string_utils.c
create mode 100644 src/pcre2_study.c
create mode 100644 src/pcre2_substitute.c
create mode 100644 src/pcre2_substring.c
create mode 100644 src/pcre2_tables.c
create mode 100644 src/pcre2_ucd.c
create mode 100644 src/pcre2_ucp.h
create mode 100644 src/pcre2_ucptables_inc.h
create mode 100644 src/pcre2_util.h
create mode 100644 src/pcre2_valid_utf.c
create mode 100644 src/pcre2_xclass.c
create mode 100644 src/pcre2demo.c
create mode 100644 src/pcre2grep.c
create mode 100644 src/pcre2posix.c
create mode 100644 src/pcre2posix.h
create mode 100644 src/pcre2posix_test.c
create mode 100644 src/pcre2test.c
create mode 100644 src/pcre2test_inc.h
create mode 100755 test-driver
create mode 100644 testdata/grepbinary
create mode 100644 testdata/grepfilelist
create mode 100644 testdata/grepinput
create mode 100644 testdata/grepinput3
create mode 100644 testdata/grepinput8
create mode 100644 testdata/grepinputBad8
create mode 100644 testdata/grepinputBad8_Trail
create mode 100644 testdata/grepinputC.bz2
create mode 100644 testdata/grepinputC.gz
create mode 100644 testdata/grepinputM
create mode 100644 testdata/grepinputUN
create mode 100644 testdata/grepinputv
create mode 100644 testdata/grepinputx
create mode 100644 testdata/greplist
create mode 100644 testdata/grepnot.bz2
create mode 100644 testdata/grepoutput
create mode 100644 testdata/grepoutput8
create mode 100644 testdata/grepoutputC
create mode 100644 testdata/grepoutputCN
create mode 100644 testdata/grepoutputCNU
create mode 100644 testdata/grepoutputCU
create mode 100644 testdata/grepoutputCbz2
create mode 100644 testdata/grepoutputCgz
create mode 100644 testdata/grepoutputN
create mode 100644 testdata/grepoutputUN
create mode 100644 testdata/greppatN4
create mode 100644 testdata/testbtables
create mode 100644 testdata/testinput1
create mode 100644 testdata/testinput10
create mode 100644 testdata/testinput11
create mode 100644 testdata/testinput12
create mode 100644 testdata/testinput13
create mode 100644 testdata/testinput14
create mode 100644 testdata/testinput15
create mode 100644 testdata/testinput16
create mode 100644 testdata/testinput17
create mode 100644 testdata/testinput18
create mode 100644 testdata/testinput19
create mode 100644 testdata/testinput2
create mode 100644 testdata/testinput20
create mode 100644 testdata/testinput21
create mode 100644 testdata/testinput22
create mode 100644 testdata/testinput23
create mode 100644 testdata/testinput24
create mode 100644 testdata/testinput25
create mode 100644 testdata/testinput26
create mode 100644 testdata/testinput27
create mode 100644 testdata/testinput28
create mode 100644 testdata/testinput29
create mode 100644 testdata/testinput3
create mode 100644 testdata/testinput4
create mode 100644 testdata/testinput5
create mode 100644 testdata/testinput6
create mode 100644 testdata/testinput7
create mode 100644 testdata/testinput8
create mode 100644 testdata/testinput9
create mode 100644 testdata/testinputheap
create mode 100644 testdata/testoutput1
create mode 100644 testdata/testoutput10
create mode 100644 testdata/testoutput11-16
create mode 100644 testdata/testoutput11-32
create mode 100644 testdata/testoutput12-16
create mode 100644 testdata/testoutput12-32
create mode 100644 testdata/testoutput13
create mode 100644 testdata/testoutput14-16
create mode 100644 testdata/testoutput14-32
create mode 100644 testdata/testoutput14-8
create mode 100644 testdata/testoutput15
create mode 100644 testdata/testoutput16
create mode 100644 testdata/testoutput17
create mode 100644 testdata/testoutput18
create mode 100644 testdata/testoutput19
create mode 100644 testdata/testoutput2
create mode 100644 testdata/testoutput20
create mode 100644 testdata/testoutput21
create mode 100644 testdata/testoutput22-16
create mode 100644 testdata/testoutput22-32
create mode 100644 testdata/testoutput22-8
create mode 100644 testdata/testoutput23
create mode 100644 testdata/testoutput24
create mode 100644 testdata/testoutput25
create mode 100644 testdata/testoutput26
create mode 100644 testdata/testoutput27
create mode 100644 testdata/testoutput28
create mode 100644 testdata/testoutput29
create mode 100644 testdata/testoutput3
create mode 100644 testdata/testoutput3A
create mode 100644 testdata/testoutput3B
create mode 100644 testdata/testoutput4
create mode 100644 testdata/testoutput5
create mode 100644 testdata/testoutput6
create mode 100644 testdata/testoutput7
create mode 100644 testdata/testoutput8-16-2
create mode 100644 testdata/testoutput8-16-4
create mode 100644 testdata/testoutput8-32-4
create mode 100644 testdata/testoutput8-8-2
create mode 100644 testdata/testoutput8-8-3
create mode 100644 testdata/testoutput8-8-4
create mode 100644 testdata/testoutput9
create mode 100644 testdata/testoutputheap-16
create mode 100644 testdata/testoutputheap-32
create mode 100644 testdata/testoutputheap-8
create mode 100644 testdata/valgrind-jit.supp
create mode 100644 testdata/wintestinput3
create mode 100644 testdata/wintestoutput3
create mode 100644 vms/configure.com
create mode 100644 vms/openvms_readme.txt
create mode 100644 vms/pcre2.h_patch
create mode 100644 vms/stdint.h
diff --git a/AUTHORS.md b/AUTHORS.md
new file mode 100644
index 0000000..4aa4ed0
--- /dev/null
+++ b/AUTHORS.md
@@ -0,0 +1,221 @@
+PCRE2 Authorship and Contributors
+=================================
+
+Copyright
+---------
+
+Please see the file [LICENCE](./LICENCE.md) in the PCRE2 distribution for
+copyright details.
+
+
+Maintainers
+-----------
+
+The PCRE and PCRE2 libraries were authored and maintained by Philip Hazel.
+
+Since 2024, the contributors with administrator access to the project are now
+Nicholas Wilson and Zoltán Herczeg. See the file [SECURITY](./SECURITY.md) for
+GPG keys.
+
+Both administrators are volunteers acting in a personal capacity.
+
+
+
+
+ | Name |
+ Role |
+
+
+
+
+
+
+ Nicholas Wilson
+ `nicholas@nicholaswilson.me.uk`
+ Currently of Microsoft Research Cambridge, UK
+
+ |
+
+
+ * General project administration & maintenance
+ * Release management
+ * Code maintenance
+
+ |
+
+
+
+
+ Zoltán Herczeg
+ `hzmester@freemail.hu`
+ Currently of the University of Szeged, Hungary
+
+ |
+
+
+ * Code maintenance
+ * Ownership of `sljit` and PCRE2's JIT
+
+ |
+
+
+
+
+
+Contributors
+------------
+
+Many others have participated and contributed to PCRE2 over its history.
+
+The maintainers are grateful for all contributions and participation over the
+years. We apologise for any names we have forgotten.
+
+We are especially grateful to Philip Hazel, creator of PCRE and PCRE2, and
+maintainer from 1997 to 2024.
+
+All names listed alphabetically.
+
+### Contributors to PCRE2
+
+This list includes names up until the PCRE2 10.48 release. New names will be
+added from the Git history on each release.
+
+ Ilia Alshanetsky
+ Bernard Assan
+ Scott Bell
+ Carlo Marcelo Arenas Belón
+ Edward Betts
+ Jan-Willem Blokland
+ Ross Burton
+ Dmitry Cherniachenko
+ Alexey Chupahin
+ Jessica Clarke
+ Alejandro Colomar
+ Jeremie Courreges-Anglas
+ Addison Crump
+ Weixie Cui
+ Alex Dowad
+ Daniel Engberg
+ Marco Feuerstein
+ Daniel Richard G
+ Isaac Oscar Gariano
+ David Gaussmann
+ Andrey Gorbachev
+ Nikolay Govorov
+ Jordan Griege
+ Rudi Heitbaum
+ Jason Hood
+ Bumsu Hyeon
+ Roy Ivy
+ Nobuhiro Iwamatsu
+ Martin Joerg
+ Guillem Jover
+ Ralf Junker
+ Anton Karpov
+ Ayesh Karunaratne
+ Michael Kaufmann
+ Srijan Keshri
+ Yunho Kim
+ Joshua Kinard
+ David Korczynski
+ Uwe Korn
+ Jonas Kvinge
+ Kristian Larsson
+ Lin Runze
+ Kai Lu
+ Behzod Mansurov
+ Brian McKenna
+ B. Scott Michel
+ Greg Minshall
+ Nathan Moinvaziri
+ Alexandre Moyer
+ Mike Munday
+ Marc Mutz
+ Kartik Naik
+ NaN
+ Fabio Pagani
+ Christian Persch
+ Alex Reinking
+ Joshua Rogers
+ Tristan Ross
+ William A Rowe Jr
+ Rocco Ruscitti
+ David Seifert
+ Yaakov Selkowitz
+ Rich Siegel
+ Karl Skomski
+ Maciej SroczyÅski
+ Wolfgang Stöggl
+ Thomas Tempelmann
+ Greg Thain
+ Lucas Trzesniewski
+ Theodore Tsirpanis
+ Matt Turner
+ Aaron M. Ucko
+ Matthew Vernon
+ Rémi Verschelde
+ Thomas Voss
+ Ezekiel Warren
+ Carl Weaver
+ Chris Wilson
+ Amin Yahyaabadi
+ Joe Zhang
+
+### Contributors to PCRE1
+
+These people contributed either by sending patches or reporting serious issues.
+
+ Irfan Adilovic
+ Alexander Barkov
+ Daniel Bergström
+ David Burgess
+ Ross Burton
+ David Byron
+ Fred Cox
+ Christian Ehrlicher
+ Tom Fortmann
+ Lionel Fourquaux
+ Mike Frysinger
+ Daniel Richard G
+ Dair Gran
+ "Graycode" (Red Hat Product Security)
+ Viktor Griph
+ Wen Guanxing
+ Robin Houston
+ Martin Jerabek
+ Peter Kankowski
+ Stephen Kelly
+ Yunho Kim
+ Joshua Kinard
+ Carsten Klein
+ Evgeny Kotkov
+ Ronald Landheer-Cieslak
+ Alan Lehotsky
+ Dmitry V. Levin
+ Nuno Lopes
+ Kai Lu
+ Giuseppe Maxia
+ Dan Mooney
+ Marc Mutz
+ Markus Oberhumer
+ Sheri Pierce
+ Petr Pisar
+ Ari Pollak
+ Bob Rossi
+ Ruiger Rill
+ Michael Shigorin
+ Rich Siegel
+ Craig Silverstein (C++ wrapper)
+ Karl Skomski
+ Paul Sokolovsky
+ Stan Switzer
+ Ian Taylor
+ Mark Tetrode
+ Jeff Trawick
+ Steven Van Ingelgem
+ Lawrence Velazquez
+ Jiong Wang
+ Stefan Weber
+ Chris Wilson
+
+Thanks go to Jeffrey Friedl for testing and debugging assistance.
diff --git a/BUILD.bazel b/BUILD.bazel
new file mode 100644
index 0000000..ec1b0b9
--- /dev/null
+++ b/BUILD.bazel
@@ -0,0 +1,199 @@
+load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
+load("@bazel_skylib//rules:native_binary.bzl", "native_test")
+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
+
+copy_file(
+ name = "config_h_generic",
+ src = "src/config.h.generic",
+ out = "src/config.h",
+)
+
+copy_file(
+ name = "pcre2_h_generic",
+ src = "src/pcre2.h.generic",
+ out = "src/pcre2.h",
+)
+
+copy_file(
+ name = "pcre2_chartables_c",
+ src = "src/pcre2_chartables.c.dist",
+ out = "src/pcre2_chartables.c",
+)
+
+LOCAL_DEFINES = [
+ "HAVE_CONFIG_H",
+ "SUPPORT_PCRE2_8",
+ "SUPPORT_UNICODE",
+] + select({
+ "@platforms//os:windows": [],
+ "//conditions:default": ["HAVE_UNISTD_H"],
+})
+
+# Workaround for a Bazel quirk. It is extremely strict about the #include path
+# used for internal headers. We have our headers inside src/, but we #include
+# them as '#include "pcre2_internal.h"', assuming that src/ is added to the
+# compiler's include path. Unfortunately, that violates the conventions used by
+# Bazel.
+#
+# This is a workaround. Note that we can't use the "include = [...]" property
+# to add the src/ directory, since that pollutes the include path for projects
+# depending on PCRE2 (we must not make our config.h file visible to consumers
+# of PCRE2).
+cc_library(
+ name = "pcre2_internal_headers",
+ hdrs = [
+ "src/pcre2_compile.h",
+ "src/pcre2_internal.h",
+ "src/pcre2_intmodedep.h",
+ "src/pcre2_jit_match_inc.h",
+ "src/pcre2_jit_misc_inc.h",
+ "src/pcre2_printint_inc.h",
+ "src/pcre2_ucp.h",
+ "src/pcre2_ucptables_inc.h",
+ "src/pcre2_util.h",
+ "src/pcre2test_inc.h",
+ ":config_h_generic",
+ ],
+ strip_include_prefix = "src",
+ visibility = ["//visibility:private"],
+)
+
+cc_library(
+ name = "pcre2",
+ srcs = [
+ "src/pcre2_auto_possess.c",
+ "src/pcre2_chkdint.c",
+ "src/pcre2_compile.c",
+ "src/pcre2_compile_cgroup.c",
+ "src/pcre2_compile_class.c",
+ "src/pcre2_config.c",
+ "src/pcre2_context.c",
+ "src/pcre2_convert.c",
+ "src/pcre2_dfa_match.c",
+ "src/pcre2_error.c",
+ "src/pcre2_extuni.c",
+ "src/pcre2_find_bracket.c",
+ "src/pcre2_jit_compile.c",
+ "src/pcre2_maketables.c",
+ "src/pcre2_match.c",
+ "src/pcre2_match_data.c",
+ "src/pcre2_match_next.c",
+ "src/pcre2_newline.c",
+ "src/pcre2_ord2utf.c",
+ "src/pcre2_pattern_info.c",
+ "src/pcre2_script_run.c",
+ "src/pcre2_serialize.c",
+ "src/pcre2_string_utils.c",
+ "src/pcre2_study.c",
+ "src/pcre2_substitute.c",
+ "src/pcre2_substring.c",
+ "src/pcre2_tables.c",
+ "src/pcre2_ucd.c",
+ "src/pcre2_valid_utf.c",
+ "src/pcre2_xclass.c",
+ ":pcre2_chartables_c",
+ ],
+ hdrs = [":pcre2_h_generic"],
+ implementation_deps = [":pcre2_internal_headers"],
+ defines = [
+ "PCRE2_STATIC",
+ ],
+ local_defines = LOCAL_DEFINES + [
+ "PCRE2_CODE_UNIT_WIDTH=8",
+ ],
+ strip_include_prefix = "src",
+ linkstatic = True,
+ visibility = ["//visibility:public"],
+)
+
+# See below for explanation of why we need this.
+#
+# https://github.com/bazelbuild/bazel/issues/680
+cc_library(
+ name = "pcre2posix_dotc_headers",
+ hdrs = [
+ "src/pcre2_tables.c",
+ ],
+ strip_include_prefix = "src",
+ visibility = ["//visibility:private"],
+)
+
+cc_library(
+ name = "pcre2-posix",
+ srcs = ["src/pcre2posix.c"],
+ hdrs = ["src/pcre2posix.h"],
+ implementation_deps = [
+ ":pcre2_internal_headers",
+ ":pcre2posix_dotc_headers",
+ ],
+ local_defines = LOCAL_DEFINES + [
+ "PCRE2_CODE_UNIT_WIDTH=8",
+ ],
+ strip_include_prefix = "src",
+ linkstatic = True,
+ visibility = ["//visibility:public"],
+ deps = [
+ ":pcre2",
+ ],
+)
+
+# Totally weird issue in Bazel. It won't let you #include any files unless they
+# are declared to the build system. OK, fair enough. But - for a cc_binary it
+# uses the file extension to determine whether it's a header or a compilation
+# unit. But... we have several .c files which are #included, rather than treated
+# as a compilation unit.
+#
+# For cc_library() above, we can overcome this with textual_hdrs. But that
+# doesn't work for cc_binary(). Here's our workaround.
+#
+# https://github.com/bazelbuild/bazel/issues/680
+cc_library(
+ name = "pcre2test_dotc_headers",
+ hdrs = [
+ "src/pcre2_chkdint.c",
+ "src/pcre2_tables.c",
+ "src/pcre2_ucd.c",
+ "src/pcre2_valid_utf.c",
+ ],
+ strip_include_prefix = "src",
+ visibility = ["//visibility:private"],
+)
+
+cc_binary(
+ name = "pcre2test",
+ srcs = ["src/pcre2test.c"],
+ linkopts = select({
+ "@platforms//os:windows": ["-STACK:2500000"],
+ "//conditions:default": [],
+ }),
+ local_defines = LOCAL_DEFINES,
+ visibility = ["//visibility:public"],
+ deps = [
+ ":pcre2",
+ ":pcre2-posix",
+ ":pcre2_internal_headers",
+ ":pcre2test_dotc_headers",
+ ],
+)
+
+filegroup(
+ name = "testdata",
+ srcs = glob(["testdata/*"]),
+)
+
+native_test(
+ name = "pcre2_test",
+ size = "small",
+ src = select({
+ "@platforms//os:windows": "RunTest.bat",
+ "//conditions:default": "RunTest",
+ }),
+ out = select({
+ "@platforms//os:windows": "RunTest.bat",
+ "//conditions:default": "RunTest",
+ }),
+ data = [
+ ":pcre2test",
+ ":testdata",
+ ],
+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..701233a
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,1637 @@
+# CMakeLists.txt
+#
+# This file enables PCRE2 to be built with the CMake configuration and build
+# tool. Download CMake in source or binary form from http://www.cmake.org/
+# Converted to support PCRE2 from the original PCRE file, August 2014.
+#
+# Original listfile by Christian Ehrlicher
+# Refined and expanded by Daniel Richard G.
+# 2007-09-14 mod by Sheri so 7.4 supported configuration options can be entered
+# 2007-09-19 Adjusted by PH to retain previous default settings
+# 2007-12-26 (a) On UNIX, use names libpcre instead of just pcre
+# (b) Ensure pcretest and pcregrep link with the local library,
+# not a previously-installed one.
+# (c) Add PCRE_SUPPORT_LIBREADLINE, PCRE_SUPPORT_LIBZ, and
+# PCRE_SUPPORT_LIBBZ2.
+# 2008-01-20 Brought up to date to include several new features by Christian
+# Ehrlicher.
+# 2008-01-22 Sheri added options for backward compatibility of library names
+# when building with minGW:
+# if "ON", NON_STANDARD_LIB_PREFIX causes shared libraries to
+# be built without "lib" as prefix. (The libraries will be named
+# pcre.dll, pcreposix.dll and pcrecpp.dll).
+# if "ON", NON_STANDARD_LIB_SUFFIX causes shared libraries to
+# be built with suffix of "-0.dll". (The libraries will be named
+# libpcre-0.dll, libpcreposix-0.dll and libpcrecpp-0.dll - same names
+# built by default with Configure and Make.
+# 2008-01-23 PH removed the automatic build of pcredemo.
+# 2008-04-22 PH modified READLINE support so it finds NCURSES when needed.
+# 2008-07-03 PH updated for revised UCP property support (change of files)
+# 2009-03-23 PH applied Steven Van Ingelgem's patch to change the name
+# CMAKE_BINARY_DIR to PROJECT_BINARY_DIR so that it works when PCRE
+# is included within another project.
+# 2009-03-23 PH applied a modified version of Steven Van Ingelgem's patches to
+# add options to stop the building of pcregrep and the tests, and
+# to disable the final configuration report.
+# 2009-04-11 PH applied Christian Ehrlicher's patch to show compiler flags that
+# are set by specifying a release type.
+# 2010-01-02 PH added test for stdint.h
+# 2010-03-02 PH added test for inttypes.h
+# 2011-08-01 PH added PCREGREP_BUFSIZE
+# 2011-08-22 PH added PCRE_SUPPORT_JIT
+# 2011-09-06 PH modified WIN32 ADD_TEST line as suggested by Sergey Cherepanov
+# 2011-09-06 PH added PCRE_SUPPORT_PCREGREP_JIT
+# 2011-10-04 Sheri added support for including coff data in windows shared libraries
+# compiled with MINGW if pcre.rc and/or pcreposix.rc are placed in
+# the source dir by the user prior to building
+# 2011-10-04 Sheri changed various add_test's to use exes' location built instead
+# of DEBUG location only (likely only matters in MSVC)
+# 2011-10-04 Sheri added scripts to provide needed variables to RunTest and
+# RunGrepTest (used for UNIX and Msys)
+# 2011-10-04 Sheri added scripts to provide needed variables and to execute
+# RunTest.bat in Win32 (for effortless testing with "make test")
+# 2011-10-04 Sheri Increased minimum required cmake version
+# 2012-01-06 PH removed pcre_info.c and added pcre_string_utils.c
+# 2012-01-10 Zoltan Herczeg added libpcre16 support
+# 2012-01-13 Stephen Kelly added out of source build support
+# 2012-01-17 PH applied Stephen Kelly's patch to parse the version data out
+# of the configure.ac file
+# 2012-02-26 PH added support for libedit
+# 2012-09-06 PH added support for PCRE_EBCDIC_NL25
+# 2012-09-08 ChPe added PCRE32 support
+# 2012-10-23 PH added support for VALGRIND and GCOV
+# 2012-12-08 PH added patch from Daniel Richard G to quash some MSVC warnings
+# 2013-07-01 PH realized that the "support" for GCOV was a total nonsense and
+# so it has been removed.
+# 2013-10-08 PH got rid of the "source" command, which is a bash-ism (use ".")
+# 2013-11-05 PH added support for PARENS_NEST_LIMIT
+# 2014-08-29 PH converted the file for PCRE2 (which has no C++).
+# 2015-04-24 PH added support for PCRE2_DEBUG
+# 2015-07-16 PH updated for new pcre2_find_bracket source module
+# 2015-08-24 PH correct C_FLAGS setting (patch from Roy Ivy III)
+# 2015-10=16 PH added support for never-backslash-C
+# 2016-03-01 PH applied Chris Wilson's patch for MSVC static
+# 2016-06-24 PH applied Chris Wilson's second patch, putting the first under
+# a new option instead of being unconditional.
+# 2016-10-05 PH fixed a typo (PCRE should be PCRE2) in above patch
+# fix by David Gaussmann
+# 2016-10-07 PH added PCREGREP_MAX_BUFSIZE
+# 2017-03-11 PH turned HEAP_MATCH_RECURSE into a NO-OP for 10.30
+# 2017-04-08 PH added HEAP_LIMIT
+# 2017-06-15 ZH added SUPPORT_JIT_SEALLOC support
+# 2018-06-19 PH added checks for stdint.h and inttypes.h (later removed)
+# 2018-06-27 PH added Daniel's patch to increase the stack for MSVC
+# 2018-11-14 PH removed unnecessary checks for stdint.h and inttypes.h
+# 2018-11-16 PH added PCRE2GREP_SUPPORT_CALLOUT_FORK support and tidied
+# 2019-02-16 PH hacked to avoid CMP0026 policy issue (see comments below)
+# 2020-03-16 PH renamed dftables as pcre2_dftables (as elsewhere)
+# 2020-03-24 PH changed CMAKE_MODULE_PATH definition to add, not replace
+# 2020-04-08 Carlo added function check for secure_getenv, fixed strerror
+# 2020-04-16 enh added check for __attribute__((uninitialized))
+# 2020-04-25 PH applied patches from Uwe Korn to support pkg-config and
+# library versioning.
+# 2020-04-25 Carlo added function check for mkostemp used in ProtExecAllocator
+# 2020-04-28 PH added function check for memfd_create based on Carlo's patch
+# 2020-05-25 PH added a check for Intel CET
+# 2020-12-03 PH altered the definition of pcre2test as suggested by Daniel
+# 2021-06-29 JWSB added the option to build static library with PIC.
+# 2021-07-05 JWSB modified such both the static and shared library can be
+# build in one go.
+# 2021-08-28 PH increased minimum version
+# 2021-08-28 PH added test for realpath()
+# 2022-12-10 PH added support for pcre2posix_test
+# 2023-01-15 Carlo added C99 as the minimum required
+# 2023-08-06 PH added support for setting variable length lookbehind maximum
+# 2025-03-27 Theodore used standard CMake constructs to export the library's
+# targets.
+
+################################################################################
+# We have used `gersemi` for auto-formatting our CMake files.
+# Applied to all CMake files using:
+# > pip3 install gersemi
+# > gersemi --in-place --line-length 120 --indent 2 \
+# --definitions cmake/*.cmake \
+# -- ./CMakeLists.txt ./cmake/*.cmake ./cmake/*.cmake.in
+################################################################################
+
+message(STATUS "Using CMake version ${CMAKE_VERSION} (${CMAKE_COMMAND})")
+
+# Increased minimum to 3.15 to allow use of string(REPEAT).
+cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
+project(PCRE2 C)
+set(CMAKE_C_STANDARD 99)
+set(CMAKE_C_STANDARD_REQUIRED TRUE)
+set(CMAKE_C_VISIBILITY_PRESET hidden)
+
+# Solaris-specific fix for "CMAKE_C_VISIBILITY_PRESET": this feature was only
+# recently added to CMake for the `cc` compiler (Oracle Developer Studio). The
+# CMake version from OpenCSW and Oracle's package repository is too old and
+# requires this fix.
+if(
+ CMAKE_SYSTEM_NAME STREQUAL "SunOS"
+ AND CMAKE_VERSION VERSION_LESS 3.31
+ AND CMAKE_C_COMPILER_ID STREQUAL "SunPro"
+ AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 5.15
+)
+ set(CMAKE_C_COMPILE_OPTIONS_VISIBILITY "-fvisibility=")
+endif()
+
+# The following policies have been set in the PCRE2 CMake file in the past.
+# Since we specify a minimum of CMake 3.15, these are no longer required.
+# cmake_policy(SET CMP0063 NEW)
+# cmake_policy(SET CMP0026 OLD)
+# cmake_policy(SET CMP0074 NEW)
+
+# For our modules in cmake/. This uses list(APPEND) rather than set() to allow
+# setting CMAKE_MODULE_PATH on the command line.
+list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
+
+# External packages
+find_package(BZip2)
+find_package(ZLIB)
+find_package(Readline)
+find_package(Editline)
+
+# Configuration checks
+
+include(CheckCSourceCompiles)
+include(CheckFunctionExists)
+include(CheckSymbolExists)
+include(CheckIncludeFile)
+include(CheckTypeSize)
+include(CMakePackageConfigHelpers)
+include(CMakePushCheckState)
+include(GNUInstallDirs) # for CMAKE_INSTALL_LIBDIR
+include(PCRE2CheckVscript)
+include(PCRE2UseSystemExtensions)
+include(PCRE2WarningAsError)
+
+check_include_file(assert.h HAVE_ASSERT_H)
+check_include_file(dirent.h HAVE_DIRENT_H)
+check_include_file(sys/stat.h HAVE_SYS_STAT_H)
+check_include_file(sys/types.h HAVE_SYS_TYPES_H)
+check_include_file(unistd.h HAVE_UNISTD_H)
+check_include_file(windows.h HAVE_WINDOWS_H)
+
+# Check whether any system-wide extensions need to be enabled, in order for
+# OS functionality to be exposed.
+pcre2_use_system_extensions()
+
+cmake_push_check_state(RESET)
+# Propagate the _GNU_SOURCE definition (added to COMPILE_DEFINITIONS by
+# pcre2_use_system_extensions()) so that these check_symbol_exists() calls
+# can find symbols only exposed with _GNU_SOURCE.
+# We only pass through known plain-text definitions (like _GNU_SOURCE) and
+# skip anything else (e.g. generator expressions inherited from a parent
+# project), because try_compile() cannot handle generator expressions.
+get_directory_property(_pcre2_compile_definitions COMPILE_DEFINITIONS)
+if(DEFINED _pcre2_compile_definitions)
+ set(CMAKE_REQUIRED_DEFINITIONS "")
+ list(FIND _pcre2_compile_definitions "_GNU_SOURCE" _idx)
+ if(_idx GREATER -1)
+ list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE")
+ endif()
+endif()
+
+check_symbol_exists(mkostemp stdlib.h HAVE_MKOSTEMP) # glibc 2.7
+check_symbol_exists(memfd_create "sys/mman.h" HAVE_MEMFD_CREATE) # glibc 2.27
+check_symbol_exists(secure_getenv "stdlib.h" HAVE_SECURE_GETENV) # glibc 2.17
+check_symbol_exists(setrlimit "sys/resource.h" HAVE_SETRLIMIT)
+cmake_pop_check_state()
+
+check_c_source_compiles(
+ [=[
+ #include
+ #include
+ int main(int c, char *v[]) { char buf[PATH_MAX]; realpath(v[c], buf); return 0; }
+ ]=]
+ HAVE_REALPATH
+)
+
+# Many CMake tests use highly-dubious C source code which generates warnings
+# (for example, calling a function with the wrong signature just to see whether
+# the linker can find it). These couple of tests here though need to be compiled
+# with -Werror to be effective.
+cmake_push_check_state()
+if(NOT DEFINED CMAKE_REQUIRED_FLAGS)
+ set(CMAKE_REQUIRED_FLAGS "")
+endif()
+pcre2_warning_as_error(WARNING_AS_ERROR_FLAGS)
+set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${WARNING_AS_ERROR_FLAGS}")
+
+check_c_source_compiles(
+ "int main(void) { char buf[128] __attribute__((uninitialized)); (void)buf; return 0; }"
+ HAVE_ATTRIBUTE_UNINITIALIZED
+)
+
+if(NOT MSVC)
+ check_c_source_compiles(
+ [=[
+ extern __attribute__ ((visibility ("default"))) int f(void);
+ int main(void) { return f(); }
+ int f(void) { return 42; }
+ ]=]
+ HAVE_VISIBILITY
+ )
+endif()
+if(CMAKE_C_COMPILE_OPTIONS_VISIBILITY AND NOT HAVE_VISIBILITY)
+ # Hmm. We don't know of any way to set a symbol to have default visibility, other
+ # than the common "__attribute__((visibility("default")))". But CMake thinks that
+ # the compiler supports CMAKE_C_VISIBILITY_PRESET. The build is likely to fail to
+ # generate a usable shared library.
+ message(
+ WARNING
+ "C compiler uses the visibility flag ${CMAKE_C_COMPILE_OPTIONS_VISIBILITY}. We did not detect support for __attribute__((visibility(\"default\"))). We do not know how to set a symbol to have default visibility."
+ )
+elseif(HAVE_VISIBILITY AND NOT CMAKE_C_COMPILE_OPTIONS_VISIBILITY)
+ # Here, the build may well work, but it's possible that CMake isn't correctly
+ # suppressing the visibility of private symbols.
+ message(
+ WARNING
+ "C compiler appears to support __attribute__((visibility(\"default\"))). However, CMake is not using a visibility flag. The visibility of private symbols may not be correct."
+ )
+endif()
+if(HAVE_VISIBILITY)
+ set(PCRE2_EXPORT [=[__attribute__ ((visibility ("default")))]=])
+else()
+ set(PCRE2_EXPORT)
+endif()
+cmake_pop_check_state()
+
+check_c_source_compiles("int main(void) { __assume(1); return 0; }" HAVE_BUILTIN_ASSUME)
+
+check_c_source_compiles(
+ [=[
+ #include
+ int main(void) { int a,b; size_t m; __builtin_mul_overflow(a,b,&m); return 0; }
+ ]=]
+ HAVE_BUILTIN_MUL_OVERFLOW
+)
+
+check_c_source_compiles(
+ "int main(int c, char *v[]) { if (c) __builtin_unreachable(); return (int)(*v[0]); }"
+ HAVE_BUILTIN_UNREACHABLE
+)
+
+# Detect support for linker scripts.
+
+pcre2_check_vscript(HAVE_VSCRIPT VSCRIPT_FLAG HAVE_VSCRIPT_NO_STAR)
+
+# Check whether Intel CET is enabled, and if so, adjust compiler flags. This
+# code was written by PH, trying to imitate the logic from the autotools
+# configuration.
+
+check_c_source_compiles(
+ [=[
+ #ifndef __CET__
+ #error CET is not enabled
+ #endif
+ int main() { return 0; }
+ ]=]
+ INTEL_CET_ENABLED
+)
+
+if(INTEL_CET_ENABLED)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mshstk")
+endif()
+
+# User-configurable options
+#
+# Note: CMakeSetup displays these in alphabetical order, regardless of
+# the order we use here.
+
+set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries.")
+
+option(BUILD_STATIC_LIBS "Build static libraries." ON)
+
+option(PCRE2_BUILD_PCRE2_8 "Build 8 bit PCRE2 library" ON)
+
+option(PCRE2_BUILD_PCRE2_16 "Build 16 bit PCRE2 library" OFF)
+
+option(PCRE2_BUILD_PCRE2_32 "Build 32 bit PCRE2 library" OFF)
+
+option(PCRE2_STATIC_PIC "Build the static library with the option position independent code enabled." OFF)
+
+set(PCRE2_DEBUG "IfDebugBuild" CACHE STRING "Include debugging code")
+set_property(CACHE PCRE2_DEBUG PROPERTY STRINGS "IfDebugBuild" "ON" "OFF")
+
+option(PCRE2_DISABLE_PERCENT_ZT "Disable the use of %zu and %td (rarely needed)" OFF)
+
+set(
+ PCRE2_EBCDIC
+ OFF
+ CACHE BOOL
+ "Use EBCDIC coding instead of ASCII. (This is rarely used outside of mainframe systems.)"
+)
+
+set(PCRE2_EBCDIC_NL25 OFF CACHE BOOL "Use 0x25 as EBCDIC NL character instead of 0x15; implies EBCDIC.")
+
+set(
+ PCRE2_EBCDIC_IGNORING_COMPILER
+ OFF
+ CACHE BOOL
+ "Force EBCDIC 1047 using numeric literals rather than C character literals; implies EBCDIC."
+)
+
+option(PCRE2_REBUILD_CHARTABLES "Rebuild char tables" OFF)
+
+set(
+ PCRE2_LINK_SIZE
+ "2"
+ CACHE STRING
+ "Internal link size (2, 3 or 4 allowed). See LINK_SIZE in config.h.in for details."
+)
+
+set(
+ PCRE2_PARENS_NEST_LIMIT
+ "250"
+ CACHE STRING
+ "Default nested parentheses limit. See PARENS_NEST_LIMIT in config.h.in for details."
+)
+
+set(
+ PCRE2_HEAP_LIMIT
+ "20000000"
+ CACHE STRING
+ "Default limit on heap memory (kibibytes). See HEAP_LIMIT in config.h.in for details."
+)
+
+set(PCRE2_MAX_VARLOOKBEHIND "255" CACHE STRING "Default limit on variable lookbehinds.")
+
+set(
+ PCRE2_MATCH_LIMIT
+ "10000000"
+ CACHE STRING
+ "Default limit on internal looping. See MATCH_LIMIT in config.h.in for details."
+)
+
+set(
+ PCRE2_MATCH_LIMIT_DEPTH
+ "MATCH_LIMIT"
+ CACHE STRING
+ "Default limit on internal depth of search. See MATCH_LIMIT_DEPTH in config.h.in for details."
+)
+
+set(
+ PCRE2GREP_BUFSIZE
+ "20480"
+ CACHE STRING
+ "Buffer starting size parameter for pcre2grep. See PCRE2GREP_BUFSIZE in config.h.in for details."
+)
+
+set(
+ PCRE2GREP_MAX_BUFSIZE
+ "1048576"
+ CACHE STRING
+ "Buffer maximum size parameter for pcre2grep. See PCRE2GREP_MAX_BUFSIZE in config.h.in for details."
+)
+
+set(PCRE2_NEWLINE "LF" CACHE STRING "What to recognize as a newline (one of CR, LF, CRLF, ANY, ANYCRLF, NUL).")
+
+set(PCRE2_HEAP_MATCH_RECURSE OFF CACHE BOOL "Obsolete option: do not use")
+mark_as_advanced(PCRE2_HEAP_MATCH_RECURSE)
+
+set(PCRE2_SUPPORT_JIT OFF CACHE BOOL "Enable support for Just-in-time compiling.")
+
+if(${CMAKE_SYSTEM_NAME} MATCHES Linux|NetBSD)
+ set(PCRE2_SUPPORT_JIT_SEALLOC OFF CACHE BOOL "Enable SELinux compatible execmem allocator in JIT (experimental).")
+else()
+ set(PCRE2_SUPPORT_JIT_SEALLOC IGNORE)
+endif()
+
+set(PCRE2GREP_SUPPORT_JIT ON CACHE BOOL "Enable use of Just-in-time compiling in pcre2grep.")
+
+set(PCRE2GREP_SUPPORT_CALLOUT ON CACHE BOOL "Enable callout string support in pcre2grep.")
+
+set(PCRE2GREP_SUPPORT_CALLOUT_FORK ON CACHE BOOL "Enable callout string fork support in pcre2grep.")
+
+set(PCRE2_SUPPORT_UNICODE ON CACHE BOOL "Enable support for Unicode and UTF-8/UTF-16/UTF-32 encoding.")
+
+set(
+ PCRE2_SUPPORT_BSR_ANYCRLF
+ OFF
+ CACHE BOOL
+ "ON=Backslash-R matches only LF CR and CRLF, OFF=Backslash-R matches all Unicode Linebreaks"
+)
+
+set(PCRE2_NEVER_BACKSLASH_C OFF CACHE BOOL "If ON, backslash-C (upper case C) is locked out.")
+
+set(PCRE2_SUPPORT_VALGRIND OFF CACHE BOOL "Enable Valgrind support.")
+
+option(PCRE2_SHOW_REPORT "Show the final configuration report" ON)
+option(PCRE2_BUILD_PCRE2GREP "Build pcre2grep" ON)
+option(PCRE2_BUILD_TESTS "Build the tests" ON)
+
+set(
+ PCRE2_INSTALL_CMAKEDIR
+ "${CMAKE_INSTALL_LIBDIR}/cmake/pcre2"
+ CACHE STRING
+ "Path used during CMake install for placing PCRE2's CMake config files, relative to the installation root (prefix)"
+)
+
+if(MINGW)
+ option(
+ NON_STANDARD_LIB_PREFIX
+ "ON=Shared libraries built in mingw will be named pcre2.dll, etc., instead of libpcre2.dll, etc."
+ OFF
+ )
+
+ option(
+ NON_STANDARD_LIB_SUFFIX
+ "ON=Shared libraries built in mingw will be named libpcre2-0.dll, etc., instead of libpcre2.dll, etc."
+ OFF
+ )
+endif()
+
+if(MSVC)
+ option(INSTALL_MSVC_PDB "ON=Install .pdb files built by MSVC, if generated" OFF)
+endif()
+
+if(HAVE_VSCRIPT)
+ option(PCRE2_SYMVERS "Enable library symbol versioning" ON)
+endif()
+
+# bzip2 lib
+if(BZip2_FOUND)
+ option(PCRE2_SUPPORT_LIBBZ2 "Enable support for linking pcre2grep with libbz2." ON)
+endif()
+
+# zlib
+if(ZLIB_FOUND)
+ option(PCRE2_SUPPORT_LIBZ "Enable support for linking pcre2grep with libz." ON)
+endif()
+
+# editline lib
+if(Editline_FOUND)
+ option(PCRE2_SUPPORT_LIBEDIT "Enable support for linking pcre2test with libedit." OFF)
+endif()
+
+# readline lib
+if(Readline_FOUND)
+ option(PCRE2_SUPPORT_LIBREADLINE "Enable support for linking pcre2test with libreadline." ON)
+endif()
+
+# Prepare build configuration
+
+include_directories(${PROJECT_BINARY_DIR}/interface ${PROJECT_BINARY_DIR}/src ${PROJECT_SOURCE_DIR}/src)
+
+if(NOT BUILD_SHARED_LIBS AND NOT BUILD_STATIC_LIBS)
+ message(FATAL_ERROR "At least one of BUILD_SHARED_LIBS or BUILD_STATIC_LIBS must be enabled.")
+endif()
+
+if(NOT PCRE2_BUILD_PCRE2_8 AND NOT PCRE2_BUILD_PCRE2_16 AND NOT PCRE2_BUILD_PCRE2_32)
+ message(
+ FATAL_ERROR
+ "At least one of PCRE2_BUILD_PCRE2_8, PCRE2_BUILD_PCRE2_16 or PCRE2_BUILD_PCRE2_32 must be enabled"
+ )
+endif()
+
+if(PCRE2_BUILD_PCRE2_8)
+ set(SUPPORT_PCRE2_8 1)
+endif()
+
+if(PCRE2_BUILD_PCRE2_16)
+ set(SUPPORT_PCRE2_16 1)
+endif()
+
+if(PCRE2_BUILD_PCRE2_32)
+ set(SUPPORT_PCRE2_32 1)
+endif()
+
+if(PCRE2_BUILD_PCRE2GREP AND NOT PCRE2_BUILD_PCRE2_8)
+ message(STATUS "** PCRE2_BUILD_PCRE2_8 must be enabled for the pcre2grep program")
+ set(PCRE2_BUILD_PCRE2GREP OFF)
+endif()
+
+if(PCRE2_SUPPORT_LIBBZ2)
+ if(BZip2_FOUND)
+ include_directories(${BZIP2_INCLUDE_DIRS})
+ else()
+ message(
+ FATAL_ERROR
+ " libbz2 not found. Set BZIP2_INCLUDE_DIRS to a compatible header\n"
+ " or set BZip2_ROOT to a full bzip2 installed tree, as needed."
+ )
+ endif()
+endif()
+
+if(PCRE2_SUPPORT_LIBZ)
+ if(ZLIB_FOUND)
+ include_directories(${ZLIB_INCLUDE_DIRS})
+ else()
+ message(
+ FATAL_ERROR
+ " zlib not found. Set ZLIB_INCLUDE_DIRS to a compatible header\n"
+ " or set ZLIB_ROOT to a full zlib installed tree, as needed."
+ )
+ endif()
+endif()
+
+if(PCRE2_SUPPORT_LIBEDIT)
+ if(Editline_FOUND)
+ include_directories(${EDITLINE_INCLUDE_DIRS})
+ else()
+ message(
+ FATAL_ERROR
+ " libedit not found. Set EDITLINE_INCLUDE_DIRS to a compatible header\n"
+ " or set Editline_ROOT to a full libedit installed tree, as needed."
+ )
+ endif()
+endif()
+
+if(PCRE2_SUPPORT_LIBREADLINE)
+ if(Readline_FOUND)
+ include_directories(${READLINE_INCLUDE_DIRS})
+ else()
+ message(
+ FATAL_ERROR
+ " libreadline not found. Set READLINE_INCLUDE_DIRS to a compatible header\n"
+ " or set Readline_ROOT to a full libreadline installed tree, as needed."
+ )
+ endif()
+endif()
+
+if(PCRE2_SUPPORT_LIBREADLINE AND PCRE2_SUPPORT_LIBEDIT)
+ if(Readline_FOUND)
+ message(
+ FATAL_ERROR
+ " Only one of the readline compatible libraries can be enabled.\n"
+ " Disable libreadline with -DPCRE2_SUPPORT_LIBREADLINE=OFF"
+ )
+ endif()
+endif()
+
+if(PCRE2_SUPPORT_BSR_ANYCRLF)
+ set(BSR_ANYCRLF 1)
+endif()
+
+if(PCRE2_NEVER_BACKSLASH_C)
+ set(NEVER_BACKSLASH_C 1)
+endif()
+
+if(PCRE2_SUPPORT_UNICODE)
+ set(SUPPORT_UNICODE 1)
+endif()
+
+if(PCRE2_SUPPORT_JIT)
+ set(SUPPORT_JIT 1)
+ if(UNIX)
+ find_package(Threads REQUIRED)
+ if(CMAKE_USE_PTHREADS_INIT)
+ set(REQUIRE_PTHREAD 1)
+ endif()
+ endif()
+endif()
+
+if(PCRE2_SUPPORT_JIT_SEALLOC)
+ set(SLJIT_PROT_EXECUTABLE_ALLOCATOR 1)
+endif()
+
+if(PCRE2GREP_SUPPORT_JIT)
+ set(SUPPORT_PCRE2GREP_JIT 1)
+endif()
+
+if(PCRE2GREP_SUPPORT_CALLOUT)
+ set(SUPPORT_PCRE2GREP_CALLOUT 1)
+ if(PCRE2GREP_SUPPORT_CALLOUT_FORK)
+ set(SUPPORT_PCRE2GREP_CALLOUT_FORK 1)
+ endif()
+endif()
+
+if(PCRE2_SUPPORT_VALGRIND)
+ set(SUPPORT_VALGRIND 1)
+endif()
+
+if(PCRE2_DISABLE_PERCENT_ZT)
+ set(DISABLE_PERCENT_ZT 1)
+endif()
+
+set(PCRE2TEST_LIBS)
+set(PCRE2GREP_LIBS)
+
+if(PCRE2_SUPPORT_LIBREADLINE)
+ set(SUPPORT_LIBREADLINE 1)
+ list(APPEND PCRE2TEST_LIBS ${READLINE_LIBRARIES})
+endif()
+
+# libedit is a plug-compatible alternative to libreadline
+
+if(PCRE2_SUPPORT_LIBEDIT)
+ set(SUPPORT_LIBEDIT 1)
+ list(APPEND PCRE2TEST_LIBS ${EDITLINE_LIBRARIES})
+endif()
+
+if(PCRE2_SUPPORT_LIBZ)
+ set(SUPPORT_LIBZ 1)
+ list(APPEND PCRE2GREP_LIBS ${ZLIB_LIBRARIES})
+endif()
+
+if(PCRE2_SUPPORT_LIBBZ2)
+ set(SUPPORT_LIBBZ2 1)
+ list(APPEND PCRE2GREP_LIBS ${BZIP2_LIBRARIES})
+endif()
+
+set(NEWLINE_DEFAULT "")
+
+if(PCRE2_NEWLINE STREQUAL "CR")
+ set(NEWLINE_DEFAULT "1")
+endif()
+if(PCRE2_NEWLINE STREQUAL "LF")
+ set(NEWLINE_DEFAULT "2")
+endif()
+if(PCRE2_NEWLINE STREQUAL "CRLF")
+ set(NEWLINE_DEFAULT "3")
+endif()
+if(PCRE2_NEWLINE STREQUAL "ANY")
+ set(NEWLINE_DEFAULT "4")
+endif()
+if(PCRE2_NEWLINE STREQUAL "ANYCRLF")
+ set(NEWLINE_DEFAULT "5")
+endif()
+if(PCRE2_NEWLINE STREQUAL "NUL")
+ set(NEWLINE_DEFAULT "6")
+endif()
+
+if(NEWLINE_DEFAULT STREQUAL "")
+ message(
+ FATAL_ERROR
+ "The PCRE2_NEWLINE variable must be set to one of the following values: \"LF\", \"CR\", \"CRLF\", \"ANY\", \"ANYCRLF\"."
+ )
+endif()
+
+set(REBUILD_CHARTABLES OFF)
+if(PCRE2_REBUILD_CHARTABLES)
+ set(REBUILD_CHARTABLES ON)
+endif()
+
+set(EBCDIC OFF)
+if(PCRE2_EBCDIC)
+ set(EBCDIC ON)
+endif()
+
+if(PCRE2_EBCDIC_NL25)
+ set(EBCDIC ON)
+ set(EBCDIC_NL25 ON)
+endif()
+
+if(PCRE2_EBCDIC_IGNORING_COMPILER)
+ set(EBCDIC ON)
+ set(EBCDIC_IGNORING_COMPILER ON)
+endif()
+
+# Make sure that if EBCDIC is set (without EBCDIC_IGNORING_COMPILER), then
+# REBUILD_CHARTABLES is also enabled.
+# Also check that UTF support is not requested, because PCRE2 cannot handle
+# EBCDIC and UTF in the same build. To do so it would need to use different
+# character constants depending on the mode.
+# Also, EBCDIC cannot be used with 16-bit and 32-bit libraries.
+if(EBCDIC)
+ if(NOT EBCDIC_IGNORING_COMPILER)
+ set(REBUILD_CHARTABLES ON)
+ endif()
+ if(PCRE2_SUPPORT_UNICODE)
+ message(FATAL_ERROR "Support for EBCDIC and Unicode cannot be enabled at the same time")
+ endif()
+ if(PCRE2_BUILD_PCRE2_16 OR PCRE2_BUILD_PCRE2_32)
+ message(FATAL_ERROR "EBCDIC support is available only for the 8-bit library")
+ endif()
+endif()
+
+# Remove the Autotools-generated copy of config.h and pcre2.h. I sometimes switch
+# between Autoconf and CMake, and the conflicting copies of config.h generate some
+# very unintuitive build errors.
+file(REMOVE ${PROJECT_SOURCE_DIR}/src/config.h)
+file(REMOVE ${PROJECT_SOURCE_DIR}/src/pcre2.h)
+
+# Parse version numbers and date out of configure.ac
+
+file(
+ STRINGS
+ ${PROJECT_SOURCE_DIR}/configure.ac
+ configure_lines
+ LIMIT_COUNT
+ 50 # Read only the first 50 lines of the file
+)
+
+set(
+ SEARCHED_VARIABLES
+ "pcre2_major"
+ "pcre2_minor"
+ "pcre2_prerelease"
+ "pcre2_date"
+ "libpcre2_posix_version"
+ "libpcre2_8_version"
+ "libpcre2_16_version"
+ "libpcre2_32_version"
+)
+foreach(configure_line ${configure_lines})
+ foreach(substitution_variable ${SEARCHED_VARIABLES})
+ string(TOUPPER ${substitution_variable} substitution_variable_upper)
+ if(NOT DEFINED ${substitution_variable_upper})
+ if("${configure_line}" MATCHES "m4_define\\(${substitution_variable}, *\\[(.*)\\]")
+ set(${substitution_variable_upper} "${CMAKE_MATCH_1}")
+ endif()
+ endif()
+ endforeach()
+endforeach()
+
+macro(PARSE_LIB_VERSION variable_prefix)
+ string(REPLACE ":" ";" ${variable_prefix}_VERSION_LIST ${${variable_prefix}_VERSION})
+ list(GET ${variable_prefix}_VERSION_LIST 0 ${variable_prefix}_VERSION_CURRENT)
+ list(GET ${variable_prefix}_VERSION_LIST 1 ${variable_prefix}_VERSION_REVISION)
+ list(GET ${variable_prefix}_VERSION_LIST 2 ${variable_prefix}_VERSION_AGE)
+
+ math(EXPR ${variable_prefix}_SOVERSION "${${variable_prefix}_VERSION_CURRENT} - ${${variable_prefix}_VERSION_AGE}")
+ math(EXPR ${variable_prefix}_MACHO_COMPATIBILITY_VERSION "${${variable_prefix}_VERSION_CURRENT} + 1")
+ math(EXPR ${variable_prefix}_MACHO_CURRENT_VERSION "${${variable_prefix}_VERSION_CURRENT} + 1")
+ set(
+ ${variable_prefix}_MACHO_CURRENT_VERSION
+ "${${variable_prefix}_MACHO_CURRENT_VERSION}.${${variable_prefix}_VERSION_REVISION}}"
+ )
+ set(
+ ${variable_prefix}_VERSION
+ "${${variable_prefix}_SOVERSION}.${${variable_prefix}_VERSION_AGE}.${${variable_prefix}_VERSION_REVISION}"
+ )
+endmacro()
+
+parse_lib_version(LIBPCRE2_POSIX)
+parse_lib_version(LIBPCRE2_8)
+parse_lib_version(LIBPCRE2_16)
+parse_lib_version(LIBPCRE2_32)
+
+# Output files
+
+configure_file(src/config-cmake.h.in ${PROJECT_BINARY_DIR}/src/config.h @ONLY)
+
+configure_file(src/pcre2.h.in ${PROJECT_BINARY_DIR}/interface/pcre2.h @ONLY)
+configure_file(src/pcre2posix.h ${PROJECT_BINARY_DIR}/interface/pcre2posix.h COPYONLY)
+
+# Configure the version script files.
+
+if(HAVE_VSCRIPT AND PCRE2_SYMVERS)
+ if(HAVE_VSCRIPT_NO_STAR)
+ set(PCRE2_EXTRA_LOCAL_SYMS "")
+ else()
+ set(PCRE2_EXTRA_LOCAL_SYMS " local: *;")
+ endif()
+
+ configure_file(src/libpcre2-8.sym.in ${PROJECT_BINARY_DIR}/src/libpcre2-8.sym @ONLY)
+ configure_file(src/libpcre2-16.sym.in ${PROJECT_BINARY_DIR}/src/libpcre2-16.sym @ONLY)
+ configure_file(src/libpcre2-32.sym.in ${PROJECT_BINARY_DIR}/src/libpcre2-32.sym @ONLY)
+ configure_file(src/libpcre2-posix.sym.in ${PROJECT_BINARY_DIR}/src/libpcre2-posix.sym @ONLY)
+endif()
+
+# Character table generation
+
+if(REBUILD_CHARTABLES)
+ add_executable(pcre2_dftables src/pcre2_dftables.c)
+ add_custom_command(
+ OUTPUT ${PROJECT_BINARY_DIR}/src/pcre2_chartables.c
+ COMMAND pcre2_dftables
+ ARGS ${PROJECT_BINARY_DIR}/src/pcre2_chartables.c
+ DEPENDS pcre2_dftables
+ COMMENT "Generating character tables (pcre2_chartables.c) for current locale"
+ VERBATIM
+ )
+elseif(NOT PCRE2_EBCDIC)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/src/pcre2_chartables.c.dist
+ ${PROJECT_BINARY_DIR}/src/pcre2_chartables.c
+ COPYONLY
+ )
+elseif(PCRE2_EBCDIC_NL25)
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/src/pcre2_chartables.c.ebcdic-1047-nl25
+ ${PROJECT_BINARY_DIR}/src/pcre2_chartables.c
+ COPYONLY
+ )
+else()
+ configure_file(
+ ${PROJECT_SOURCE_DIR}/src/pcre2_chartables.c.ebcdic-1047-nl15
+ ${PROJECT_BINARY_DIR}/src/pcre2_chartables.c
+ COPYONLY
+ )
+endif()
+
+# Source code
+
+set(PCRE2_HEADERS ${PROJECT_BINARY_DIR}/interface/pcre2.h)
+
+set(
+ PCRE2_SOURCES
+ src/pcre2_auto_possess.c
+ ${PROJECT_BINARY_DIR}/src/pcre2_chartables.c
+ src/pcre2_chkdint.c
+ src/pcre2_compile.c
+ src/pcre2_compile_cgroup.c
+ src/pcre2_compile_class.c
+ src/pcre2_config.c
+ src/pcre2_context.c
+ src/pcre2_convert.c
+ src/pcre2_dfa_match.c
+ src/pcre2_error.c
+ src/pcre2_extuni.c
+ src/pcre2_find_bracket.c
+ src/pcre2_jit_compile.c
+ src/pcre2_maketables.c
+ src/pcre2_match.c
+ src/pcre2_match_data.c
+ src/pcre2_match_next.c
+ src/pcre2_newline.c
+ src/pcre2_ord2utf.c
+ src/pcre2_pattern_info.c
+ src/pcre2_script_run.c
+ src/pcre2_serialize.c
+ src/pcre2_string_utils.c
+ src/pcre2_study.c
+ src/pcre2_substitute.c
+ src/pcre2_substring.c
+ src/pcre2_tables.c
+ src/pcre2_ucd.c
+ src/pcre2_valid_utf.c
+ src/pcre2_xclass.c
+)
+
+set(PCRE2POSIX_HEADERS ${PROJECT_BINARY_DIR}/interface/pcre2posix.h)
+set(PCRE2POSIX_SOURCES src/pcre2posix.c)
+
+if(MINGW AND BUILD_SHARED_LIBS)
+ if(EXISTS ${PROJECT_SOURCE_DIR}/pcre2.rc)
+ add_custom_command(
+ OUTPUT ${PROJECT_SOURCE_DIR}/pcre2.o PRE-LINK
+ COMMAND windres
+ ARGS pcre2.rc pcre2.o
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ COMMENT "Using pcre2 coff info in mingw build"
+ )
+ list(APPEND PCRE2_SOURCES ${PROJECT_SOURCE_DIR}/pcre2.o)
+ endif()
+
+ if(EXISTS ${PROJECT_SOURCE_DIR}/pcre2posix.rc)
+ add_custom_command(
+ OUTPUT ${PROJECT_SOURCE_DIR}/pcre2posix.o PRE-LINK
+ COMMAND windres
+ ARGS pcre2posix.rc pcre2posix.o
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ COMMENT "Using pcre2posix coff info in mingw build"
+ )
+ list(APPEND PCRE2POSIX_SOURCES ${PROJECT_SOURCE_DIR}/pcre2posix.o)
+ endif()
+endif()
+
+if(MSVC AND BUILD_SHARED_LIBS)
+ if(EXISTS ${PROJECT_SOURCE_DIR}/pcre2.rc)
+ list(APPEND PCRE2_SOURCES pcre2.rc)
+ endif()
+
+ if(EXISTS ${PROJECT_SOURCE_DIR}/pcre2posix.rc)
+ list(APPEND PCRE2POSIX_SOURCES pcre2posix.rc)
+ endif()
+endif()
+
+# Build setup
+
+add_compile_definitions(HAVE_CONFIG_H)
+
+if(PCRE2_DEBUG STREQUAL "IfDebugBuild")
+ add_compile_definitions("$<$:PCRE2_DEBUG>")
+elseif(PCRE2_DEBUG)
+ add_compile_definitions("PCRE2_DEBUG")
+endif()
+
+if(MSVC)
+ add_compile_definitions(_CRT_SECURE_NO_DEPRECATE _CRT_SECURE_NO_WARNINGS)
+endif()
+
+# Make sure to not link debug libs against release libs and vice versa.
+if(WIN32)
+ set(CMAKE_DEBUG_POSTFIX "d")
+endif()
+
+set(TARGETS)
+set(DLL_PDB_FILES)
+
+# 8-bit library
+
+if(PCRE2_BUILD_PCRE2_8)
+ if(BUILD_STATIC_LIBS)
+ add_library(pcre2-8-static STATIC ${PCRE2_HEADERS} ${PCRE2_SOURCES})
+ set_target_properties(
+ pcre2-8-static
+ PROPERTIES
+ COMPILE_DEFINITIONS PCRE2_CODE_UNIT_WIDTH=8
+ MACHO_COMPATIBILITY_VERSION "${LIBPCRE2_8_MACHO_COMPATIBILITY_VERSION}"
+ MACHO_CURRENT_VERSION "${LIBPCRE2_8_MACHO_CURRENT_VERSION}"
+ VERSION ${LIBPCRE2_8_VERSION}
+ SOVERSION ${LIBPCRE2_8_SOVERSION}
+ )
+ target_compile_definitions(pcre2-8-static PUBLIC PCRE2_STATIC)
+ target_include_directories(
+ pcre2-8-static
+ PUBLIC "$" "$"
+ )
+ if(REQUIRE_PTHREAD)
+ target_link_libraries(pcre2-8-static Threads::Threads)
+ endif()
+ list(APPEND TARGETS pcre2-8-static)
+ add_library(pcre2-posix-static STATIC ${PCRE2POSIX_HEADERS} ${PCRE2POSIX_SOURCES})
+ set_target_properties(
+ pcre2-posix-static
+ PROPERTIES
+ COMPILE_DEFINITIONS PCRE2_CODE_UNIT_WIDTH=8
+ MACHO_COMPATIBILITY_VERSION "${LIBPCRE2_POSIX_MACHO_COMPATIBILITY_VERSION}"
+ MACHO_CURRENT_VERSION "${LIBPCRE2_POSIX_MACHO_CURRENT_VERSION}"
+ VERSION ${LIBPCRE2_POSIX_VERSION}
+ SOVERSION ${LIBPCRE2_POSIX_SOVERSION}
+ )
+ target_link_libraries(pcre2-posix-static pcre2-8-static)
+ target_include_directories(
+ pcre2-posix-static
+ PUBLIC "$" "$"
+ )
+ list(APPEND TARGETS pcre2-posix-static)
+
+ if(MSVC)
+ set_target_properties(pcre2-8-static PROPERTIES OUTPUT_NAME pcre2-8-static)
+ set_target_properties(pcre2-posix-static PROPERTIES OUTPUT_NAME pcre2-posix-static)
+ else()
+ set_target_properties(pcre2-8-static PROPERTIES OUTPUT_NAME pcre2-8)
+ set_target_properties(pcre2-posix-static PROPERTIES OUTPUT_NAME pcre2-posix)
+ endif()
+ if(PCRE2_STATIC_PIC)
+ set_target_properties(pcre2-8-static pcre2-posix-static PROPERTIES POSITION_INDEPENDENT_CODE 1)
+ endif()
+ endif()
+
+ if(BUILD_SHARED_LIBS)
+ add_library(pcre2-8-shared SHARED ${PCRE2_HEADERS} ${PCRE2_SOURCES})
+ target_include_directories(
+ pcre2-8-shared
+ PUBLIC "$" "$"
+ )
+ set_target_properties(
+ pcre2-8-shared
+ PROPERTIES
+ COMPILE_DEFINITIONS PCRE2_CODE_UNIT_WIDTH=8
+ MACHO_COMPATIBILITY_VERSION "${LIBPCRE2_8_MACHO_COMPATIBILITY_VERSION}"
+ MACHO_CURRENT_VERSION "${LIBPCRE2_8_MACHO_CURRENT_VERSION}"
+ VERSION ${LIBPCRE2_8_VERSION}
+ SOVERSION ${LIBPCRE2_8_SOVERSION}
+ OUTPUT_NAME pcre2-8
+ )
+ if(REQUIRE_PTHREAD)
+ target_link_libraries(pcre2-8-shared Threads::Threads)
+ endif()
+ if(HAVE_VSCRIPT AND PCRE2_SYMVERS)
+ target_link_options(pcre2-8-shared PRIVATE -Wl,${VSCRIPT_FLAG},${PROJECT_BINARY_DIR}/src/libpcre2-8.sym)
+ set_target_properties(pcre2-8-shared PROPERTIES LINK_DEPENDS ${PROJECT_BINARY_DIR}/src/libpcre2-8.sym)
+ endif()
+ list(APPEND TARGETS pcre2-8-shared)
+ list(APPEND DLL_PDB_FILES $)
+
+ add_library(pcre2-posix-shared SHARED ${PCRE2POSIX_HEADERS} ${PCRE2POSIX_SOURCES})
+ target_include_directories(
+ pcre2-posix-shared
+ PUBLIC "$" "$"
+ )
+ set_target_properties(
+ pcre2-posix-shared
+ PROPERTIES
+ COMPILE_DEFINITIONS PCRE2_CODE_UNIT_WIDTH=8
+ MACHO_COMPATIBILITY_VERSION "${LIBPCRE2_POSIX_MACHO_COMPATIBILITY_VERSION}"
+ MACHO_CURRENT_VERSION "${LIBPCRE2_POSIX_MACHO_CURRENT_VERSION}"
+ VERSION ${LIBPCRE2_POSIX_VERSION}
+ SOVERSION ${LIBPCRE2_POSIX_SOVERSION}
+ OUTPUT_NAME pcre2-posix
+ )
+ if(HAVE_VSCRIPT AND PCRE2_SYMVERS)
+ target_link_options(pcre2-posix-shared PRIVATE -Wl,${VSCRIPT_FLAG},${PROJECT_BINARY_DIR}/src/libpcre2-posix.sym)
+ set_target_properties(pcre2-posix-shared PROPERTIES LINK_DEPENDS ${PROJECT_BINARY_DIR}/src/libpcre2-posix.sym)
+ endif()
+ target_compile_definitions(pcre2-posix-shared PUBLIC PCRE2POSIX_SHARED)
+ target_link_libraries(pcre2-posix-shared pcre2-8-shared)
+ list(APPEND TARGETS pcre2-posix-shared)
+ list(APPEND DLL_PDB_FILES $)
+
+ if(MINGW)
+ if(NON_STANDARD_LIB_PREFIX)
+ set_target_properties(pcre2-8-shared pcre2-posix-shared PROPERTIES PREFIX "")
+ endif()
+ if(NON_STANDARD_LIB_SUFFIX)
+ set_target_properties(pcre2-8-shared pcre2-posix-shared PROPERTIES SUFFIX "-0.dll")
+ endif()
+ endif()
+ endif()
+
+ if(BUILD_STATIC_LIBS)
+ add_library(pcre2-8 ALIAS pcre2-8-static)
+ add_library(pcre2-posix ALIAS pcre2-posix-static)
+ else()
+ add_library(pcre2-8 ALIAS pcre2-8-shared)
+ add_library(pcre2-posix ALIAS pcre2-posix-shared)
+ endif()
+endif()
+
+# 16-bit library
+
+if(PCRE2_BUILD_PCRE2_16)
+ if(BUILD_STATIC_LIBS)
+ add_library(pcre2-16-static STATIC ${PCRE2_HEADERS} ${PCRE2_SOURCES})
+ target_include_directories(
+ pcre2-16-static
+ PUBLIC "$" "$"
+ )
+ set_target_properties(
+ pcre2-16-static
+ PROPERTIES
+ COMPILE_DEFINITIONS PCRE2_CODE_UNIT_WIDTH=16
+ MACHO_COMPATIBILITY_VERSION "${LIBPCRE2_32_MACHO_COMPATIBILITY_VERSION}"
+ MACHO_CURRENT_VERSION "${LIBPCRE2_32_MACHO_CURRENT_VERSION}"
+ VERSION ${LIBPCRE2_16_VERSION}
+ SOVERSION ${LIBPCRE2_16_SOVERSION}
+ )
+ target_compile_definitions(pcre2-16-static PUBLIC PCRE2_STATIC)
+ if(REQUIRE_PTHREAD)
+ target_link_libraries(pcre2-16-static Threads::Threads)
+ endif()
+ list(APPEND TARGETS pcre2-16-static)
+
+ if(MSVC)
+ set_target_properties(pcre2-16-static PROPERTIES OUTPUT_NAME pcre2-16-static)
+ else()
+ set_target_properties(pcre2-16-static PROPERTIES OUTPUT_NAME pcre2-16)
+ endif()
+ if(PCRE2_STATIC_PIC)
+ set_target_properties(pcre2-16-static PROPERTIES POSITION_INDEPENDENT_CODE 1)
+ endif()
+ endif()
+
+ if(BUILD_SHARED_LIBS)
+ add_library(pcre2-16-shared SHARED ${PCRE2_HEADERS} ${PCRE2_SOURCES})
+ target_include_directories(
+ pcre2-16-shared
+ PUBLIC "$" "$"
+ )
+ set_target_properties(
+ pcre2-16-shared
+ PROPERTIES
+ COMPILE_DEFINITIONS PCRE2_CODE_UNIT_WIDTH=16
+ MACHO_COMPATIBILITY_VERSION "${LIBPCRE2_32_MACHO_COMPATIBILITY_VERSION}"
+ MACHO_CURRENT_VERSION "${LIBPCRE2_32_MACHO_CURRENT_VERSION}"
+ VERSION ${LIBPCRE2_16_VERSION}
+ SOVERSION ${LIBPCRE2_16_SOVERSION}
+ OUTPUT_NAME pcre2-16
+ )
+ if(REQUIRE_PTHREAD)
+ target_link_libraries(pcre2-16-shared Threads::Threads)
+ endif()
+ if(HAVE_VSCRIPT AND PCRE2_SYMVERS)
+ target_link_options(pcre2-16-shared PRIVATE -Wl,${VSCRIPT_FLAG},${PROJECT_BINARY_DIR}/src/libpcre2-16.sym)
+ set_target_properties(pcre2-16-shared PROPERTIES LINK_DEPENDS ${PROJECT_BINARY_DIR}/src/libpcre2-16.sym)
+ endif()
+ list(APPEND TARGETS pcre2-16-shared)
+ list(APPEND DLL_PDB_FILES $)
+
+ if(MINGW)
+ if(NON_STANDARD_LIB_PREFIX)
+ set_target_properties(pcre2-16-shared PROPERTIES PREFIX "")
+ endif()
+ if(NON_STANDARD_LIB_SUFFIX)
+ set_target_properties(pcre2-16-shared PROPERTIES SUFFIX "-0.dll")
+ endif()
+ endif()
+ endif()
+
+ if(BUILD_STATIC_LIBS)
+ add_library(pcre2-16 ALIAS pcre2-16-static)
+ else()
+ add_library(pcre2-16 ALIAS pcre2-16-shared)
+ endif()
+endif()
+
+# 32-bit library
+
+if(PCRE2_BUILD_PCRE2_32)
+ if(BUILD_STATIC_LIBS)
+ add_library(pcre2-32-static STATIC ${PCRE2_HEADERS} ${PCRE2_SOURCES})
+ target_include_directories(
+ pcre2-32-static
+ PUBLIC "$" "$"
+ )
+ set_target_properties(
+ pcre2-32-static
+ PROPERTIES
+ COMPILE_DEFINITIONS PCRE2_CODE_UNIT_WIDTH=32
+ MACHO_COMPATIBILITY_VERSION "${LIBPCRE2_32_MACHO_COMPATIBILITY_VERSION}"
+ MACHO_CURRENT_VERSION "${LIBPCRE2_32_MACHO_CURRENT_VERSION}"
+ VERSION ${LIBPCRE2_32_VERSION}
+ SOVERSION ${LIBPCRE2_32_SOVERSION}
+ )
+ target_compile_definitions(pcre2-32-static PUBLIC PCRE2_STATIC)
+ if(REQUIRE_PTHREAD)
+ target_link_libraries(pcre2-32-static Threads::Threads)
+ endif()
+ list(APPEND TARGETS pcre2-32-static)
+
+ if(MSVC)
+ set_target_properties(pcre2-32-static PROPERTIES OUTPUT_NAME pcre2-32-static)
+ else()
+ set_target_properties(pcre2-32-static PROPERTIES OUTPUT_NAME pcre2-32)
+ endif()
+ if(PCRE2_STATIC_PIC)
+ set_target_properties(pcre2-32-static PROPERTIES POSITION_INDEPENDENT_CODE 1)
+ endif()
+ endif()
+
+ if(BUILD_SHARED_LIBS)
+ add_library(pcre2-32-shared SHARED ${PCRE2_HEADERS} ${PCRE2_SOURCES})
+ target_include_directories(
+ pcre2-32-shared
+ PUBLIC "$" "$"
+ )
+ set_target_properties(
+ pcre2-32-shared
+ PROPERTIES
+ COMPILE_DEFINITIONS PCRE2_CODE_UNIT_WIDTH=32
+ MACHO_COMPATIBILITY_VERSION "${LIBPCRE2_32_MACHO_COMPATIBILITY_VERSION}"
+ MACHO_CURRENT_VERSION "${LIBPCRE2_32_MACHO_CURRENT_VERSION}"
+ VERSION ${LIBPCRE2_32_VERSION}
+ SOVERSION ${LIBPCRE2_32_SOVERSION}
+ OUTPUT_NAME pcre2-32
+ )
+ if(REQUIRE_PTHREAD)
+ target_link_libraries(pcre2-32-shared Threads::Threads)
+ endif()
+ if(HAVE_VSCRIPT AND PCRE2_SYMVERS)
+ target_link_options(pcre2-32-shared PRIVATE -Wl,${VSCRIPT_FLAG},${PROJECT_BINARY_DIR}/src/libpcre2-32.sym)
+ set_target_properties(pcre2-32-shared PROPERTIES LINK_DEPENDS ${PROJECT_BINARY_DIR}/src/libpcre2-32.sym)
+ endif()
+ list(APPEND TARGETS pcre2-32-shared)
+ list(APPEND DLL_PDB_FILES $)
+
+ if(MINGW)
+ if(NON_STANDARD_LIB_PREFIX)
+ set_target_properties(pcre2-32-shared PROPERTIES PREFIX "")
+ endif()
+ if(NON_STANDARD_LIB_SUFFIX)
+ set_target_properties(pcre2-32-shared PROPERTIES SUFFIX "-0.dll")
+ endif()
+ endif()
+ endif()
+
+ if(BUILD_STATIC_LIBS)
+ add_library(pcre2-32 ALIAS pcre2-32-static)
+ else()
+ add_library(pcre2-32 ALIAS pcre2-32-shared)
+ endif()
+endif()
+
+# Generate pkg-config files
+
+set(PACKAGE_VERSION "${PCRE2_MAJOR}.${PCRE2_MINOR}")
+set(prefix ${CMAKE_INSTALL_PREFIX})
+set(exec_prefix "\${prefix}")
+set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
+set(includedir "\${prefix}/include")
+
+set(LIB_POSTFIX "")
+if(WIN32 AND (CMAKE_BUILD_TYPE MATCHES Debug))
+ set(LIB_POSTFIX ${CMAKE_DEBUG_POSTFIX})
+endif()
+
+set(PCRE2_STATIC_CFLAG "")
+if(NOT BUILD_SHARED_LIBS)
+ set(PCRE2_STATIC_CFLAG "-DPCRE2_STATIC")
+endif()
+
+set(PCRE2POSIX_CFLAG "")
+if(BUILD_SHARED_LIBS)
+ set(PCRE2POSIX_CFLAG "-DPCRE2POSIX_SHARED")
+endif()
+
+set(PTHREAD_CFLAGS "")
+set(PTHREAD_LIBS "")
+if(REQUIRE_PTHREAD)
+ set(PTHREAD_CFLAGS "$")
+ set(PTHREAD_LIBS "$")
+endif()
+
+if(PCRE2_BUILD_PCRE2_8)
+ configure_file(libpcre2-posix.pc.in libpcre2-posix.pc.generator @ONLY)
+ file(GENERATE OUTPUT libpcre2-posix.pc INPUT "${PROJECT_BINARY_DIR}/libpcre2-posix.pc.generator")
+ list(APPEND pkg_config_files "${PROJECT_BINARY_DIR}/libpcre2-posix.pc")
+ configure_file(libpcre2-8.pc.in libpcre2-8.pc.generator @ONLY)
+ file(GENERATE OUTPUT libpcre2-8.pc INPUT "${PROJECT_BINARY_DIR}/libpcre2-8.pc.generator")
+ list(APPEND pkg_config_files "${PROJECT_BINARY_DIR}/libpcre2-8.pc")
+ set(enable_pcre2_8 "yes")
+else()
+ set(enable_pcre2_8 "no")
+endif()
+
+if(PCRE2_BUILD_PCRE2_16)
+ configure_file(libpcre2-16.pc.in libpcre2-16.pc.generator @ONLY)
+ file(GENERATE OUTPUT libpcre2-16.pc INPUT "${PROJECT_BINARY_DIR}/libpcre2-16.pc.generator")
+ list(APPEND pkg_config_files "${PROJECT_BINARY_DIR}/libpcre2-16.pc")
+ set(enable_pcre2_16 "yes")
+else()
+ set(enable_pcre2_16 "no")
+endif()
+
+if(PCRE2_BUILD_PCRE2_32)
+ configure_file(libpcre2-32.pc.in libpcre2-32.pc.generator @ONLY)
+ file(GENERATE OUTPUT libpcre2-32.pc INPUT "${PROJECT_BINARY_DIR}/libpcre2-32.pc.generator")
+ list(APPEND pkg_config_files "${PROJECT_BINARY_DIR}/libpcre2-32.pc")
+ set(enable_pcre2_32 "yes")
+else()
+ set(enable_pcre2_32 "no")
+endif()
+
+configure_file(pcre2-config.in pcre2-config @ONLY NEWLINE_STYLE LF)
+
+# Executables
+
+if(PCRE2_BUILD_PCRE2GREP)
+ add_executable(pcre2grep src/pcre2grep.c)
+ set_property(TARGET pcre2grep PROPERTY COMPILE_DEFINITIONS PCRE2_CODE_UNIT_WIDTH=8)
+ list(APPEND TARGETS pcre2grep)
+ target_link_libraries(pcre2grep pcre2-posix ${PCRE2GREP_LIBS})
+endif()
+
+# Testing
+
+if(PCRE2_BUILD_TESTS)
+ enable_testing()
+
+ set(PCRE2TEST_SOURCES src/pcre2test.c)
+
+ set(PCRE2TEST_LINKER_FLAGS "")
+ if(MSVC)
+ # This is needed to avoid a stack overflow error in the standard tests. The
+ # flag should be indicated with a forward-slash instead of a hyphen, but
+ # then CMake treats it as a file path.
+ set(PCRE2TEST_LINKER_FLAGS -STACK:2500000)
+ endif()
+
+ add_executable(pcre2test ${PCRE2TEST_SOURCES})
+ list(APPEND TARGETS pcre2test)
+ if(PCRE2_BUILD_PCRE2_8)
+ list(APPEND PCRE2TEST_LIBS pcre2-posix pcre2-8)
+ endif()
+ if(PCRE2_BUILD_PCRE2_16)
+ list(APPEND PCRE2TEST_LIBS pcre2-16)
+ endif()
+ if(PCRE2_BUILD_PCRE2_32)
+ list(APPEND PCRE2TEST_LIBS pcre2-32)
+ endif()
+ target_link_libraries(pcre2test ${PCRE2TEST_LIBS} ${PCRE2TEST_LINKER_FLAGS})
+
+ if(PCRE2_BUILD_PCRE2_8)
+ add_executable(pcre2posix_test src/pcre2posix_test.c)
+ target_link_libraries(pcre2posix_test pcre2-posix pcre2-8)
+ endif()
+
+ if(PCRE2_SUPPORT_JIT)
+ add_executable(pcre2_jit_test src/pcre2_jit_test.c)
+ set(PCRE2_JIT_TEST_LIBS)
+ if(PCRE2_BUILD_PCRE2_8)
+ list(APPEND PCRE2_JIT_TEST_LIBS pcre2-8)
+ endif()
+ if(PCRE2_BUILD_PCRE2_16)
+ list(APPEND PCRE2_JIT_TEST_LIBS pcre2-16)
+ endif()
+ if(PCRE2_BUILD_PCRE2_32)
+ list(APPEND PCRE2_JIT_TEST_LIBS pcre2-32)
+ endif()
+ target_link_libraries(pcre2_jit_test ${PCRE2_JIT_TEST_LIBS})
+ endif()
+
+ # =================================================
+ # Write out a CTest configuration file
+ #
+ file(
+ WRITE
+ ${PROJECT_BINARY_DIR}/CTestCustom.ctest
+ "# This is a generated file.
+MESSAGE(\"When testing is complete, review test output in the
+\\\"${PROJECT_BINARY_DIR}/Testing/Temporary\\\" folder.\")
+MESSAGE(\" \")
+"
+ )
+
+ file(
+ WRITE
+ ${PROJECT_BINARY_DIR}/pcre2_test.sh
+ "#! /bin/sh
+# This is a generated file.
+srcdir=${PROJECT_SOURCE_DIR}
+pcre2test=${PROJECT_BINARY_DIR}/pcre2test
+test -z \"$CMAKE_CONFIG_TYPE\" || pcre2test=${PROJECT_BINARY_DIR}/$CMAKE_CONFIG_TYPE/pcre2test
+. ${PROJECT_SOURCE_DIR}/RunTest
+if test \"$?\" != \"0\"; then exit 1; fi
+# End
+"
+ )
+
+ if(UNIX)
+ add_test(pcre2_test sh ${PROJECT_BINARY_DIR}/pcre2_test.sh)
+ endif()
+
+ if(PCRE2_BUILD_PCRE2GREP)
+ file(
+ WRITE
+ ${PROJECT_BINARY_DIR}/pcre2_grep_test.sh
+ "#! /bin/sh
+# This is a generated file.
+srcdir=${PROJECT_SOURCE_DIR}
+pcre2grep=${PROJECT_BINARY_DIR}/pcre2grep
+test -z \"$CMAKE_CONFIG_TYPE\" || pcre2grep=${PROJECT_BINARY_DIR}/$CMAKE_CONFIG_TYPE/pcre2grep
+pcre2test=${PROJECT_BINARY_DIR}/pcre2test
+test -z \"$CMAKE_CONFIG_TYPE\" || pcre2test=${PROJECT_BINARY_DIR}/$CMAKE_CONFIG_TYPE/pcre2test
+. ${PROJECT_SOURCE_DIR}/RunGrepTest
+if test \"$?\" != \"0\"; then exit 1; fi
+# End
+"
+ )
+
+ if(UNIX)
+ add_test(pcre2_grep_test sh ${PROJECT_BINARY_DIR}/pcre2_grep_test.sh)
+
+ if(PCRE2_EBCDIC)
+ # The grep tests currently fail in EBCDIC mode because the test data
+ # files are in ASCII. This could be fixed properly, but for now, we
+ # have very few EBCDIC users and the pcre2grep utility is hardly even
+ # part of the official project artifacts.
+ set_property(TEST pcre2_grep_test PROPERTY WILL_FAIL TRUE)
+ endif()
+ endif()
+ endif()
+
+ if(WIN32)
+ # Provide environment for executing the bat file version of RunTest
+ file(TO_NATIVE_PATH ${PROJECT_SOURCE_DIR} winsrc)
+ file(TO_NATIVE_PATH ${PROJECT_BINARY_DIR} winbin)
+
+ file(
+ WRITE
+ ${PROJECT_BINARY_DIR}/pcre2_test.bat
+ "\@REM This is a generated file.
+\@echo off
+setlocal
+SET srcdir=\"${winsrc}\"
+SET pcre2test=\"${winbin}\\pcre2test.exe\"
+if not [%CMAKE_CONFIG_TYPE%]==[] SET pcre2test=\"${winbin}\\%CMAKE_CONFIG_TYPE%\\pcre2test.exe\"
+call %srcdir%\\RunTest.bat
+if errorlevel 1 exit /b 1
+echo RunTest.bat tests successfully completed
+"
+ )
+
+ add_test(NAME pcre2_test_bat COMMAND pcre2_test.bat)
+ set_tests_properties(pcre2_test_bat PROPERTIES PASS_REGULAR_EXPRESSION "RunTest\\.bat tests successfully completed")
+
+ if(PCRE2_BUILD_PCRE2GREP)
+ file(
+ WRITE
+ ${PROJECT_BINARY_DIR}/pcre2_grep_test.bat
+ "\@REM This is a generated file.
+\@echo off
+setlocal
+SET srcdir=\"${winsrc}\"
+SET pcre2test=\"${winbin}\\pcre2test.exe\"
+if not [%CMAKE_CONFIG_TYPE%]==[] SET pcre2test=\"${winbin}\\%CMAKE_CONFIG_TYPE%\\pcre2test.exe\"
+SET pcre2grep=\"${winbin}\\pcre2grep.exe\"
+if not [%CMAKE_CONFIG_TYPE%]==[] SET pcre2grep=\"${winbin}\\%CMAKE_CONFIG_TYPE%\\pcre2grep.exe\"
+call %srcdir%\\RunGrepTest.bat
+if errorlevel 1 exit /b 1
+echo RunGrepTest.bat tests successfully completed
+"
+ )
+
+ add_test(NAME pcre2_grep_test_bat COMMAND pcre2_grep_test.bat)
+ set_tests_properties(
+ pcre2_grep_test_bat
+ PROPERTIES PASS_REGULAR_EXPRESSION "RunGrepTest\\.bat tests successfully completed"
+ )
+ endif()
+
+ if(DEFINED ENV{OSTYPE})
+ if("$ENV{OSTYPE}" STREQUAL "msys")
+ set(MSYS2 TRUE)
+ endif()
+ endif()
+ if(MSYS2)
+ # Both the sh and bat file versions of RunTest are run if make test is used
+ # in msys
+ add_test(pcre2_test_sh sh.exe ${PROJECT_BINARY_DIR}/pcre2_test.sh)
+ if(PCRE2_BUILD_PCRE2GREP)
+ add_test(pcre2_grep_test sh.exe ${PROJECT_BINARY_DIR}/pcre2_grep_test.sh)
+ endif()
+ endif()
+ endif()
+
+ # Changed to accommodate testing whichever location was just built
+
+ if(PCRE2_SUPPORT_JIT)
+ add_test(pcre2_jit_test pcre2_jit_test)
+ endif()
+
+ if(PCRE2_BUILD_PCRE2_8)
+ add_test(pcre2posix_test pcre2posix_test)
+ endif()
+endif()
+
+# Installation
+
+set(CMAKE_INSTALL_ALWAYS 1)
+
+install(
+ TARGETS ${TARGETS}
+ EXPORT pcre2-targets
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+)
+install(EXPORT pcre2-targets DESTINATION ${PCRE2_INSTALL_CMAKEDIR} NAMESPACE pcre2::)
+install(FILES ${pkg_config_files} DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
+install(
+ FILES "${PROJECT_BINARY_DIR}/pcre2-config"
+ DESTINATION ${CMAKE_INSTALL_BINDIR}
+ # Set 0755 permissions
+ PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
+)
+
+install(FILES ${PCRE2_HEADERS} ${PCRE2POSIX_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+
+# CMake config files.
+set(PCRE2_CONFIG_IN ${PROJECT_SOURCE_DIR}/cmake/pcre2-config.cmake.in)
+set(PCRE2_CONFIG_OUT ${PROJECT_BINARY_DIR}/cmake/pcre2-config.cmake)
+configure_package_config_file(${PCRE2_CONFIG_IN} ${PCRE2_CONFIG_OUT} INSTALL_DESTINATION ${PCRE2_INSTALL_CMAKEDIR})
+set(PCRE2_CONFIG_VERSION_OUT ${PROJECT_BINARY_DIR}/cmake/pcre2-config-version.cmake)
+write_basic_package_version_file(
+ ${PCRE2_CONFIG_VERSION_OUT}
+ VERSION ${PCRE2_MAJOR}.${PCRE2_MINOR}.0
+ COMPATIBILITY SameMajorVersion
+)
+install(FILES ${PCRE2_CONFIG_OUT} ${PCRE2_CONFIG_VERSION_OUT} DESTINATION ${PCRE2_INSTALL_CMAKEDIR})
+
+file(GLOB html ${PROJECT_SOURCE_DIR}/doc/html/*.html ${PROJECT_SOURCE_DIR}/doc/html/*.txt)
+file(
+ GLOB txts
+ ${PROJECT_SOURCE_DIR}/doc/*.txt
+ AUTHORS.md
+ COPYING
+ ChangeLog
+ LICENCE.md
+ NEWS
+ README
+ SECURITY.md
+ SUPPORT-LIFECYCLE.md
+)
+file(GLOB man1 ${PROJECT_SOURCE_DIR}/doc/*.1)
+file(GLOB man3 ${PROJECT_SOURCE_DIR}/doc/*.3)
+
+install(FILES ${man1} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
+install(FILES ${man3} DESTINATION ${CMAKE_INSTALL_MANDIR}/man3)
+install(FILES ${txts} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/pcre2)
+install(FILES ${html} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/doc/pcre2/html)
+
+if(MSVC AND INSTALL_MSVC_PDB)
+ install(
+ FILES ${DLL_PDB_FILES}
+ DESTINATION ${CMAKE_INSTALL_BINDIR}
+ CONFIGURATIONS Debug RelWithDebInfo
+ )
+endif()
+
+# Help, only for nice output
+if(BUILD_STATIC_LIBS)
+ set(BUILD_STATIC_LIBS ON)
+else()
+ set(BUILD_STATIC_LIBS OFF)
+endif()
+
+if(PCRE2_HEAP_MATCH_RECURSE)
+ message(WARNING "HEAP_MATCH_RECURSE is obsolete and does nothing.")
+endif()
+
+if(PCRE2_SHOW_REPORT)
+ message(STATUS "")
+ message(STATUS "")
+ message(STATUS "PCRE2-${PCRE2_MAJOR}.${PCRE2_MINOR} configuration summary:")
+ message(STATUS "")
+ message(STATUS " Install prefix .................... : ${CMAKE_INSTALL_PREFIX}")
+ message(STATUS " C compiler ........................ : ${CMAKE_C_COMPILER}")
+
+ set(CFSP "")
+ if(CMAKE_C_FLAGS)
+ set(CFSP " ")
+ endif()
+ if(CMAKE_CONFIGURATION_TYPES)
+ foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES)
+ string(TOUPPER "${config}" buildtype)
+ string(LENGTH " (${config})" buildtypelen)
+ math(EXPR dotslen "18 - ${buildtypelen}")
+ string(REPEAT "." ${dotslen} dots)
+ message(STATUS " C compiler flags (${config}) ${dots} : ${CMAKE_C_FLAGS}${CFSP}${CMAKE_C_FLAGS_${buildtype}}")
+ endforeach()
+ else()
+ string(TOUPPER "${CMAKE_BUILD_TYPE}" buildtype)
+ if(buildtype STREQUAL "")
+ set(CFBLD "")
+ else()
+ set(CFBLD "${CMAKE_C_FLAGS_${buildtype}}")
+ endif()
+ message(STATUS " C compiler flags .................. : ${CMAKE_C_FLAGS}${CFSP}${CFBLD}")
+ endif()
+
+ message(STATUS "")
+ if(CMAKE_CONFIGURATION_TYPES)
+ message(STATUS " Build configurations .............. : ${CMAKE_CONFIGURATION_TYPES}")
+ else()
+ message(STATUS " Build type ........................ : ${CMAKE_BUILD_TYPE}")
+ endif()
+ message(STATUS " Build 8 bit pcre2 library ......... : ${PCRE2_BUILD_PCRE2_8}")
+ message(STATUS " Build 16 bit pcre2 library ........ : ${PCRE2_BUILD_PCRE2_16}")
+ message(STATUS " Build 32 bit pcre2 library ........ : ${PCRE2_BUILD_PCRE2_32}")
+ message(STATUS " Include debugging code ............ : ${PCRE2_DEBUG}")
+ message(STATUS " Enable JIT compiling support ...... : ${PCRE2_SUPPORT_JIT}")
+ message(STATUS " Use SELinux allocator in JIT ...... : ${PCRE2_SUPPORT_JIT_SEALLOC}")
+ message(STATUS " Enable Unicode support ............ : ${PCRE2_SUPPORT_UNICODE}")
+ message(STATUS " Newline char/sequence ............. : ${PCRE2_NEWLINE}")
+ message(STATUS " \\R matches only ANYCRLF ........... : ${PCRE2_SUPPORT_BSR_ANYCRLF}")
+ message(STATUS " \\C is disabled .................... : ${PCRE2_NEVER_BACKSLASH_C}")
+
+ if(NOT EBCDIC)
+ set(EBCDIC_NL_CODE "n/a")
+ elseif(EBCDIC_NL25)
+ set(EBCDIC_NL_CODE "0x25")
+ else()
+ set(EBCDIC_NL_CODE "0x15")
+ endif()
+ message(STATUS " EBCDIC coding ..................... : ${EBCDIC}")
+ message(STATUS " EBCDIC code for NL ................ : ${EBCDIC_NL_CODE}")
+ message(STATUS " EBCDIC coding ignoring compiler ... : ${PCRE2_EBCDIC_IGNORING_COMPILER}")
+ message(STATUS " Rebuild char tables ............... : ${REBUILD_CHARTABLES}")
+
+ message(STATUS " Internal link size ................ : ${PCRE2_LINK_SIZE}")
+ message(STATUS " Maximum variable lookbehind ....... : ${PCRE2_MAX_VARLOOKBEHIND}")
+ message(STATUS " Nested parentheses limit .......... : ${PCRE2_PARENS_NEST_LIMIT}")
+ message(STATUS " Heap limit ........................ : ${PCRE2_HEAP_LIMIT}")
+ message(STATUS " Match limit ....................... : ${PCRE2_MATCH_LIMIT}")
+ message(STATUS " Match depth limit ................. : ${PCRE2_MATCH_LIMIT_DEPTH}")
+ message(STATUS " Build shared libs ................. : ${BUILD_SHARED_LIBS}")
+ if(NOT HAVE_VSCRIPT)
+ message(STATUS " with symbol versioning ........ : n/a")
+ else()
+ message(STATUS " with symbol versioning ........ : ${PCRE2_SYMVERS}")
+ endif()
+ message(STATUS " Build static libs ................. : ${BUILD_STATIC_LIBS}")
+ message(STATUS " with PIC enabled .............. : ${PCRE2_STATIC_PIC}")
+ message(STATUS " Build pcre2grep ................... : ${PCRE2_BUILD_PCRE2GREP}")
+ message(STATUS " Enable JIT in pcre2grep ........... : ${PCRE2GREP_SUPPORT_JIT}")
+ message(STATUS " Enable callouts in pcre2grep ...... : ${PCRE2GREP_SUPPORT_CALLOUT}")
+ message(STATUS " Enable callout fork in pcre2grep .. : ${PCRE2GREP_SUPPORT_CALLOUT_FORK}")
+ message(STATUS " Initial buffer size for pcre2grep . : ${PCRE2GREP_BUFSIZE}")
+ message(STATUS " Maximum buffer size for pcre2grep . : ${PCRE2GREP_MAX_BUFSIZE}")
+ message(STATUS " Build tests (implies pcre2test .... : ${PCRE2_BUILD_TESTS}")
+ message(STATUS " and pcre2grep)")
+ if(ZLIB_FOUND)
+ message(STATUS " Link pcre2grep with libz .......... : ${PCRE2_SUPPORT_LIBZ}")
+ else()
+ message(STATUS " Link pcre2grep with libz .......... : Library not found")
+ endif()
+ if(BZip2_FOUND)
+ message(STATUS " Link pcre2grep with libbz2 ........ : ${PCRE2_SUPPORT_LIBBZ2}")
+ else()
+ message(STATUS " Link pcre2grep with libbz2 ........ : Library not found")
+ endif()
+ if(Editline_FOUND)
+ message(STATUS " Link pcre2test with libeditline ... : ${PCRE2_SUPPORT_LIBEDIT}")
+ else()
+ message(STATUS " Link pcre2test with libeditline ... : Library not found")
+ endif()
+ if(Readline_FOUND)
+ message(STATUS " Link pcre2test with libreadline ... : ${PCRE2_SUPPORT_LIBREADLINE}")
+ else()
+ message(STATUS " Link pcre2test with libreadline ... : Library not found")
+ endif()
+ message(STATUS " Enable Valgrind support ........... : ${PCRE2_SUPPORT_VALGRIND}")
+ if(PCRE2_DISABLE_PERCENT_ZT)
+ message(STATUS " Use %zu and %td ................... : OFF")
+ else()
+ message(STATUS " Use %zu and %td ................... : AUTO")
+ endif()
+
+ if(MINGW AND BUILD_SHARED_LIBS)
+ message(STATUS " Non-standard dll names (prefix) ... : ${NON_STANDARD_LIB_PREFIX}")
+ message(STATUS " Non-standard dll names (suffix) ... : ${NON_STANDARD_LIB_SUFFIX}")
+ endif()
+
+ if(MSVC)
+ message(STATUS " Install MSVC .pdb files ........... : ${INSTALL_MSVC_PDB}")
+ endif()
+
+ message(STATUS "")
+endif()
+
+# end CMakeLists.txt
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..c233950
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,5 @@
+PCRE2 LICENCE
+
+Please see the file LICENCE in the PCRE2 distribution for licensing details.
+
+End
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..01fc8cd
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,3518 @@
+Change Log for PCRE2
+--------------------
+
+Before the move to GitHub, this was the only record of changes to PCRE2. Now
+there is also the log of commit messages.
+
+Internal changes which are not visible to clients of the library are mostly not
+listed here.
+
+
+Version 10.48 31-August-2026
+----------------------------
+
+1. (#826) [GHSA-q7rw-r7qq-2hx6] Initialized alignment padding in serialized
+character lists so that pcre2_serialize_encode() does not expose two
+uninitialised bytes from malloc().
+
+2. (#825) Fixed the casing of CMake package variables and corrected
+Readline/ncurses linkage.
+
+3. (#830) Updated Unicode support to Unicode 17.0, including new scripts,
+characters, properties, case mappings, and emoji data.
+
+4. (a9d4a748) Renamed the default development branch from master to main.
+
+5. (574f5683) Allowed PCRE2_NO_UTF_CHECK to differ between an existing match
+and pcre2_substitute() with PCRE2_SUBSTITUTE_MATCHED, instead of returning
+PCRE2_ERROR_DIFFSUBSOPTIONS.
+
+6. (#841) Fixed incorrect compilation and matching of character classes that
+combine characters from multiple internal ranges, including characters at or
+below U+00FF together with characters at U+0100 and U+8000 or above.
+
+7. (#849) Reduced the memory used by each pcre2_match() heap frame by shrinking
+temporary fields.
+
+8. (#852) Added interpreter and JIT support for possessive repeats of
+backreferences.
+
+9. (#857) Fixed a regression in pcre2_substitute() that mishandled repeated
+backslash escapes in extended replacement strings.
+
+10. (#858) Added improvements to pcre2_substitute(). Support for partial matches
+with PCRE2_SUBSTITUTE_REPLACEMENT_ONLY added, and added
+PCRE2_ERROR_PARTIALSUBS for replacements containing $' or $_ which cannot be
+expanded for partial matches.
+
+11. (#859, 30c9faa4) Expanded pcre2-config's recognition of system library
+directories on Linux (multilib and multiarch), and AIX and Solaris, avoiding
+unnecessary -L options.
+
+12. (#875) Fixed a stale repeat value while constructing JIT scan prefixes,
+which could cause missed matches when a prefix was followed by a bounded
+character-class repeat with a zero minimum.
+
+13. (#879) Fixed build warnings in pcre2grep with C23 and glibc 2.43, by retaining
+const qualifiers from strstr() and strchr().
+
+14. (#883) Prevented generator expressions inherited from a parent CMake
+project from entering CMAKE_REQUIRED_DEFINITIONS during configuration checks.
+
+15. (#884, #880) Made symbol-version scripts platform-specific, fixing Solaris SPARC
+symbol versioning.
+
+16. (#888) Fixed memory leaks and stale-pointer double frees when
+pcre2_deserialize_decode() rejects an invalid block size.
+
+17. (#894) Updated Zig's build.zig, including exported headers, hidden symbol
+visibility, and sanitizer support.
+
+18. (#893) Changed pcre2test builds to detect setrlimit() instead of relying on
+a hard-coded platform list.
+
+19. (#907) Added support for installing PCRE2 directly with `zig fetch`,
+including a Zig package manifest and release integration.
+
+20. (#912) Fixed a JIT-specific bug in variable-length lookbehinds which caused
+incorrect match results during backtracking.
+
+21. (#863) Added a five-year support lifecycle policy and publication of backport
+patches for security and high-severity fixes in older releases.
+
+22. (#937) Fixed a leak and later invalid free when calling the fast-path
+pcre2_jit_match() function with a match data object previously used with
+pcre2_match() and PCRE2_COPY_MATCHED_SUBJECT. No security advisory, as this is
+considered unlikely to affect applications.
+
+23. (#936) Made pcre2grep recognize -- during positional argument processing,
+for improved compatibility with GNU grep.
+
+24. (#922) Added support for Zig JIT builds to fetch SLJIT through the Zig
+package manager when the Git submodule is absent. The minimum Zig version
+is raised to 0.16.0.
+
+25. (#926) [GHSA-2p8c-ff85-vh9x] If pcre2_jit_compile() is called with options
+for some match modes, and then pcre2_match() is used to perform a match for a
+different match mode, an out-of-bounds read can occur if the match is attempted
+against invalid UTF input. The interpreter fallback now performs its own UTF
+validation correctly when some JIT match modes have been compiled, but not the
+requested mode.
+
+26. (#909) [GHSA-q8g2-wprr-34m9] If pcre2_convert() is called on untrusted input
+on platforms with 32-bit size_t, an out-of-bounds heap write can occur.
+Additionally, the allocation made was larger than required in common cases.
+Added overflow checks for allocations in pattern conversion and substring APIs.
+
+27. (#945) Fixed JIT character advancement with PCRE2_MATCH_INVALID_UTF in
+UTF-8 and UTF-16 modes. Valid multi-code-unit characters are now advanced as a
+unit, while invalid characters advance by one code unit, preventing adjacent
+characters from being skipped.
+
+28. (#948) Fixed one-past-the-end compile error offsets for incomplete \x{,
+\o{, and \N{U+ escapes at the end of a pattern.
+
+29. (#947) Clarified documentation for PCRE2_DFA_RESTART, which does not remove
+the requirement to retain previously supplied subject data, including sufficient
+history for nested lookbehinds.
+
+30. (#942, #954) Fixed pcre2grep handling for \K matches whose end offset precedes
+their start offset. Such ranges could previously cause an unsigned match-length
+underflow.
+
+31. (#956) Fixed an integer overflow in pcre2grep when advancing multiline
+output state, and preserved pending output when crossing lines.
+
+32. (#957) Updated bundled SLJIT with architecture-specific code-generation and
+portability fixes.
+
+33. (#958) Fixed CMake installation of MSVC PDB files when
+CMAKE_SHARED_LIBRARY_PREFIX_C is customized.
+
+34. (#961, #962) Fixed two compilation issues preventing use of extended
+(Boolean) character classes before a lookbehind, or inside a lookaround.
+
+35. (GHSA-3r4p-g7gg-ppmf) Fixed an out-of-bounds write in DFA matching when
+using a heap limit; also fixed possible integer overflows which could cause
+under-allocation of the workspace.
+
+36. (GHSA-fmgr-6ggq-9859) Added bounds checks for several integer overflows
+while compiling patterns on 32-bit CPUs, which could cause under-allocation
+followed by out-of-bounds writes.
+
+37. (GHSA-9qww-pwc4-77qq) Applied lower buffer bound to prevent two
+out-of-bounds reads while scanning backwards through invalid UTF data with
+PCRE2_MATCH_INVALID_UTF.
+
+
+Version 10.47 21-October-2025
+-----------------------------
+
+1. (#660, #655, #663) Expanded platforms tested by CI: FreeBSD, OpenBSD,
+Solaris, MSYS (Cygwin), S390x, PPC64le, ARMv7, AARCH64, RiscV.
+
+2. (#655) Made build clean of `/W3` warnings on MSVC. Further suppression of
+minor build warnings on other platforms (various commits).
+
+3. (#651) Added `--enable-Werror` flag to `./configure` to treat warnings as
+errors (or `--enable-errwarn` for Solaris cc). Previously, you had to hackily
+override the CPPFLAGS when calling make since you can't pass `-Werror` as a
+CFLAG into `./configure` (it breaks compiler feature detection).
+
+4. (#682) Added AM_MAINTAINER_MODE for Git tag releases. Users building with
+the `./configure` script can check out the release tag using Git, which assigns
+the current time as the modification time to each checked-out file. This caused
+Autoconf to attempt to regenerate the configure script.
+
+5. (#692) Add LICENSE file for sljit to the tarball release, to clarify that the
+sljit code is governed separately by the 2-clause BSD license.
+
+6. (#656, #695) Add full support for z/OS and native EBCDIC support. The z/OS
+support is tested nightly using the XLC and IBM-Clang compilers, with Autoconf
+and CMake. In addition, for test purposes, the EBCDIC support can now be enabled
+on any platform using the new Autoconf `--enable-ebcdic-ignoring-compiler` and
+CMake `-DPCRE2_EBCDIC_IGNORING_COMPILER` options.
+
+7. (#700) Faster lookup of named capture groups during pattern compilation using
+a hash table.
+
+8. (#697, #756, #778) Improvements to pcre2test to increase code coverage:
+-malloc argument; more detailed test assertions.
+
+9. (#705, #710, #737, #738) Powerful new feature: pattern recursion of
+the form "(?1(GROUP_NAME_OR_NUM,...))" acts as a subroutine call which
+additionally returns the listed capturing groups to the calling context.
+
+10. (#721) Add linker scripts to enable symbol versioning for the PCRE2 dynamic
+libraries. Downstream Linux distributions may make use of this, or disable it
+with the new Autoconf `--disable-symvers` and CMake `-DPCRE2_SYMVERS` options.
+Currently, Linux, Solaris, and FreeBSD (GNU ld, LLVM lld, and Solaris ld) are
+tested and supported.
+
+11. (#733) New API function: pcre2_next_match(). This function makes it both
+simpler and safer for clients to iterate over all matches in a subject. The
+documentation in `pcre2api` also provides improved guidance in the section
+"Iterating over all matches".
+
+12. (#739, #744, #753) Modernize the CMake build files, to use standard
+commands to export the PCRE2 targets. This makes use of the
+"$" and "$" expressions alongside
+the built-in "install(EXPORT...)" command. This brings the CMake files in line
+with the patches used by vcpkg to distribute PCRE2. The minimum CMake version
+remains 3.15.
+
+13. (#756) Improved error offsets and diagnostics for syntax errors during
+pattern compilation.
+
+14. (#708, #729, #724, #731, #777) Various updates to Bazel and Zig
+build support.
+
+15. (#775) Added PCRE2_CONFIG_EFFECTIVE_LINKSIZE option to pcre2_config(), to
+report the actual number of code units used in compiled patterns for recording
+string lengths and offsets.
+
+16. (#801) Significant bugfix: Fix a crash in pcre2_callout_enumerate() which is
+easily reachable on any pattern that contains a Unicode character class. If your
+application uses this function, please read the details for this change and
+evaluate its severity for your application.
+
+17. (#806, #807) Improved input validation for pcre2_substitute() used with
+PCRE2_SUBSTITUTE_MATCHED.
+
+18. (#817) Add support for $+ replacement to pcre2_substitute().
+
+19. (#818) New SIMD code generation in the JIT for AArch64.
+
+
+Version 10.46 27-August-2025
+----------------------------
+
+1. (#771) (CVE-2025-58050) Security fix to prevent a read-past-the-end memory
+error, of arbitrary length. An attacker-controlled regex pattern is required,
+and it cannot be triggered by providing crafted subject (match) text. The
+(*ACCEPT) and (*scs:) pattern features must be used together.
+
+Release 10.44 and earlier are not affected.
+
+This could have implications of denial-of-service or information disclosure,
+and could potentially be used to escalate other vulnerabilities in a system
+(such as information disclosure being used to escalate the severity of an
+unrelated bug in another system).
+
+
+Version 10.45 05-February-2025
+------------------------------
+
+1. (#418) Change 6 of 10.44 broke 32-bit tests because pcre2test's reporting of
+memory size was changed to the entire compiled data block, instead of just the
+pattern and tables data, so as to align with the new length restriction.
+Because the block's header contains pointers, this meant the pcre2test output
+was different in 32-bit mode. A patch by Carlo reverts to the previous state
+and makes sure that any limit set by pcre2_set_max_pattern_compiled_length()
+also avoids the internal struct overhead.
+
+2. (#416, #622) Updates to build.zig.
+
+3. (#427, et al.) Various fixes to pacify static analyzers.
+
+4. (#428) Add --posix-pattern-file to pcre2grep to allow processing of empty
+patterns through the -f option, as well as patterns that end in space
+characters, for compatibility with other grep tools.
+
+5. (4fa5b8bd) Fix a bug in the fuzz support quantifier-limiting code. It ignores
+strings of more than 5 digits because they are necessarily numbers greater than
+65535, the largest legal quantifier. However, it wasn't ignoring non-significant
+leading zeros.
+
+6. (6d82f0cd) The case-independent processing of the letter-matching Unicode
+properties Ll, Lt, and Lu have been changed to match Perl (which changed a while
+ago). When caseless matching is in force, all three of these properties are now
+treated as Lc (cased letter).
+
+7. (#433) The pcre2_jit_compile() function was updated by the addition of a new
+option PCRE2_JIT_TEST_ALLOC which, if called with a NULL first argument, tests
+not only the availability of JIT, but also its ability to allocate executable
+memory. Update pcre2test to use this support to extend the -C option.
+
+8. (75b1025a) The code for parsing Unicode property descriptions for \p and \P
+been changed as follows:
+
+ . White space etc. before ^ in a negated value such as \p{ ^L } was not being
+ ignored.
+
+ . The code wouldn't have worked if PCRE2 was compiled for UTF-8 support
+ within an EBCDIC environment. Possibly nobody does this any more, but it
+ should now work.
+
+ . The documentation of the syntax of what can follow \p and \P has been
+ updated.
+
+9. (1c24ba01) There was an error in the table of lengths for parsed items for
+the OPTIONS item, but fortuitously it could never have actually bitten. While
+fixing this, some other code that could never be obeyed was discovered and
+removed.
+
+10. (674b6640) Removed some incorect optimization code from DFA matching that
+has been there since PCRE1, but has just been found to cause a no match return
+instead of a partial match in some cases. It involves partial matching when (*F)
+is present so is unlikely to have actually affected anyone.
+
+11. (b0f4ac17) Tidy the wording and formatting of some pcre2test error messages
+concerned with bad modifiers. Also restrict single-letter modifier sequences to
+the first item in a modifier list, as documented and always intended.
+
+12. (1415565c) An iterator at the end of many assertions can always be
+auto-possessified, but not at the end of variable-length lookbehinds. There was
+a bug in the code that checks for such a lookbehind; it was looking only at the
+first branch, which is wrong because some branches can be fixed length when
+others are not, for example (?<=AB|CD?). Now all branches are checked for
+variability.
+
+13. (ead08288) Matching with pcre2_match() could give an incorrect result if a
+variable-length lookbehind was used as the condition in a conditional group.
+The condition could erroneously be treated as true if a branch matched but
+overran the current position. This bug was in the interpreter only; matching
+with JIT was correct.
+
+14. (#443) Split out the sljit sub-project into a "Git submodule". Git users
+must now run `git submodule init; git submodule update` after a Git checkout, or
+the build will fail due to missing files in deps/sljit.
+
+15. (#441) Add a new error code (PCRE2_ERROR_JIT_UNSUPPORTED) which is yielded
+for unsupported jit features.
+
+16. (#444) Fix bug in 'first code unit' and 'last code unit' optimization
+combined with lookahead assertions.
+
+17. (#445, #447, #449, #451, #452, #459, #563) Add a new feature called scan
+substring. This feature is a new type of assertion which matches the content of
+a capturing block to a sub-pattern.
+
+18. (#450) Improvements to 'first code unit' / 'starting code units'
+optimisation.
+
+19. (#455) Many, many improvements to the JIT compiler.
+
+20. Item 43 of 10.43 was incomplete because it addressed only \z and not \Z,
+which was still misbehaving when matching fragments inside invalid UTF strings.
+
+21. (d29e7290) Octal escapes of the form \045 or \111 were not being recognized
+in substitution strings, and if encountered gave an error, though the \o{...}
+form was recognized. This bug is now fixed.
+
+22. (#463, #487) Fix 1 byte out-of-bounds read when parsing malformed limits
+(e.g. LIMIT_HEAP)
+
+23. Many improvements to test infrastructure. Many more platforms and
+configurations are now run in Continuous Integration, and all the platforms now
+run the full test suite, rather than a partial subset.
+
+24. (#475) Implement title casing in substitution strings using Perl syntax.
+
+25. (#478, #504) Disallow \x if not followed by { or a hex digit.
+
+26. (#473) Implements Python-style backrefs in substitutions.
+
+27. (#472) Fix error reporting for certain over-large octal escapes.
+
+28. (#482) Fix parsing of named captures in replacement strings, allowing
+non-ASCII capture names to be used.
+
+29. (#477, #474, #488, #494, #496, #506, #508, #511, #518, #524, #540) Many
+improvements to parsing and optimising of character classes.
+
+30. (#483, #498) Add support for \g and $ to replacement strings.
+
+31. (#470) Add option flags PCRE2_EXTRA_NO_BS0 and PCRE2_EXTRA_PYTHON_OCTAL.
+
+32. (#471) Add new API function pcre2_set_optimize() for controlling which
+optimizations are enabled.
+
+33. (#491) Adds $& $` $' and $_ to substitution replacements, as well as
+interpreting \b and \v as characters.
+
+34. (#499) Add option PCRE2_EXTRA_NEVER_CALLOUT to disable callouts.
+
+35. (#503, #513) Update Unicode support to UCD 16.
+
+36. (#512, #618, #638) Add new function pcre2_set_substitute_case_callout() to
+allow clients to provide a custom callback with locale-aware case
+transformation.
+
+37. (#516) Fix case-insensitive matching of backreferences when using the
+PCRE2_EXTRA_CASELESS_RESTRICT option.
+
+38. (#519) In pcre2grep, add $& as an alias for $0
+
+39. (c9bf8339, #534) Updated perltest.sh to enable locale setting.
+
+40. (#521) Add support for Turkish I casefolding, using new options
+PCRE2_EXTRA_TURKISH_CASING, and added pre-pattern flags (*TURKISH_CASING) and
+(*CASELESS_RESTRICT).
+
+41. (#523, #546, #547) Add support for UTS#18 compatible character classes,
+using the new option PCRE2_ALT_EXTENDED_CLASS. This adds '[' as a metacharacter
+within character classes and the operators '&&', '--' and '~~', allowing
+subtractions and intersections of character classes to be easily expressed.
+
+42. (#553, #586, #596, #597) Add support for Perl-style extended character
+classes, using the syntax (?[...]). This also allows expressing subtractions and
+intersections of character classes, but using a different syntax to UTS#18.
+
+43. (#554) Fixed a bug in JIT affecting greedy bounded repeats. The upper limit
+of repeats inside a repeated bracket might be incorrectly checked.
+
+44. (#556) Fixed a bug in JIT affecting caseful matching of backreferences. When
+utf is disabled, and dupnames is enabled, caseless matching was used even
+if caseful matching was needed.
+
+45. (f34fc0a3) Fixed a bug in pcre2grep reported by Alejandro Colomar
+ (GitHub issue #577). In certain cases, when lines of above and
+below context were contiguous, a separator line was incorrectly being inserted.
+
+46. (#594) Fix a small (one/two byte) out-of-bounds read on invalid UTF-8 input
+in pcre2grep.
+
+47. (#370) Fix the INSTALL_MSVC_PDB CMake flag.
+
+48. (#366) Install cmake files in prefix/lib/cmake/pcre2 rather than
+prefix/cmake. The new CMake flag PCRE2_INSTALL_CMAKEDIR allows customising this
+location.
+
+49. (#624, #626, #628, #632, #639, #641) Reduce code size of generated JIT code
+for repeated character classes.
+
+50. (#623) Update the Bazel build files.
+
+
+Version 10.44 07-June-2024
+--------------------------
+
+1. If a pattern contained a variable-length lookbehind in which the first
+branch was not the one with the shortest minimum length, and the lookbehind
+contained a capturing group, and elsewhere in the pattern there was another
+lookbehind that referenced that group, the pattern was incorrectly compiled,
+leading to unpredictable results, including crashes in JIT compiling. An
+example pattern is: /(((?<=123?456456|ABC)))(?<=\2)/
+
+2. Further updates to the oss-fuzz support:
+
+ (a) Limit quantifiers for groups and classes to be no more than 10. This
+ avoids very long JIT compile times that happen in some cases when groups
+ are replicated for quantification, and very long match times when
+ classes contain a lot of non-ascii characters.
+
+ (b) Added PCRE2_EXTENDED_MORE to the list of allowed options.
+
+ (c) Arranged for text error messages to be shown in 16-bit and 32-bit modes.
+
+ (d) Made the output in standalone mode more readable.
+
+ (e) General code tidies.
+
+ (f) Limit the size of compiled patterns to 10MB (see 6 below).
+
+ (g) Do not run JIT on patterns whose compiled length is greater than 200K
+ bytes because this takes a long time, causing oss-fuzz to time out.
+
+ (h) Avoid compiling or matching twice with the same options (this could
+ happen if the input didn't set any options).
+
+3. Increase the maximum length of a name for a group from 32 to 128 because
+there is a user for whom 32 is too small.
+
+4. Cause pcre2test to output a message when pcre2_jit_compile() gives an error
+return if either jitverify or info is specified.
+
+5. Some auxiliary files for building under OpenVMS that were contributed by
+Alexey Chupahin have been installed.
+
+6. Added pcre2_set_max_pattern_compiled_length() to limit the size of compiled
+patterns.
+
+7. There was a bug in the implementation of \X caused by my (PH) misreading or
+misunderstanding one of the grapheme sequence breaking rules in Unicode Annex
+#29. A break should occur between two characters with the Extended Pictographic
+break property unless a zero-width joiner intervenes. PCRE2 was not insisting
+on the ZWJ, causing \X to match more than it should. See GitHub issue #410.
+
+8. Avoid compilation issues with proprietary compilers in UNIX since 10.43.
+
+
+Version 10.43 16-February-2024
+------------------------------
+
+1. The test program added by change 2 of 10.42 didn't work when the default
+newline setting didn't include \n as a newline. One test needed (*LF) to ensure
+that it worked.
+
+2. Added the new freestanding POSIX test program to the ManyConfigTests script
+in the maint directory (overlooked in 2 below). Also improved the selection
+facilities in that script, and added a test with JIT in a non-source directory,
+fixing an oversight that would have made such a test fail before.
+
+3. Added pcre2_get_match_data_heapframes_size() and related pcre2test flags
+to allow for finer control of the heap used when pcre2_match() without JIT is
+used and the match_data might be reused. This began as PR #191, but has had
+further refinement and documentation edits.
+
+4. Applied PR #181, which tidies some casts in pcre2_valid_utf.c.
+
+5. Applied PR #184, which avoids overflow issues with the heap limit
+(introduced in 10.41/9).
+
+6. Applied PR #192, which changes the timing units for pcre2test from
+milliseconds to microseconds. This is more useful for modern CPUs.
+
+7. Applied PR #193, which makes the requirement for C99 explicit in
+configure.ac and CMakeLists.txt.
+
+8. Fixed a bug in pcre2test when a ridiculously large string repeat required a
+stupid amount of memory. It now gives a clean realloc() failure error.
+
+9. Updates to restrict the interaction between ASCII and non-ASCII characters
+for caseless matching and items like \d:
+
+ (a) Added PCRE2_EXTRA_CASELESS_RESTRICT to lock out mixing of ASCII and
+ non-ASCII when matching caselessly. This is also /r in pcre2test and
+ (?r) within patterns.
+
+ (b) Added PCRE2_EXTRA_ASCII_{BSD,BSS,BSW,POSIX} and corresponding (?aD) etc
+ in patterns and /a in pcre2test.
+
+ (c) Corresponding updates to pcre2test.
+
+10. Unicode has been updated to 15.0.0.
+
+11. The Python scripts and ucptest.c in maint have been updated (a) a minor
+change needed for 9(a) above; (b) fix bugs in ucptest,
+
+12. Integer overflow testing is now centralized in a new function.
+
+13. Made PCRE2_UCP the default in UTF mode in pcre2grep, and added new options
+--case-restrict and --no-ucp.
+
+14. In the debugging printint module (which is normally only linked into
+pcre2test), avoid the use of a variable called "not" because that's deprecated
+in C and forbidden in C++. Also rewrite some code to avoid a goto into a block
+that bypassed its initialization (though it didn't actually matter).
+
+15. More minor code adjustments to avoid using reserved C++ words as variable
+names ("new" and "typename") and another jump that bypassed an (irrelevant)
+initialization.
+
+16. Merged a pull request that removed pcre2_ucptables.c from the list of files
+to compile in NON-AUTOTOOLS-BUILD because it is #included in pcre2_tables.c.
+Also adjusted the BUILD.bazel and build.zig files, which had the same issue. At
+the same time, fixed a typo in the Bazel file.
+
+17. Add PCRE2_EXTRA_ASCII_DIGIT to allow [:digit:] to be kept on sync with \d
+even in UCP mode.
+
+18. Fix an invalid match of ascii word classes when invalid utf is enabled.
+
+19. Add a --posix-digit to pcre2grep for compatibility with GNU grep, and
+other tools that prefer the POSIX compatible unicode definition for \d.
+
+20. Report the bit width of the library in use by pcre2test for usability.
+
+21. A pathological pattern conversion test could result in a string longer than
+the available input buffer. Cause such a test to fail.
+
+22. Add a check that forces a compiler error if PCRE2_CODE_UNIT_WIDTH is not 8,
+16, or 32 when compiling any of the library modules.
+
+23. Update pcre2_compile() to treat a NULL pattern with zero length as an empty
+string.
+
+24. Add support for limited-length variable-length lookbehind assertions, with
+default maximum length 255 characters (same as Perl) but with a function to
+adjust the limit.
+
+25. Applied pull request #262, which updates the zig configuration, and #278
+which fixes a bug with out-of-source-tree CMake build testing.
+
+26. Add support for LoongArch to JIT.
+
+27. Fixed a bug in pcre2_match() in the code for handling the vector of
+backtracking frames on the heap, which caused a heap overflow if *LIMIT_HEAP
+restricted an attempt to extend to less than the frame size. Generally tidy up
+the code for extending the heap frames vector. This fixes GitHub issue #275.
+
+28. Update pcre2_fuzzsupport.c to avoid clang sanitize complaint about shifting
+left by 16 when there are non-zeros in the top 16 bits.
+
+29. Perl 5.34.0 changed the meaning of (for example) {,3} which did not used to
+be treated as a quantifier. Now it is interpreted as {0,3} and PCRE2 has
+changed to match. Note that {,} is still not a quantifier.
+
+30. Perl allows spaces and/or horizontal tabs after { or before } in all items
+that use braces, and also before or after the comma in quantifiers. PCRE2 now
+does the same, except for \u{...}, which is recognized only when
+PCRE2_EXTRA_ALT_BSUX is set. This an ECMAScript, non-Perl compatible,
+extension, so PCRE2 follows ECMAScript rather than Perl.
+
+31. Applied pull request #300 by Carlo, which fixes #261. The bug was that
+pcre2_match() was not fully resetting all captures that had been set within a
+(possibly recursive) subroutine call such as (?3).
+
+32. Changed the meaning of \w (and its synonyms) in UCP mode to match Perl. It
+now matches characters whose general categories are L or N or whose particular
+categories are Mn (non-spacing mark) or Pc (combining punctuation). The latter
+includes underscore.
+
+33. Changed the meaning of [:xdigit:] in UCP mode to match Perl. It now also
+matches the "fullwidth" versions of the hex digits. Just like it is done for
+[:digit:], PCRE2_EXTRA_ASCII_DIGIT can be used to keep this class ASCII only
+without affecting other POSIX classes.
+
+34. GitHub PR305 fixes a potential integer overflow in pcre2_dfa_match().
+
+35. Updated handling of \b and \B in UCP mode to match the changes to \w in 32
+above because \b and \B are defined in terms of \w.
+
+36. Within a pattern (?aT) and (?-aT) set and reset the PCRE2_EXTRA_ASCII_DIGIT
+option, and (?aP) also sets (?aT) so that (?-aP) disables all ASCII
+restrictions on POSIX classes.
+
+37. If PCRE2_FIRSTLINE was set on an anchored pattern, pcre2_match() and
+pcre2_dfa_match() misbehaved. PCRE2_FIRSTLINE is now ignored for anchored
+patterns.
+
+38. Add a test for ridiculous ovector offset values to the substring extraction
+functions.
+
+39. Make OP_REVERSE use IMM2_SIZE for its data instead of LINK_SIZE, for
+consistency with OP_VREVERSE.
+
+40. In some legacy environments with a pre C99 snprintf, pcre2_regerror could
+return an incorrect value when the provided buffer was too small.
+
+41. Applied pull request #342 which adds sanity checks for ctype functions and
+locks out any accidental sign-extension.
+
+42. In the 32-bit library, in non-UTF mode, a quantifier that followed a
+literal character with a value greater than or equal to 0x80000000u caused
+undefined behaviour.
+
+43. \z was misbehaving when matching fragments inside invalid UTF strings.
+
+44. Implement --group-separator and --no-group-separator for pcre2grep.
+
+45. Fix \X matching in 32 bit mode without UTF in JIT.
+
+46. Fix backref iterators when PCRE2_MATCH_UNSET_BACKREF is set in JIT.
+
+47. Refactor the handling of whole-pattern recursion (?0) in pcre2_match() so
+that its end is handled similarly to other recursions. This has altered the
+behaviour of /|(?0)./endanchored which was previously not right.
+
+48. Improved the test for looping recursion by checking the last referenced
+character as well as the current character. This allows some patterns that
+previously triggered the check to run to completion instead of giving the loop
+error.
+
+49. In 32-bit mode, the compiler looped for the pattern /[\x{ffffffff}]/ when
+PCRE2_CASELESS and PCRE2_UCP (but not PCRE2_UTF) were set. Fixed by not trying
+to look for other cases for characters above the Unicode range.
+
+50. In caseless 32-bit mode with UCP (but not UTF) set, the character
+0xffffffff incorrectly matched any character that has more than one other case,
+in particular k and s.
+
+51. Fix accept and endanchored interaction in JIT.
+
+52. Fix backreferences with unset backref and non-greedy iterators in JIT.
+
+53. Improve the logic that checks for a list of starting code units -- positive
+lookahead assertions are now ignored if the immediately following item is one
+that sets a mandatory starting character. For example, /a?(?=bc|)d/ used to set
+all of a, b, and d as possible starting code units; now it sets only a and d.
+
+54. Fix incorrect class character matches in JIT.
+
+55. In pcre2test, ensure pcre2_jit_match() is used when jitfast is used with
+substitution testing.
+
+56. Insert omitted setting of subject length in match data at the end of
+pcre2_jit_match().
+
+57. Implemented PCRE2_DISABLE_RECURSELOOP_CHECK for pcre2_match() to enable
+some apparently looping recursions to run to completion and therefore match the
+JIT behaviour. With this set, real loops will eventually get caught by match or
+heap limits or run out of resource.
+
+58. AC did a lot of work on pcre2_fuzzsupport.c to extend it to 16-bit and
+32-bit libraries and to compare JIT and non-JIT matching.
+
+
+Version 10.42 11-December-2022
+------------------------------
+
+1. Change 19 of 10.41 wasn't quite right; it put the definition of a default,
+empty value for PCRE2_CALL_CONVENTION in src/pcre2posix.c instead of
+src/pcre2posix.h, which meant that programs that included pcre2posix.h but not
+pcre2.h failed to compile.
+
+2. To catch similar issues to the above in future, a new small test program
+that includes pcre2posix.h but not pcre2.h has been added to the test suite.
+
+3. When the -S option of pcre2test was used to set a stack size greater than
+the allowed maximum, the error message displayed the hard limit incorrectly.
+This was pointed out on GitHub pull request #171, but the suggested patch
+didn't cope with all cases. Some further modification was required.
+
+4. Supplying an ovector count of more than 65535 to pcre2_match_data_create()
+caused a crash because the field in the match data block is only 16 bits. A
+maximum of 65535 is now silently applied.
+
+5. Merged @carenas patch #175 which fixes #86 - segfault on aarch64 (ARM),
+
+6. The prototype for pcre2_substring_list_free() specified its argument as
+PCRE2_SPTR * which is a const data type, whereas the yield from
+pcre2_substring_list() is not const. This caused compiler warnings. I have
+changed the argument of pcre2_substring_list_free() to be PCRE2_UCHAR ** to
+remove this anomaly. This might cause new warnings in existing code where a
+cast has been used to avoid previous ones.
+
+
+Version 10.41 06-December-2022
+------------------------------
+
+1. Add fflush() before and after a fork callout in pcre2grep to get its output
+to be the same on all systems. (There were previously ordering differences in
+Alpine Linux).
+
+2. Merged patch from @carenas (GitHub #110) for pthreads support in CMake.
+
+3. SSF scorecards grumbled about possible overflow in an expression in
+pcre2test. It never would have overflowed in practice, but some casts have been
+added and at the some time there's been some tidying of fprints that output
+size_t values.
+
+4. PR #94 showed up an unused enum in pcre2_convert.c, which is now removed.
+
+5. Minor code re-arrangement to remove gcc warning about realloc() in
+pcre2test.
+
+6. Change a number of int variables that hold buffer and line lengths in
+pcre2grep to PCRE2_SIZE (aka size_t).
+
+7. Added an #ifdef to cut out a call to PRIV(jit_free) when JIT is not
+supported (even though that function would do nothing in that case) at the
+request of a user who doesn't even want to link with pcre_jit_compile.o. Also
+tidied up an untidy #ifdef arrangement in pcre2test.
+
+8. Fixed an issue in the backtracking optimization of character repeats in
+JIT. Furthermore optimize star repetitions, not just plus repetitions.
+
+9. Removed the use of an initial backtracking frames vector on the system stack
+in pcre2_match() so that it now always uses the heap. (In a multi-thread
+environment with very small stacks there had been an issue.) This also is
+tidier for JIT matching, which didn't need that vector. The heap vector is now
+remembered in the match data block and re-used if that block itself is re-used.
+It is freed with the match data block.
+
+10. Adjusted the find_limits code in pcre2test to work with change 9 above.
+
+11. Added find_limits_noheap to pcre2test, because the heap limits are now
+different in different environments and so cannot be included in the standard
+tests.
+
+12. Created a test for pcre2_match() heap processing that is not part of the
+tests run by 'make check', but can be run manually. The current output is from
+a 64-bit system.
+
+13. Implemented -Z aka --null in pcre2grep.
+
+14. A minor change to pcre2test and the addition of several new pcre2grep tests
+have improved LCOV coverage statistics. At the same time, code in pcre2grep and
+elsewhere that can never be obeyed in normal testing has been excluded from
+coverage.
+
+15. Fixed a bug in pcre2grep that could cause an extra newline to be written
+after output generated by --output.
+
+16. If a file has a .bz2 extension but is not in fact compressed, pcre2grep
+should process it as a plain text file. A bug stopped this happening; now fixed
+and added to the tests.
+
+17. When pcre2grep was running not in UTF mode, if a string specified by
+--output or obtained from a callout in a pattern contained a character (byte)
+greater than 127, it was incorrectly output in UTF-8 format.
+
+18. Added some casts after warnings from Clang sanitize.
+
+19. Merged patch from cbouc (GitHub #139): 4 function prototypes were missing
+PCRE2_CALL_CONVENTION in src/pcre2posix.h. All function prototypes returning
+pointers had out of place PCRE2_CALL_CONVENTION in src/pcre2.h.*. These
+produced errors when building for Windows with #define PCRE2_CALL_CONVENTION
+__stdcall.
+
+20. A negative repeat value in a pcre2test subject line was not being
+diagnosed, leading to infinite looping.
+
+21. Updated RunGrepTest to discard the warning that Bash now gives when setting
+LC_CTYPE to a bad value (because older versions didn't).
+
+22. Updated pcre2grep so that it behaves like GNU grep when matching more than
+one pattern and a later pattern matches at an earlier point in the subject when
+the matched substrings are being identified by colour or by offsets.
+
+23. Updated the PrepareRelease script so that the man page that it makes for
+the pcre2demo demonstration program is more standard and does not cause errors
+when processed by lexgrog or mandb -c (GitHub issue #160).
+
+24. The JIT compiler was updated.
+
+
+Version 10.40 15-April-2022
+---------------------------
+
+1. Merged patch from @carenas (GitHub #35, 7db87842) to fix pcre2grep incorrect
+handling of multiple passes.
+
+2. Merged patch from @carenas (GitHub #36, dae47509) to fix portability issue
+in pcre2grep with buffered fseek(stdin).
+
+3. Merged patch from @carenas (GitHub #37, acc520924) to fix tests when -S is
+not supported.
+
+4. Revert an unintended change in JIT repeat detection.
+
+5. Merged patch from @carenas (GitHub #52, b037bfa1) to fix build on GNU Hurd.
+
+6. Merged documentation and comments patches from @carenas (GitHub #47).
+
+7. Merged patch from @carenas (GitHub #49) to remove obsolete JFriedl test code
+from pcre2grep.
+
+8. Merged patch from @carenas (GitHub #48) to fix CMake install issue #46.
+
+9. Merged patch from @carenas (GitHub #53) fixing NULL checks in matching and
+substituting.
+
+10. Add null_subject and null_replacement modifiers to pcre2test.
+
+11. Add check for NULL subject to POSIX regexec() function.
+
+12. Add check for NULL replacement to pcre2_substitute().
+
+13. For the subject arguments of pcre2_match(), pcre2_dfa_match(), and
+pcre2_substitute(), and the replacement argument of the latter, if the pointer
+is NULL and the length is zero, treat as an empty string. Apparently a number
+of applications treat NULL/0 in this way.
+
+14. Added support for Bidi_Class and a number of binary Unicode properties,
+including Bidi_Control.
+
+15. Fix some minor issues raised by clang sanitize.
+
+16. Very minor code speed up for maximizing character property matches.
+
+17. A number of changes to script matching for \p and \P:
+
+ (a) Script extensions for a character are now coded as a bitmap instead of
+ a list of script numbers, which should be faster and does not need a
+ loop.
+
+ (b) Added the syntax \p{script:xxx} and \p{script_extensions:xxx} (synonyms
+ sc and scx).
+
+ (c) Changed \p{scriptname} from being the same as \p{sc:scriptname} to being
+ the same as \p{scx:scriptname} because this change happened in Perl at
+ release 5.26.
+
+ (d) The standard Unicode 4-letter abbreviations for script names are now
+ recognized.
+
+ (e) In accordance with Unicode and Perl's "loose matching" rules, spaces,
+ hyphens, and underscores are ignored in property names, which are then
+ matched independent of case.
+
+18. The Python scripts in the maint directory have been refactored. There are
+now three scripts that generate pcre2_ucd.c, pcre2_ucp.h, and pcre2_ucptables.c
+(which is #included by pcre2_tables.c). The data lists that used to be
+duplicated are now held in a single common Python module.
+
+19. On CHERI, and thus Arm's Morello prototype, pointers are represented as
+hardware capabilities, which consist of both an integer address and additional
+metadata, meaning they are twice the size of the platform's size_t type, i.e.
+16 bytes on a 64-bit system. The ovector member of heapframe happens to only be
+8 byte aligned, and so computing frame_size ended up with a multiple of 8 but
+not 16. Whilst the first frame was always suitably aligned, this then
+misaligned the frame that follows, resulting in an alignment fault when storing
+a pointer to Fecode at the start of match. Patch to fix this issue by Jessica
+Clarke PR#72.
+
+20. Added -LP and -LS listing options to pcre2test.
+
+21. A user discovered that the library names in CMakeLists.txt for MSVC
+debugger (PDB) files were incorrect - perhaps never tried for PCRE2?
+
+22. An item such as [Aa] is optimized into a caseless single character match.
+When this was quantified (e.g. [Aa]{2}) and was also the last literal item in a
+pattern, the optimizing "must be present for a match" character check was not
+being flagged as caseless, causing some matches that should have succeeded to
+fail.
+
+23. Fixed a unicode property matching issue in JIT. The character was not
+fully read in caseless matching.
+
+24. Fixed an issue affecting recursions in JIT caused by duplicated data
+transfers.
+
+25. Merged patch from @carenas (GitHub #96) which fixes some problems with
+pcre2test and readline/readedit:
+
+ * Use the right header for libedit in FreeBSD with autoconf
+ * Really allow libedit with cmake
+ * Avoid using readline headers with libedit
+
+
+Version 10.39 29-October-2021
+-----------------------------
+
+1. Fix incorrect detection of alternatives in first character search in JIT.
+
+2. Merged patch from @carenas (GitHub #28):
+
+ Visual Studio 2013 includes support for %zu and %td, so let newer
+ versions of it avoid the fallback, and while at it, make sure that
+ the first check is for DISABLE_PERCENT_ZT so it will be always
+ honoured if chosen.
+
+ prtdiff_t is signed, so use a signed type instead, and make sure
+ that an appropriate width is chosen if pointers are 64bit wide and
+ long is not (ex: Windows 64bit).
+
+ IMHO removing the cast (and therefore the possibility of truncation)
+ make the code cleaner and the fallback is likely portable enough
+ with all 64-bit POSIX systems doing LP64 except for Windows.
+
+3. Merged patch from @carenas (GitHub #29) to update to Unicode 14.0.0.
+
+4. Merged patch from @carenas (GitHub #30):
+
+ * Cleanup: remove references to no longer used stdint.h
+
+ Since 19c50b9d (Unconditionally use inttypes.h instead of trying for stdint.h
+ (simplification) and remove the now unnecessary inclusion in
+ pcre2_internal.h., 2018-11-14), stdint.h is no longer used.
+
+ Remove checks for it in autotools and CMake and document better the expected
+ build failures for systems that might have stdint.h (C99) and not inttypes.h
+ (from POSIX), like old Windows.
+
+ * Cleanup: remove detection for inttypes.h which is a hard dependency
+
+ CMake checks for standard headers are not meant to be used for hard
+ dependencies, so will prevent a possible fallback to work.
+
+ Alternatively, the header could be checked to make the configuration fail
+ instead of breaking the build, but that was punted, as it was missing anyway
+ from autotools.
+
+5. Merged patch from @carenas (GitHub #32):
+
+ * jit: allow building with ancient MSVC versions
+
+ Visual Studio older than 2013 fails to build with JIT enabled, because it is
+ unable to parse non C89 compatible syntax, with mixed declarations and code.
+ While most recent compilers wouldn't even report this as a warning since it
+ is valid C99, it could be also made visible by adding to gcc/clang the
+ -Wdeclaration-after-statement flag at build time.
+
+ Move the code below the affected definitions.
+
+ * pcre2grep: avoid mixing declarations with code
+
+ Since d5a61ee8 (Patch to detect (and ignore) symlink loops in pcre2grep,
+ 2021-08-28), code will fail to build in a strict C89 compiler.
+
+ Reformat slightly to make it C89 compatible again.
+
+
+Version 10.38 01-October-2021
+-----------------------------
+
+1. Fix invalid single character repetition issues in JIT when the repetition
+is inside a capturing bracket and the bracket is preceded by character
+literals.
+
+2. Installed revised CMake configuration files provided by Jan-Willem Blokland.
+This extends the CMake build system to build both static and shared libraries
+in one go, builds the static library with PIC, and exposes PCRE2 libraries
+using the CMake config files. JWB provided these notes:
+
+- Introduced CMake variable BUILD_STATIC_LIBS to build the static library.
+
+- Make a small modification to config-cmake.h.in by removing the PCRE2_STATIC
+ variable. Added PCRE2_STATIC variable to the static build using the
+ target_compile_definitions() function.
+
+- Extended the CMake config files.
+
+ - Introduced CMake variable PCRE2_USE_STATIC_LIBS to easily switch between
+ the static and shared libraries.
+
+ - Added the PCRE_STATIC variable to the target compile definitions for the
+ import of the static library.
+
+Building static and shared libraries using MSVC results in a name clash of
+the libraries. Both static and shared library builds create, for example, the
+file pcre2-8.lib. Therefore, I decided to change the static library names by
+adding "-static". For example, pcre2-8.lib has become pcre2-8-static.lib.
+[Comment by PH: this is MSVC-specific. It doesn't happen on Linux.]
+
+3. Increased the minimum release number for CMake to 3.0.0 because older than
+2.8.12 is deprecated (it was set to 2.8.5) and causes warnings. Even 3.0.0 is
+quite old; it was released in 2014.
+
+4. Implemented a modified version of Thomas Tempelmann's pcre2grep patch for
+detecting symlink loops. This is dependent on the availability of realpath(),
+which is now tested for in ./configure and CMakeLists.txt.
+
+5. Implemented a modified version of Thomas Tempelmann's patch for faster
+case-independent "first code unit" searches for unanchored patterns in 8-bit
+mode in the interpreters. Instead of just remembering whether one case matched
+or not, it remembers the position of a previous match so as to avoid
+unnecessary repeated searching.
+
+6. Perl now locks out \K in lookarounds, so PCRE2 now does the same by default.
+However, just in case anybody was relying on the old behaviour, there is an
+option called PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK that enables the old behaviour.
+An option has also been added to pcre2grep to enable this.
+
+7. Re-enable a JIT optimization which was unintentionally disabled in 10.35.
+
+8. There is a loop counter to catch excessively crazy patterns when checking
+the lengths of lookbehinds at compile time. This was incorrectly getting reset
+whenever a lookahead was processed, leading to some fuzzer-generated patterns
+taking a very long time to compile when (?|) was present in the pattern,
+because (?|) disables caching of group lengths.
+
+
+Version 10.37 26-May-2021
+-------------------------
+
+1. Change RunGrepTest to use tr instead of sed when testing with binary
+zero bytes, because sed varies a lot from system to system and has problems
+with binary zeros. This is from Bugzilla #2681. Patch from Jeremie
+Courreges-Anglas via Nam Nguyen. This fixes RunGrepTest for OpenBSD. Later:
+it broke it for at least one version of Solaris, where tr can't handle binary
+zeros. However, that system had /usr/xpg4/bin/tr installed, which works OK, so
+RunGrepTest now checks for that command and uses it if found.
+
+2. Compiling with gcc 10.2's -fanalyzer option showed up a hypothetical problem
+with a NULL dereference. I don't think this case could ever occur in practice,
+but I have put in a check in order to get rid of the compiler error.
+
+3. An alternative patch for CMakeLists.txt because 10.36 #4 breaks CMake on
+Windows. Patch from email@cs-ware.de fixes bugzilla #2688.
+
+4. Two bugs related to over-large numbers have been fixed so the behaviour is
+now the same as Perl.
+
+ (a) A pattern such as /\214748364/ gave an overflow error instead of being
+ treated as the octal number \214 followed by literal digits.
+
+ (b) A sequence such as {65536 that has no terminating } so is not a
+ quantifier was nevertheless complaining that a quantifier number was too big.
+
+5. A run of autoconf suggested that configure.ac was out-of-date with respect
+to the latest autoconf. Running autoupdate made some valid changes, some valid
+suggestions, and also some invalid changes, which were fixed by hand. Autoconf
+now runs clean and the resulting "configure" seems to work, so I hope nothing
+is broken. Later: the requirement for autoconf 2.70 broke some automatic test
+robots. It doesn't seem to be necessary: trying a reduction to 2.60.
+
+6. The pattern /a\K.(?0)*/ when matched against "abac" by the interpreter gave
+the answer "bac", whereas Perl and JIT both yield "c". This was because the
+effect of \K was not propagating back from the full pattern recursion. Other
+recursions such as /(a\K.(?1)*)/ did not have this problem.
+
+7. Restore single character repetition optimization in JIT. Currently fewer
+character repetitions are optimized than in 10.34.
+
+8. When the names of the functions in the POSIX wrapper were changed to
+pcre2_regcomp() etc. (see change 10.33 #4 below), functions with the original
+names were left in the library so that pre-compiled programs would still work.
+However, this has proved troublesome when programs link with several libraries,
+some of which use PCRE2 via the POSIX interface while others use a native POSIX
+library. For this reason, the POSIX function names are removed in this release.
+The macros in pcre2posix.h should ensure that re-compiling fixes any programs
+that haven't been compiled since before 10.33.
+
+
+Version 10.36 04-December-2020
+------------------------------
+
+1. Add CET_CFLAGS so that when Intel CET is enabled, pass -mshstk to
+compiler. This fixes https://bugs.exim.org/show_bug.cgi?id=2578. Patch for
+Makefile.am and configure.ac by H.J. Lu. Equivalent patch for CMakeLists.txt
+invented by PH.
+
+2. Fix infinite loop when a single byte newline is searched in JIT when
+invalid utf8 mode is enabled.
+
+3. Updated CMakeLists.txt with patch from Wolfgang Stöggl (Bugzilla #2584):
+
+ - Include GNUInstallDirs and use ${CMAKE_INSTALL_LIBDIR} instead of hardcoded
+ lib. This allows differentiation between lib and lib64.
+ CMAKE_INSTALL_LIBDIR is used for installation of libraries and also for
+ pkgconfig file generation.
+
+ - Add the version of PCRE2 to the configuration summary like ./configure
+ does.
+
+ - Fix typo: MACTHED_STRING->MATCHED_STRING
+
+4. Updated CMakeLists.txt with another patch from Wolfgang Stöggl (Bugzilla
+#2588):
+
+ - Add escaped double quotes around include directory in CMakeLists.txt to
+ allow spaces in directory names.
+
+ - This fixes a cmake error, if the path of the pcre2 source contains a space.
+
+5. Updated CMakeLists.txt with a patch from B. Scott Michel: CMake's
+documentation suggests using CHECK_SYMBOL_EXISTS over CHECK_FUNCTION_EXIST.
+Moreover, these functions come from specific header files, which need to be
+specified (and, thankfully, are the same on both the Linux and WinXX
+platforms.)
+
+6. Added a (uint32_t) cast to prevent a compiler warning in pcre2_compile.c.
+
+7. Applied a patch from Wolfgang Stöggl (Bugzilla #2600) to fix postfix for
+debug Windows builds using CMake. This also updated configure so that it
+generates *.pc files and pcre2-config with the same content, as in the past.
+
+8. If a pattern ended with (?(VERSION=n.d where n is any number but d is just a
+single digit, the code unit beyond d was being read (i.e. there was a read
+buffer overflow). Fixes ClusterFuzz 23779.
+
+9. After the rework in r1235, certain character ranges were incorrectly
+handled by an optimization in JIT. Furthermore a wrong offset was used to
+read a value from a buffer which could lead to memory overread.
+
+10. Unnoticed for many years was the fact that delimiters other than / in the
+testinput1 and testinput4 files could cause incorrect behaviour when these
+files were processed by perltest.sh. There were several tests that used quotes
+as delimiters, and it was just luck that they didn't go wrong with perltest.sh.
+All the patterns in testinput1 and testinput4 now use / as their delimiter.
+This fixes Bugzilla #2641.
+
+11. Perl has started to give an error for \K within lookarounds (though there
+are cases where it doesn't). PCRE2 still allows this, so the tests that include
+this case have been moved from test 1 to test 2.
+
+12. Further to 10 above, pcre2test has been updated to detect and grumble if a
+delimiter other than / is used after #perltest.
+
+13. Fixed a bug with PCRE2_MATCH_INVALID_UTF in 8-bit mode when PCRE2_CASELESS
+was set and PCRE2_NO_START_OPTIMIZE was not set. The optimization for finding
+the start of a match was not resetting correctly after a failed match on the
+first valid fragment of the subject, possibly causing incorrect "no match"
+returns on subsequent fragments. For example, the pattern /A/ failed to match
+the subject \xe5A. Fixes Bugzilla #2642.
+
+14. Fixed a bug in character set matching when JIT is enabled and both unicode
+scripts and unicode classes are present at the same time.
+
+15. Added GNU grep's -m (aka --max-count) option to pcre2grep.
+
+16. Refactored substitution processing in pcre2grep strings, both for the -O
+option and when dealing with callouts. There is now a single function that
+handles $ expansion in all cases (instead of multiple copies of almost
+identical code). This means that the same escape sequences are available
+everywhere, which was not previously the case. At the same time, the escape
+sequences $x{...} and $o{...} have been introduced, to allow for characters
+whose code points are greater than 255 in Unicode mode.
+
+17. Applied the patch from Bugzilla #2628 to RunGrepTest. This does an explicit
+test for a version of sed that can handle binary zero, instead of assuming that
+any Linux version will work. Later: replaced $(...) by `...` because not all
+shells recognize the former.
+
+18. Fixed a word boundary check bug in JIT when partial matching is enabled.
+
+19. Fix ARM64 compilation warning in JIT. Patch by Carlo.
+
+20. A bug in the RunTest script meant that if the first part of test 2 failed,
+the failure was not reported.
+
+21. Test 2 was failing when run from a directory other than the source
+directory. This failure was previously missed in RunTest because of 20 above.
+Fixes added to both RunTest and RunTest.bat.
+
+22. Patch to CMakeLists.txt from Daniel to fix problem with testing under
+Windows.
+
+
+Version 10.35 09-May-2020
+---------------------------
+
+1. Use PCRE2_MATCH_EMPTY flag to detect empty matches in JIT.
+
+2. Fix ARMv5 JIT improper handling of labels right after a constant pool.
+
+3. A JIT bug is fixed which allowed to read the fields of the compiled
+pattern before its existence is checked.
+
+4. Back in the PCRE1 day, capturing groups that contained recursive back
+references to themselves were made atomic (version 8.01, change 18) because
+after the end a repeated group, the captured substrings had their values from
+the final repetition, not from an earlier repetition that might be the
+destination of a backtrack. This feature was documented, and was carried over
+into PCRE2. However, it has now been realized that the major refactoring that
+was done for 10.30 has made this atomizing unnecessary, and it is confusing
+when users are unaware of it, making some patterns appear not to be working as
+expected. Capture values of recursive back references in repeated groups are
+now correctly backtracked, so this unnecessary restriction has been removed.
+
+5. Added PCRE2_SUBSTITUTE_LITERAL.
+
+6. Avoid some VS compiler warnings.
+
+7. Added PCRE2_SUBSTITUTE_MATCHED.
+
+8. Added (?* and (?<* as synonyms for (*napla: and (*naplb: to match another
+regex engine. The Perl regex folks are aware of this usage and have made a note
+about it.
+
+9. When an assertion is repeated, PCRE2 used to limit the maximum repetition to
+1, believing that repeating an assertion is pointless. However, if a positive
+assertion contains capturing groups, repetition can be useful. In any case, an
+assertion could always be wrapped in a repeated group. The only restriction
+that is now imposed is that an unlimited maximum is changed to one more than
+the minimum.
+
+10. Fix *THEN verbs in lookahead assertions in JIT.
+
+11. Added PCRE2_SUBSTITUTE_REPLACEMENT_ONLY.
+
+12. The JIT stack should be freed when the low-level stack allocation fails.
+
+13. In pcre2grep, if the final line in a scanned file is output but does not
+end with a newline sequence, add a newline according to the --newline setting.
+
+14. (?(DEFINE)...) groups were not being handled correctly when checking for
+the fixed length of a lookbehind assertion. Such a group within a lookbehind
+should be skipped, as it does not contribute to the length of the group.
+Instead, the (DEFINE) group was being processed, and if at the end of the
+lookbehind, that end was not correctly recognized. Errors such as "lookbehind
+assertion is not fixed length" and also "internal error: bad code value in
+parsed_skip()" could result.
+
+15. Put a limit of 1000 on recursive calls in pcre2_study() when searching
+nested groups for starting code units, in order to avoid stack overflow issues.
+If the limit is reached, it just gives up trying for this optimization.
+
+16. The control verb chain list must always be restored when exiting from a
+recurse function in JIT.
+
+17. Fix a crash which occurs when the character type of an invalid UTF
+character is decoded in JIT.
+
+18. Changes in many areas of the code so that when Unicode is supported and
+PCRE2_UCP is set without PCRE2_UTF, Unicode character properties are used for
+upper/lower case computations on characters whose code points are greater than
+127.
+
+19. The function for checking UTF-16 validity was returning an incorrect offset
+for the start of the error when a high surrogate was not followed by a valid
+low surrogate. This caused incorrect behaviour, for example when
+PCRE2_MATCH_INVALID_UTF was set and a match started immediately following the
+invalid high surrogate, such as /aa/ matching "\x{d800}aa".
+
+20. If a DEFINE group immediately preceded a lookbehind assertion, the pattern
+could be mis-compiled and therefore not match correctly. This is the example
+that found this: /(?(DEFINE)(?bar))(? has been raised to
+50, (b) the new --om-capture option changes the limit, (c) an error is raised
+if -o asks for a group that is above the limit.
+
+12. The quantifier {1} was always being ignored, but this is incorrect when it
+is made possessive and applied to an item in parentheses, because a
+parenthesized item may contain multiple branches or other backtracking points,
+for example /(a|ab){1}+c/ or /(a+){1}+a/.
+
+13. For partial matches, pcre2test was always showing the maximum lookbehind
+characters, flagged with "<", which is misleading when the lookbehind didn't
+actually look behind the start (because it was later in the pattern). Showing
+all consulted preceding characters for partial matches is now controlled by the
+existing "allusedtext" modifier and, as for complete matches, this facility is
+available only for non-JIT matching, because JIT does not maintain the first
+and last consulted characters.
+
+14. DFA matching (using pcre2_dfa_match()) was not recognising a partial match
+if the end of the subject was encountered in a lookahead (conditional or
+otherwise), an atomic group, or a recursion.
+
+15. Give error if pcre2test -t, -T, -tm or -TM is given an argument of zero.
+
+16. Check for integer overflow when computing lookbehind lengths. Fixes
+Clusterfuzz issue 15636.
+
+17. Implemented non-atomic positive lookaround assertions.
+
+18. If a lookbehind contained a lookahead that contained another lookbehind
+within it, the nested lookbehind was not correctly processed. For example, if
+/(?<=(?=(?<=a)))b/ was matched to "ab" it gave no match instead of matching
+"b".
+
+19. Implemented pcre2_get_match_data_size().
+
+20. Two alterations to partial matching:
+
+ (a) The definition of a partial match is slightly changed: if a pattern
+ contains any lookbehinds, an empty partial match may be given, because this
+ is another situation where adding characters to the current subject can
+ lead to a full match. Example: /c*+(?<=[bc])/ with subject "ab".
+
+ (b) Similarly, if a pattern could match an empty string, an empty partial
+ match may be given. Example: /(?![ab]).*/ with subject "ab". This case
+ applies only to PCRE2_PARTIAL_HARD.
+
+ (c) An empty string partial hard match can be returned for \z and \Z as it
+ is documented that they shouldn't match.
+
+21. A branch that started with (*ACCEPT) was not being recognized as one that
+could match an empty string.
+
+22. Corrected pcre2_set_character_tables() tables data type: was const unsigned
+char * instead of const uint8_t *, as generated by pcre2_maketables().
+
+23. Upgraded to Unicode 12.1.0.
+
+24. Add -jitfast command line option to pcre2test (to make all the jit options
+available directly).
+
+25. Make pcre2test -C show if libreadline or libedit is supported.
+
+26. If the length of one branch of a group exceeded 65535 (the maximum value
+that is remembered as a minimum length), the whole group's length was
+incorrectly recorded as 65535, leading to incorrect "no match" when start-up
+optimizations were in force.
+
+27. The "rightmost consulted character" value was not always correct; in
+particular, if a pattern ended with a negative lookahead, characters that were
+inspected in that lookahead were not included.
+
+28. Add the pcre2_maketables_free() function.
+
+29. The start-up optimization that looks for a unique initial matching
+code unit in the interpretive engines uses memchr() in 8-bit mode. When the
+search is caseless, it was doing so inefficiently, which ended up slowing down
+the match drastically when the subject was very long. The revised code (a)
+remembers if one case is not found, so it never repeats the search for that
+case after a bumpalong and (b) when one case has been found, it searches only
+up to that position for an earlier occurrence of the other case. This fix
+applies to both interpretive pcre2_match() and to pcre2_dfa_match().
+
+30. While scanning to find the minimum length of a group, if any branch has
+minimum length zero, there is no need to scan any subsequent branches (a small
+compile-time performance improvement).
+
+31. Installed a .gitignore file on a user's suggestion. When using the svn
+repository with git (through git svn) this helps keep it tidy.
+
+32. Add underflow check in JIT which may occur when the value of subject
+string pointer is close to 0.
+
+33. Arrange for classes such as [Aa] which contain just the two cases of the
+same character, to be treated as a single caseless character. This causes the
+first and required code unit optimizations to kick in where relevant.
+
+34. Improve the bitmap of starting bytes for positive classes that include wide
+characters, but no property types, in UTF-8 mode. Previously, on encountering
+such a class, the bits for all bytes greater than \xc4 were set, thus
+specifying any character with codepoint >= 0x100. Now the only bits that are
+set are for the relevant bytes that start the wide characters. This can give a
+noticeable performance improvement.
+
+35. If the bitmap of starting code units contains only 1 or 2 bits, replace it
+with a single starting code unit (1 bit) or a caseless single starting code
+unit if the two relevant characters are case-partners. This is particularly
+relevant to the 8-bit library, though it applies to all. It can give a
+performance boost for patterns such as [Ww]ord and (word|WORD). However, this
+optimization doesn't happen if there is a "required" code unit of the same
+value (because the search for a "required" code unit starts at the match start
+for non-unique first code unit patterns, but after a unique first code unit,
+and patterns such as a*a need the former action).
+
+36. Small patch to pcre2posix.c to set the erroroffset field to -1 immediately
+after a successful compile, instead of at the start of matching to avoid a
+sanitizer complaint (regexec is supposed to be thread safe).
+
+37. Add NEON vectorization to JIT to speed up matching of first character and
+pairs of characters on ARM64 CPUs.
+
+38. If a non-ASCII character was the first in a starting assertion in a
+caseless match, the "first code unit" optimization did not get the casing
+right, and the assertion failed to match a character in the other case if it
+did not start with the same code unit.
+
+39. Fixed the incorrect computation of jump sizes on x86 CPUs in JIT. A masking
+operation was incorrectly removed in r1136. Reported by Ralf Junker.
+
+
+Version 10.33 16-April-2019
+---------------------------
+
+1. Added "allvector" to pcre2test to make it easy to check the part of the
+ovector that shouldn't be changed, in particular after substitute and failed or
+partial matches.
+
+2. Fix subject buffer overread in JIT when UTF is disabled and \X or \R has
+a greater than 1 fixed quantifier. This issue was found by Yunho Kim.
+
+3. Added support for callouts from pcre2_substitute(). After 10.33-RC1, but
+prior to release, fixed a bug that caused a crash if pcre2_substitute() was
+called with a NULL match context.
+
+4. The POSIX functions are now all called pcre2_regcomp() etc., with wrapper
+functions that use the standard POSIX names. However, in pcre2posix.h the POSIX
+names are defined as macros. This should help avoid linking with the wrong
+library in some environments while still exporting the POSIX names for
+pre-existing programs that use them. (The Debian alternative names are also
+defined as macros, but not documented.)
+
+5. Fix an xclass matching issue in JIT.
+
+6. Implement PCRE2_EXTRA_ESCAPED_CR_IS_LF (see Bugzilla 2315).
+
+7. Implement the Perl 5.28 experimental alphabetic names for atomic groups and
+lookaround assertions, for example, (*pla:...) and (*atomic:...). These are
+characterized by a lower case letter following (* and to simplify coding for
+this, the character tables created by pcre2_maketables() were updated to add a
+new "is lower case letter" bit. At the same time, the now unused "is
+hexadecimal digit" bit was removed. The default tables in
+src/pcre2_chartables.c.dist are updated.
+
+8. Implement the new Perl "script run" features (*script_run:...) and
+(*atomic_script_run:...) aka (*sr:...) and (*asr:...).
+
+9. Fixed two typos in change 22 for 10.21, which added special handling for
+ranges such as a-z in EBCDIC environments. The original code probably never
+worked, though there were no bug reports.
+
+10. Implement PCRE2_COPY_MATCHED_SUBJECT for pcre2_match() (including JIT via
+pcre2_match()) and pcre2_dfa_match(), but *not* the pcre2_jit_match() fast
+path. Also, when a match fails, set the subject field in the match data to NULL
+for tidiness - none of the substring extractors should reference this after
+match failure.
+
+11. If a pattern started with a subroutine call that had a quantifier with a
+minimum of zero, an incorrect "match must start with this character" could be
+recorded. Example: /(?&xxx)*ABC(?XYZ)/ would (incorrectly) expect 'A' to
+be the first character of a match.
+
+12. The heap limit checking code in pcre2_dfa_match() could suffer from
+overflow if the heap limit was set very large. This could cause incorrect "heap
+limit exceeded" errors.
+
+13. Add "kibibytes" to the heap limit output from pcre2test -C to make the
+units clear.
+
+14. Add a call to pcre2_jit_free_unused_memory() in pcre2grep, for tidiness.
+
+15. Updated the VMS-specific code in pcre2test on the advice of a VMS user.
+
+16. Removed the unnecessary inclusion of stdint.h (or inttypes.h) from
+pcre2_internal.h as it is now included by pcre2.h. Also, change 17 for 10.32
+below was unnecessarily complicated, as inttypes.h is a Standard C header,
+which is defined to be a superset of stdint.h. Instead of conditionally
+including stdint.h or inttypes.h, pcre2.h now unconditionally includes
+inttypes.h. This supports environments that do not have stdint.h but do have
+inttypes.h, which are known to exist. A note in the autotools documentation
+says (November 2018) that there are none known that are the other way round.
+
+17. Added --disable-percent-zt to "configure" (and equivalent to CMake) to
+forcibly disable the use of %zu and %td in formatting strings because there is
+at least one version of VMS that claims to be C99 but does not support these
+modifiers.
+
+18. Added --disable-pcre2grep-callout-fork, which restricts the callout support
+in pcre2grep to the inbuilt echo facility. This may be useful in environments
+that do not support fork().
+
+19. Fix two instances of <= 0 being applied to unsigned integers (the VMS
+compiler complains).
+
+20. Added "fork" support for VMS to pcre2grep, for running an external program
+via a string callout.
+
+21. Improve MAP_JIT flag usage on MacOS. Patch by Rich Siegel.
+
+22. If a pattern started with (*MARK), (*COMMIT), (*PRUNE), (*SKIP), or (*THEN)
+followed by ^ it was not recognized as anchored.
+
+23. The RunGrepTest script used to cut out the test of NUL characters for
+Solaris and MacOS as printf and sed can't handle them. It seems that the *BSD
+systems can't either. I've inverted the test so that only those OS that are
+known to work (currently only Linux) try to run this test.
+
+24. Some tests in RunGrepTest appended to testtrygrep from two different file
+descriptors instead of redirecting stderr to stdout. This worked on Linux, but
+it was reported not to on other systems, causing the tests to fail.
+
+25. In the RunTest script, make the test for stack setting use the same value
+for the stack as it needs for -bigstack.
+
+26. Insert a cast in pcre2_dfa_match.c to suppress a compiler warning.
+
+26. With PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL set, escape sequences such as \s
+which are valid in character classes, but not as the end of ranges, were being
+treated as literals. An example is [_-\s] (but not [\s-_] because that gave an
+error at the *start* of a range). Now an "invalid range" error is given
+independently of PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL.
+
+27. Related to 26 above, PCRE2_BAD_ESCAPE_IS_LITERAL was affecting known escape
+sequences such as \eX when they appeared invalidly in a character class. Now
+the option applies only to unrecognized or malformed escape sequences.
+
+28. Fix word boundary in JIT compiler. Patch by Mike Munday.
+
+29. The pcre2_dfa_match() function was incorrectly handling conditional version
+tests such as (?(VERSION>=0)...) when the version test was true. Incorrect
+processing or a crash could result.
+
+30. When PCRE2_UTF is set, allow non-ASCII letters and decimal digits in group
+names, as Perl does. There was a small bug in this new code, found by
+ClusterFuzz 12950, fixed before release.
+
+31. Implemented PCRE2_EXTRA_ALT_BSUX to support ECMAScript 6's \u{hhh}
+construct.
+
+32. Compile \p{Any} to be the same as . in DOTALL mode, so that it benefits
+from auto-anchoring if \p{Any}* starts a pattern.
+
+33. Compile invalid UTF check in JIT test when only pcre32 is enabled.
+
+34. For some time now, CMake has been warning about the setting of policy
+CMP0026 to "OLD" in CmakeLists.txt, and hinting that the feature might be
+removed in a future version. A request for CMake expertise on the list produced
+no result, so I have now hacked CMakeLists.txt along the lines of some changes
+I found on the Internet. The new code no longer needs the policy setting, and
+it appears to work fine on Linux.
+
+35. Setting --enable-jit=auto for an out-of-tree build failed because the
+source directory wasn't in the search path for AC_TRY_COMPILE always. Patch
+from Ross Burton.
+
+36. Disable SSE2 JIT optimizations in x86 CPUs when SSE2 is not available.
+Patch by Guillem Jover.
+
+37. Changed expressions such as 1<<10 to 1u<<10 in many places because compiler
+warnings were reported.
+
+38. Using the clang compiler with sanitizing options causes runtime complaints
+about truncation for statements such as x = ~x when x is an 8-bit value; it
+seems to compute ~x as a 32-bit value. Changing such statements to x = 255 ^ x
+gets rid of the warnings. There were also two missing casts in pcre2test.
+
+
+Version 10.32 10-September-2018
+-------------------------------
+
+1. When matching using the REG_STARTEND feature of the POSIX API with a
+non-zero starting offset, unset capturing groups with lower numbers than a
+group that did capture something were not being correctly returned as "unset"
+(that is, with offset values of -1).
+
+2. When matching using the POSIX API, pcre2test used to omit listing unset
+groups altogether. Now it shows those that come before any actual captures as
+"", as happens for non-POSIX matching.
+
+3. Running "pcre2test -C" always stated "\R matches CR, LF, or CRLF only",
+whatever the build configuration was. It now correctly says "\R matches all
+Unicode newlines" in the default case when --enable-bsr-anycrlf has not been
+specified. Similarly, running "pcre2test -C bsr" never produced the result
+ANY.
+
+4. Matching the pattern /(*UTF)\C[^\v]+\x80/ against an 8-bit string containing
+multi-code-unit characters caused bad behaviour and possibly a crash. This
+issue was fixed for other kinds of repeat in release 10.20 by change 19, but
+repeating character classes were overlooked.
+
+5. pcre2grep now supports the inclusion of binary zeros in patterns that are
+read from files via the -f option.
+
+6. A small fix to pcre2grep to avoid compiler warnings for -Wformat-overflow=2.
+
+7. Added --enable-jit=auto support to configure.ac.
+
+8. Added some dummy variables to the heapframe structure in 16-bit and 32-bit
+modes for the benefit of m68k, where pointers can be 16-bit aligned. The
+dummies force 32-bit alignment and this ensures that the structure is a
+multiple of PCRE2_SIZE, a requirement that is tested at compile time. In other
+architectures, alignment requirements take care of this automatically.
+
+9. When returning an error from pcre2_pattern_convert(), ensure the error
+offset is set zero for early errors.
+
+10. A number of patches for Windows support from Daniel Richard G:
+
+ (a) List of error numbers in Runtest.bat corrected (it was not the same as in
+ Runtest).
+
+ (b) pcre2grep snprintf() workaround as used elsewhere in the tree.
+
+ (c) Support for non-C99 snprintf() that returns -1 in the overflow case.
+
+11. Minor tidy of pcre2_dfa_match() code.
+
+12. Refactored pcre2_dfa_match() so that the internal recursive calls no longer
+use the stack for local workspace and local ovectors. Instead, an initial block
+of stack is reserved, but if this is insufficient, heap memory is used. The
+heap limit parameter now applies to pcre2_dfa_match().
+
+13. If a "find limits" test of DFA matching in pcre2test resulted in too many
+matches for the ovector, no matches were displayed.
+
+14. Removed an occurrence of ctrl/Z from test 6 because Windows treats it as
+EOF. The test looks to have come from a fuzzer.
+
+15. If PCRE2 was built with a default match limit a lot greater than the
+default default of 10 000 000, some JIT tests of the match limit no longer
+failed. All such tests now set 10 000 000 as the upper limit.
+
+16. Another Windows related patch for pcregrep to ensure that WIN32 is
+undefined under Cygwin.
+
+17. Test for the presence of stdint.h and inttypes.h in configure and CMake and
+include whichever exists (stdint preferred) instead of unconditionally
+including stdint. This makes life easier for old and non-standard systems.
+
+18. Further changes to improve portability, especially to old and or non-
+standard systems:
+
+ (a) Put all printf arguments in RunGrepTest into single, not double, quotes,
+ and use \0 not \x00 for binary zero.
+
+ (b) Avoid the use of C++ (i.e. BCPL) // comments.
+
+ (c) Parameterize the use of %zu in pcre2test to make it like %td. For both of
+ these now, if using MSVC or a standard C before C99, %lu is used with a
+ cast if necessary.
+
+19. Applied a contributed patch to CMakeLists.txt to increase the stack size
+when linking pcre2test with MSVC. This gets rid of a stack overflow error in
+the standard set of tests.
+
+20. Output a warning in pcre2test when ignoring the "altglobal" modifier when
+it is given with the "replace" modifier.
+
+21. In both pcre2test and pcre2_substitute(), with global matching, a pattern
+that matched an empty string, but never at the starting match offset, was not
+handled in a Perl-compatible way. The pattern /(=\G.)/ is an example of such
+a pattern. Because \G is in a lookbehind assertion, there has to be a
+"bumpalong" before there can be a match. The automatic "advance by one
+character after an empty string match" rule is therefore inappropriate. A more
+complicated algorithm has now been implemented.
+
+22. When checking to see if a lookbehind is of fixed length, lookaheads were
+correctly ignored, but qualifiers on lookaheads were not being ignored, leading
+to an incorrect "lookbehind assertion is not fixed length" error.
+
+23. The VERSION condition test was reading fractional PCRE2 version numbers
+such as the 04 in 10.04 incorrectly and hence giving wrong results.
+
+24. Updated to Unicode version 11.0.0. As well as the usual addition of new
+scripts and characters, this involved re-jigging the grapheme break property
+algorithm because Unicode has changed the way emojis are handled.
+
+25. Fixed an obscure bug that struck when there were two atomic groups not
+separated by something with a backtracking point. There could be an incorrect
+backtrack into the first of the atomic groups. A complicated example is
+/(?>a(*:1))(?>b)(*SKIP:1)x|.*/ matched against "abc", where the *SKIP
+shouldn't find a MARK (because is in an atomic group), but it did.
+
+26. Upgraded the perltest.sh script: (1) #pattern lines can now be used to set
+a list of modifiers for all subsequent patterns - only those that the script
+recognizes are meaningful; (2) #subject lines can be used to set or unset a
+default "mark" modifier; (3) Unsupported #command lines give a warning when
+they are ignored; (4) Mark data is output only if the "mark" modifier is
+present.
+
+27. (*ACCEPT:ARG), (*FAIL:ARG), and (*COMMIT:ARG) are now supported.
+
+28. A (*MARK) name was not being passed back for positive assertions that were
+terminated by (*ACCEPT).
+
+29. Add support for \N{U+dddd}, but only in Unicode mode.
+
+30. Add support for (?^) for unsetting all imnsx options.
+
+31. The PCRE2_EXTENDED (/x) option only ever discarded space characters whose
+code point was less than 256 and that were recognized by the lookup table
+generated by pcre2_maketables(), which uses isspace() to identify white space.
+Now, when Unicode support is compiled, PCRE2_EXTENDED also discards U+0085,
+U+200E, U+200F, U+2028, and U+2029, which are additional characters defined by
+Unicode as "Pattern White Space". This makes PCRE2 compatible with Perl.
+
+32. In certain circumstances, option settings within patterns were not being
+correctly processed. For example, the pattern /((?i)A)(?m)B/ incorrectly
+matched "ab". (The (?m) setting lost the fact that (?i) should be reset at the
+end of its group during the parse process, but without another setting such as
+(?m) the compile phase got it right.) This bug was introduced by the
+refactoring in release 10.23.
+
+33. PCRE2 uses bcopy() if available when memmove() is not, and it used just to
+define memmove() as function call to bcopy(). This hasn't been tested for a
+long time because in pcre2test the result of memmove() was being used, whereas
+bcopy() doesn't return a result. This feature is now refactored always to call
+an emulation function when there is no memmove(). The emulation makes use of
+bcopy() when available.
+
+34. When serializing a pattern, set the memctl, executable_jit, and tables
+fields (that is, all the fields that contain pointers) to zeros so that the
+result of serializing is always the same. These fields are re-set when the
+pattern is deserialized.
+
+35. In a pattern such as /[^\x{100}-\x{ffff}]*[\x80-\xff]/ which has a repeated
+negative class with no characters less than 0x100 followed by a positive class
+with only characters less than 0x100, the first class was incorrectly being
+auto-possessified, causing incorrect match failures.
+
+36. Removed the character type bit ctype_meta, which dates from PCRE1 and is
+not used in PCRE2.
+
+37. Tidied up unnecessarily complicated macros used in the escapes table.
+
+38. Since 10.21, the new testoutput8-16-4 file has accidentally been omitted
+from distribution tarballs, owing to a typo in Makefile.am which had
+testoutput8-16-3 twice. Now fixed.
+
+39. If the only branch in a conditional subpattern was anchored, the whole
+subpattern was treated as anchored, when it should not have been, since the
+assumed empty second branch cannot be anchored. Demonstrated by test patterns
+such as /(?(1)^())b/ or /(?(?=^))b/.
+
+40. A repeated conditional subpattern that could match an empty string was
+always assumed to be unanchored. Now it is checked just like any other
+repeated conditional subpattern, and can be found to be anchored if the minimum
+quantifier is one or more. I can't see much use for a repeated anchored
+pattern, but the behaviour is now consistent.
+
+41. Minor addition to pcre2_jit_compile.c to avoid static analyzer complaint
+(for an event that could never occur but you had to have external information
+to know that).
+
+42. If before the first match in a file that was being searched by pcre2grep
+there was a line that was sufficiently long to cause the input buffer to be
+expanded, the variable holding the location of the end of the previous match
+was being adjusted incorrectly, and could cause an overflow warning from a code
+sanitizer. However, as the value is used only to print pending "after" lines
+when the next match is reached (and there are no such lines in this case) this
+bug could do no damage.
+
+
+Version 10.31 12-February-2018
+------------------------------
+
+1. Fix typo (missing ]) in VMS code in pcre2test.c.
+
+2. Replace the replicated code for matching extended Unicode grapheme sequences
+(which got a lot more complicated by change 10.30/49) by a single subroutine
+that is called by both pcre2_match() and pcre2_dfa_match().
+
+3. Add idempotent guard to pcre2_internal.h.
+
+4. Add new pcre2_config() options: PCRE2_CONFIG_NEVER_BACKSLASH_C and
+PCRE2_CONFIG_COMPILED_WIDTHS.
+
+5. Cut out \C tests in the JIT regression tests when NEVER_BACKSLASH_C is
+defined (e.g. by --enable-never-backslash-C).
+
+6. Defined public names for all the pcre2_compile() error numbers, and used
+the public names in pcre2_convert.c.
+
+7. Fixed a small memory leak in pcre2test (convert contexts).
+
+8. Added two casts to compile.c and one to match.c to avoid compiler warnings.
+
+9. Added code to pcre2grep when compiled under VMS to set the symbol
+PCRE2GREP_RC to the exit status, because VMS does not distinguish between
+exit(0) and exit(1).
+
+10. Added the -LM (list modifiers) option to pcre2test. Also made -C complain
+about a bad option only if the following argument item does not start with a
+hyphen.
+
+11. pcre2grep was truncating components of file names to 128 characters when
+processing files with the -r option, and also (some very odd code) truncating
+path names to 512 characters. There is now a check on the absolute length of
+full path file names, which may be up to 2047 characters long.
+
+12. When an assertion contained (*ACCEPT) it caused all open capturing groups
+to be closed (as for a non-assertion ACCEPT), which was wrong and could lead to
+misbehaviour for subsequent references to groups that started outside the
+assertion. ACCEPT in an assertion now closes only those groups that were
+started within that assertion. Fixes oss-fuzz issues 3852 and 3891.
+
+13. Multiline matching in pcre2grep was misbehaving if the pattern matched
+within a line, and then matched again at the end of the line and over into
+subsequent lines. Behaviour was different with and without colouring, and
+sometimes context lines were incorrectly printed and/or line endings were lost.
+All these issues should now be fixed.
+
+14. If --line-buffered was specified for pcre2grep when input was from a
+compressed file (.gz or .bz2) a segfault occurred. (Line buffering should be
+ignored for compressed files.)
+
+15. Although pcre2_jit_match checks whether the pattern is compiled
+in a given mode, it was also expected that at least one mode is available.
+This is fixed and pcre2_jit_match returns with PCRE2_ERROR_JIT_BADOPTION
+when the pattern is not optimized by JIT at all.
+
+16. The line number and related variables such as match counts in pcre2grep
+were all int variables, causing overflow when files with more than 2147483647
+lines were processed (assuming 32-bit ints). They have all been changed to
+unsigned long ints.
+
+17. If a backreference with a minimum repeat count of zero was first in a
+pattern, apart from assertions, an incorrect first matching character could be
+recorded. For example, for the pattern /(?=(a))\1?b/, "b" was incorrectly set
+as the first character of a match.
+
+18. Characters in a leading positive assertion are considered for recording a
+first character of a match when the rest of the pattern does not provide one.
+However, a character in a non-assertive group within a leading assertion such
+as in the pattern /(?=(a))\1?b/ caused this process to fail. This was an
+infelicity rather than an outright bug, because it did not affect the result of
+a match, just its speed. (In fact, in this case, the starting 'a' was
+subsequently picked up in the study.)
+
+19. A minor tidy in pcre2_match(): making all PCRE2_ERROR_ returns use "return"
+instead of "RRETURN" saves unwinding the backtracks in these cases (only one
+didn't).
+
+20. Allocate a single callout block on the stack at the start of pcre2_match()
+and set its never-changing fields once only. Do the same for pcre2_dfa_match().
+
+21. Save the extra compile options (set in the compile context) with the
+compiled pattern (they were not previously saved), add PCRE2_INFO_EXTRAOPTIONS
+to retrieve them, and update pcre2test to show them.
+
+22. Added PCRE2_CALLOUT_STARTMATCH and PCRE2_CALLOUT_BACKTRACK bits to a new
+field callout_flags in callout blocks. The bits are set by pcre2_match(), but
+not by JIT or pcre2_dfa_match(). Their settings are shown in pcre2test callouts
+if the callout_extra subject modifier is set. These bits are provided to help
+with tracking how a backtracking match is proceeding.
+
+23. Updated the pcre2demo.c demonstration program, which was missing the extra
+code for -g that handles the case when \K in an assertion causes the match to
+end at the original start point. Also arranged for it to detect when \K causes
+the end of a match to be before its start.
+
+24. Similar to 23 above, strange things (including loops) could happen in
+pcre2grep when \K was used in an assertion when --colour was used or in
+multiline mode. The "end at original start point" bug is fixed, and if the end
+point is found to be before the start point, they are swapped.
+
+25. When PCRE2_FIRSTLINE without PCRE2_NO_START_OPTIMIZE was used in non-JIT
+matching (both pcre2_match() and pcre2_dfa_match()) and the matched string
+started with the first code unit of a newline sequence, matching failed because
+it was not tried at the newline.
+
+26. Code for giving up a non-partial match after failing to find a starting
+code unit anywhere in the subject was missing when searching for one of a
+number of code units (the bitmap case) in both pcre2_match() and
+pcre2_dfa_match(). This was a missing optimization rather than a bug.
+
+27. Tidied up the ACROSSCHAR macro to be like FORWARDCHAR and BACKCHAR, using a
+pointer argument rather than a code unit value. This should not have affected
+the generated code.
+
+28. The JIT compiler has been updated.
+
+29. Avoid pointer overflow for unset captures in pcre2_substring_list_get().
+This could not actually cause a crash because it was always used in a memcpy()
+call with zero length.
+
+30. Some internal structures have a variable-length ovector[] as their last
+element. Their actual memory is obtained dynamically, giving an ovector of
+appropriate length. However, they are defined in the structure as
+ovector[NUMBER], where NUMBER is large so that array bound checkers don't
+grumble. The value of NUMBER was 10000, but a fuzzer exceeded 5000 capturing
+groups, making the ovector larger than this. The number has been increased to
+131072, which allows for the maximum number of captures (65535) plus the
+overall match. This fixes oss-fuzz issue 5415.
+
+31. Auto-possessification at the end of a capturing group was dependent on what
+follows the group (e.g. /(a+)b/ would auto-possessify the a+) but this caused
+incorrect behaviour when the group was called recursively from elsewhere in the
+pattern where something different might follow. This bug is an unforseen
+consequence of change #1 for 10.30 - the implementation of backtracking into
+recursions. Iterators at the ends of capturing groups are no longer considered
+for auto-possessification if the pattern contains any recursions. Fixes
+Bugzilla #2232.
+
+
+Version 10.30 14-August-2017
+----------------------------
+
+1. The main interpreter, pcre2_match(), has been refactored into a new version
+that does not use recursive function calls (and therefore the stack) for
+remembering backtracking positions. This makes --disable-stack-for-recursion a
+NOOP. The new implementation allows backtracking into recursive group calls in
+patterns, making it more compatible with Perl, and also fixes some other
+hard-to-do issues such as #1887 in Bugzilla. The code is also cleaner because
+the old code had a number of fudges to try to reduce stack usage. It seems to
+run no slower than the old code.
+
+A number of bugs in the refactored code were subsequently fixed during testing
+before release, but after the code was made available in the repository. These
+bugs were never in fully released code, but are noted here for the record.
+
+ (a) If a pattern had fewer capturing parentheses than the ovector supplied in
+ the match data block, a memory error (detectable by ASAN) occurred after
+ a match, because the external block was being set from non-existent
+ internal ovector fields. Fixes oss-fuzz issue 781.
+
+ (b) A pattern with very many capturing parentheses (when the internal frame
+ size was greater than the initial frame vector on the stack) caused a
+ crash. A vector on the heap is now set up at the start of matching if the
+ vector on the stack is not big enough to handle at least 10 frames.
+ Fixes oss-fuzz issue 783.
+
+ (c) Handling of (*VERB)s in recursions was wrong in some cases.
+
+ (d) Captures in negative assertions that were used as conditions were not
+ happening if the assertion matched via (*ACCEPT).
+
+ (e) Mark values were not being passed out of recursions.
+
+ (f) Refactor some code in do_callout() to avoid picky compiler warnings about
+ negative indices. Fixes oss-fuzz issue 1454.
+
+ (g) Similarly refactor the way the variable length ovector is addressed for
+ similar reasons. Fixes oss-fuzz issue 1465.
+
+2. Now that pcre2_match() no longer uses recursive function calls (see above),
+the "match limit recursion" value seems misnamed. It still exists, and limits
+the depth of tree that is searched. To avoid future confusion, it has been
+renamed as "depth limit" in all relevant places (--with-depth-limit,
+(*LIMIT_DEPTH), pcre2_set_depth_limit(), etc) but the old names are still
+available for backwards compatibility.
+
+3. Hardened pcre2test so as to reduce the number of bugs reported by fuzzers:
+
+ (a) Check for malloc failures when getting memory for the ovector (POSIX) or
+ the match data block (non-POSIX).
+
+4. In the 32-bit library in non-UTF mode, an attempt to find a Unicode property
+for a character with a code point greater than 0x10ffff (the Unicode maximum)
+caused a crash.
+
+5. If a lookbehind assertion that contained a back reference to a group
+appearing later in the pattern was compiled with the PCRE2_ANCHORED option,
+undefined actions (often a segmentation fault) could occur, depending on what
+other options were set. An example assertion is (?" should be ">=" in opcode check in pcre2_auto_possess.c.
+ (b) Added some casts to avoid "suspicious implicit sign extension".
+ (c) Resource leaks in pcre2test in rare error cases.
+ (d) Avoid warning for never-use case OP_TABLE_LENGTH which is just a fudge
+ for checking at compile time that tables are the right size.
+ (e) Add missing "fall through" comment.
+
+29. Implemented PCRE2_EXTENDED_MORE and related /xx and (?xx) features.
+
+30. Implement (?n: for PCRE2_NO_AUTO_CAPTURE, because Perl now has this.
+
+31. If more than one of "push", "pushcopy", or "pushtablescopy" were set in
+pcre2test, a crash could occur.
+
+32. Make -bigstack in RunTest allocate a 64MiB stack (instead of 16MiB) so
+that all the tests can run with clang's sanitizing options.
+
+33. Implement extra compile options in the compile context and add the first
+one: PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES.
+
+34. Implement newline type PCRE2_NEWLINE_NUL.
+
+35. A lookbehind assertion that had a zero-length branch caused undefined
+behaviour when processed by pcre2_dfa_match(). This is oss-fuzz issue 1859.
+
+36. The match limit value now also applies to pcre2_dfa_match() as there are
+patterns that can use up a lot of resources without necessarily recursing very
+deeply. (Compare item 10.23/36.) This should fix oss-fuzz #1761.
+
+37. Implement PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL.
+
+38. Fix returned offsets from regexec() when REG_STARTEND is used with a
+starting offset greater than zero.
+
+39. Implement REG_PEND (GNU extension) for the POSIX wrapper.
+
+40. Implement the subject_literal modifier in pcre2test, and allow jitstack on
+pattern lines.
+
+41. Implement PCRE2_LITERAL and use it to support REG_NOSPEC.
+
+42. Implement PCRE2_EXTRA_MATCH_LINE and PCRE2_EXTRA_MATCH_WORD for the benefit
+of pcre2grep.
+
+43. Re-implement pcre2grep's -F, -w, and -x options using PCRE2_LITERAL,
+PCRE2_EXTRA_MATCH_WORD, and PCRE2_EXTRA_MATCH_LINE. This fixes two bugs:
+
+ (a) The -F option did not work for fixed strings containing \E.
+ (b) The -w option did not work for patterns with multiple branches.
+
+44. Added configuration options for the SELinux compatible execmem allocator in
+JIT.
+
+45. Increased the limit for searching for a "must be present" code unit in
+subjects from 1000 to 2000 for 8-bit searches, since they use memchr() and are
+much faster.
+
+46. Arrange for anchored patterns to record and use "first code unit" data,
+because this can give a fast "no match" without searching for a "required code
+unit". Previously only non-anchored patterns did this.
+
+47. Upgraded the Unicode tables from Unicode 8.0.0 to Unicode 10.0.0.
+
+48. Add the callout_no_where modifier to pcre2test.
+
+49. Update extended grapheme breaking rules to the latest set that are in
+Unicode Standard Annex #29.
+
+50. Added experimental foreign pattern conversion facilities
+(pcre2_pattern_convert() and friends).
+
+51. Change the macro FWRITE, used in pcre2grep, to FWRITE_IGNORE because FWRITE
+is defined in a system header in cygwin. Also modified some of the #ifdefs in
+pcre2grep related to Windows and Cygwin support.
+
+52. Change 3(g) for 10.23 was a bit too zealous. If a hyphen that follows a
+character class is the last character in the class, Perl does not give a
+warning. PCRE2 now also treats this as a literal.
+
+53. Related to 52, though PCRE2 was throwing an error for [[:digit:]-X] it was
+not doing so for [\d-X] (and similar escapes), as is documented.
+
+54. Fixed a MIPS issue in the JIT compiler reported by Joshua Kinard.
+
+55. Fixed a "maybe uninitialized" warning for class_uchardata in \p handling in
+pcre2_compile() which could never actually trigger (code should have been cut
+out when Unicode support is disabled).
+
+
+Version 10.23 14-February-2017
+------------------------------
+
+1. Extended pcre2test with the utf8_input modifier so that it is able to
+generate all possible 16-bit and 32-bit code unit values in non-UTF modes.
+
+2. In any wide-character mode (8-bit UTF or any 16-bit or 32-bit mode), without
+PCRE2_UCP set, a negative character type such as \D in a positive class should
+cause all characters greater than 255 to match, whatever else is in the class.
+There was a bug that caused this not to happen if a Unicode property item was
+added to such a class, for example [\D\P{Nd}] or [\W\pL].
+
+3. There has been a major re-factoring of the pcre2_compile.c file. Most syntax
+checking is now done in the pre-pass that identifies capturing groups. This has
+reduced the amount of duplication and made the code tidier. While doing this,
+some minor bugs and Perl incompatibilities were fixed, including:
+
+ (a) \Q\E in the middle of a quantifier such as A+\Q\E+ is now ignored instead
+ of giving an invalid quantifier error.
+
+ (b) {0} can now be used after a group in a lookbehind assertion; previously
+ this caused an "assertion is not fixed length" error.
+
+ (c) Perl always treats (?(DEFINE) as a "define" group, even if a group with
+ the name "DEFINE" exists. PCRE2 now does likewise.
+
+ (d) A recursion condition test such as (?(R2)...) must now refer to an
+ existing subpattern.
+
+ (e) A conditional recursion test such as (?(R)...) misbehaved if there was a
+ group whose name began with "R".
+
+ (f) When testing zero-terminated patterns under valgrind, the terminating
+ zero is now marked "no access". This catches bugs that would otherwise
+ show up only with non-zero-terminated patterns.
+
+ (g) A hyphen appearing immediately after a POSIX character class (for example
+ /[[:ascii:]-z]/) now generates an error. Perl does accept this as a
+ literal, but gives a warning, so it seems best to fail it in PCRE.
+
+ (h) An empty \Q\E sequence may appear after a callout that precedes an
+ assertion condition (it is, of course, ignored).
+
+One effect of the refactoring is that some error numbers and messages have
+changed, and the pattern offset given for compiling errors is not always the
+right-most character that has been read. In particular, for a variable-length
+lookbehind assertion it now points to the start of the assertion. Another
+change is that when a callout appears before a group, the "length of next
+pattern item" that is passed now just gives the length of the opening
+parenthesis item, not the length of the whole group. A length of zero is now
+given only for a callout at the end of the pattern. Automatic callouts are no
+longer inserted before and after explicit callouts in the pattern.
+
+A number of bugs in the refactored code were subsequently fixed during testing
+before release, but after the code was made available in the repository. Many
+of the bugs were discovered by fuzzing testing. Several of them were related to
+the change from assuming a zero-terminated pattern (which previously had
+required non-zero terminated strings to be copied). These bugs were never in
+fully released code, but are noted here for the record.
+
+ (a) An overall recursion such as (?0) inside a lookbehind assertion was not
+ being diagnosed as an error.
+
+ (b) In utf mode, the length of a *MARK (or other verb) name was being checked
+ in characters instead of code units, which could lead to bad code being
+ compiled, leading to unpredictable behaviour.
+
+ (c) In extended /x mode, characters whose code was greater than 255 caused
+ a lookup outside one of the global tables. A similar bug existed for wide
+ characters in *VERB names.
+
+ (d) The amount of memory needed for a compiled pattern was miscalculated if a
+ lookbehind contained more than one toplevel branch and the first branch
+ was of length zero.
+
+ (e) In UTF-8 or UTF-16 modes with PCRE2_EXTENDED (/x) set and a non-zero-
+ terminated pattern, if a # comment ran on to the end of the pattern, one
+ or more code units past the end were being read.
+
+ (f) An unterminated repeat at the end of a non-zero-terminated pattern (e.g.
+ "{2,2") could cause reading beyond the pattern.
+
+ (g) When reading a callout string, if the end delimiter was at the end of the
+ pattern one further code unit was read.
+
+ (h) An unterminated number after \g' could cause reading beyond the pattern.
+
+ (i) An insufficient memory size was being computed for compiling with
+ PCRE2_AUTO_CALLOUT.
+
+ (j) A conditional group with an assertion condition used more memory than was
+ allowed for it during parsing, so too many of them could therefore
+ overrun a buffer.
+
+ (k) If parsing a pattern exactly filled the buffer, the internal test for
+ overrun did not check when the final META_END item was added.
+
+ (l) If a lookbehind contained a subroutine call, and the called group
+ contained an option setting such as (?s), and the PCRE2_ANCHORED option
+ was set, unpredictable behaviour could occur. The underlying bug was
+ incorrect code and insufficient checking while searching for the end of
+ the called subroutine in the parsed pattern.
+
+ (m) Quantifiers following (*VERB)s were not being diagnosed as errors.
+
+ (n) The use of \Q...\E in a (*VERB) name when PCRE2_ALT_VERBNAMES and
+ PCRE2_AUTO_CALLOUT were both specified caused undetermined behaviour.
+
+ (o) If \Q was preceded by a quantified item, and the following \E was
+ followed by '?' or '+', and there was at least one literal character
+ between them, an internal error "unexpected repeat" occurred (example:
+ /.+\QX\E+/).
+
+ (p) A buffer overflow could occur while sorting the names in the group name
+ list (depending on the order in which the names were seen).
+
+ (q) A conditional group that started with a callout was not doing the right
+ check for a following assertion, leading to compiling bad code. Example:
+ /(?(C'XX))?!XX/
+
+ (r) If a character whose code point was greater than 0xffff appeared within
+ a lookbehind that was within another lookbehind, the calculation of the
+ lookbehind length went wrong and could provoke an internal error.
+
+ (t) The sequence \E- or \Q\E- after a POSIX class in a character class caused
+ an internal error. Now the hyphen is treated as a literal.
+
+4. Back references are now permitted in lookbehind assertions when there are
+no duplicated group numbers (that is, (?| has not been used), and, if the
+reference is by name, there is only one group of that name. The referenced
+group must, of course be of fixed length.
+
+5. pcre2test has been upgraded so that, when run under valgrind with valgrind
+support enabled, reading past the end of the pattern is detected, both when
+compiling and during callout processing.
+
+6. \g{+} (e.g. \g{+2} ) is now supported. It is a "forward back
+reference" and can be useful in repetitions (compare \g{-} ). Perl does
+not recognize this syntax.
+
+7. Automatic callouts are no longer generated before and after callouts in the
+pattern.
+
+8. When pcre2test was outputting information from a callout, the caret indicator
+for the current position in the subject line was incorrect if it was after an
+escape sequence for a character whose code point was greater than \x{ff}.
+
+9. Change 19 for 10.22 had a typo (PCRE_STATIC_RUNTIME should be
+PCRE2_STATIC_RUNTIME). Fix from David Gaussmann.
+
+10. Added --max-buffer-size to pcre2grep, to allow for automatic buffer
+expansion when long lines are encountered. Original patch by Dmitry
+Cherniachenko.
+
+11. If pcre2grep was compiled with JIT support, but the library was compiled
+without it (something that neither ./configure nor CMake allow, but it can be
+done by editing config.h), pcre2grep was giving a JIT error. Now it detects
+this situation and does not try to use JIT.
+
+12. Added some "const" qualifiers to variables in pcre2grep.
+
+13. Added Dmitry Cherniachenko's patch for colouring output in Windows
+(untested by me). Also, look for GREP_COLOUR or GREP_COLOR if the environment
+variables PCRE2GREP_COLOUR and PCRE2GREP_COLOR are not found.
+
+14. Add the -t (grand total) option to pcre2grep.
+
+15. A number of bugs have been mended relating to match start-up optimizations
+when the first thing in a pattern is a positive lookahead. These all applied
+only when PCRE2_NO_START_OPTIMIZE was *not* set:
+
+ (a) A pattern such as (?=.*X)X$ was incorrectly optimized as if it needed
+ both an initial 'X' and a following 'X'.
+ (b) Some patterns starting with an assertion that started with .* were
+ incorrectly optimized as having to match at the start of the subject or
+ after a newline. There are cases where this is not true, for example,
+ (?=.*[A-Z])(?=.{8,16})(?!.*[\s]) matches after the start in lines that
+ start with spaces. Starting .* in an assertion is no longer taken as an
+ indication of matching at the start (or after a newline).
+
+16. The "offset" modifier in pcre2test was not being ignored (as documented)
+when the POSIX API was in use.
+
+17. Added --enable-fuzz-support to "configure", causing an non-installed
+library containing a test function that can be called by fuzzers to be
+compiled. A non-installed binary to run the test function locally, called
+pcre2fuzzcheck is also compiled.
+
+18. A pattern with PCRE2_DOTALL (/s) set but not PCRE2_NO_DOTSTAR_ANCHOR, and
+which started with .* inside a positive lookahead was incorrectly being
+compiled as implicitly anchored.
+
+19. Removed all instances of "register" declarations, as they are considered
+obsolete these days and in any case had become very haphazard.
+
+20. Add strerror() to pcre2test for failed file opening.
+
+21. Make pcre2test -C list valgrind support when it is enabled.
+
+22. Add the use_length modifier to pcre2test.
+
+23. Fix an off-by-one bug in pcre2test for the list of names for 'get' and
+'copy' modifiers.
+
+24. Add PCRE2_CALL_CONVENTION into the prototype declarations in pcre2.h as it
+is apparently needed there as well as in the function definitions. (Why did
+nobody ask for this in PCRE1?)
+
+25. Change the _PCRE2_H and _PCRE2_UCP_H guard macros in the header files to
+PCRE2_H_IDEMPOTENT_GUARD and PCRE2_UCP_H_IDEMPOTENT_GUARD to be more standard
+compliant and unique.
+
+26. pcre2-config --libs-posix was listing -lpcre2posix instead of
+-lpcre2-posix. Also, the CMake build process was building the library with the
+wrong name.
+
+27. In pcre2test, give some offset information for errors in hex patterns.
+This uses the C99 formatting sequence %td, except for MSVC which doesn't
+support it - %lu is used instead.
+
+28. Implemented pcre2_code_copy_with_tables(), and added pushtablescopy to
+pcre2test for testing it.
+
+29. Fix small memory leak in pcre2test.
+
+30. Fix out-of-bounds read for partial matching of /./ against an empty string
+when the newline type is CRLF.
+
+31. Fix a bug in pcre2test that caused a crash when a locale was set either in
+the current pattern or a previous one and a wide character was matched.
+
+32. The appearance of \p, \P, or \X in a substitution string when
+PCRE2_SUBSTITUTE_EXTENDED was set caused a segmentation fault (NULL
+dereference).
+
+33. If the starting offset was specified as greater than the subject length in
+a call to pcre2_substitute() an out-of-bounds memory reference could occur.
+
+34. When PCRE2 was compiled to use the heap instead of the stack for recursive
+calls to match(), a repeated minimizing caseless back reference, or a
+maximizing one where the two cases had different numbers of code units,
+followed by a caseful back reference, could lose the caselessness of the first
+repeated back reference (example: /(Z)(a)\2{1,2}?(?-i)\1X/i should match ZaAAZX
+but didn't).
+
+35. When a pattern is too complicated, PCRE2 gives up trying to find a minimum
+matching length and just records zero. Typically this happens when there are
+too many nested or recursive back references. If the limit was reached in
+certain recursive cases it failed to be triggered and an internal error could
+be the result.
+
+36. The pcre2_dfa_match() function now takes note of the recursion limit for
+the internal recursive calls that are used for lookrounds and recursions within
+the pattern.
+
+37. More refactoring has got rid of the internal could_be_empty_branch()
+function (around 400 lines of code, including comments) by keeping track of
+could-be-emptiness as the pattern is compiled instead of scanning compiled
+groups. (This would have been much harder before the refactoring of #3 above.)
+This lifts a restriction on the number of branches in a group (more than about
+1100 would give "pattern is too complicated").
+
+38. Add the "-ac" command line option to pcre2test as a synonym for "-pattern
+auto_callout".
+
+39. In a library with Unicode support, incorrect data was compiled for a
+pattern with PCRE2_UCP set without PCRE2_UTF if a class required all wide
+characters to match (for example, /[\s[:^ascii:]]/).
+
+40. The callout_error modifier has been added to pcre2test to make it possible
+to return PCRE2_ERROR_CALLOUT from a callout.
+
+41. A minor change to pcre2grep: colour reset is now "[0m" instead of
+"[00m".
+
+42. The limit in the auto-possessification code that was intended to catch
+overly-complicated patterns and not spend too much time auto-possessifying was
+being reset too often, resulting in very long compile times for some patterns.
+Now such patterns are no longer completely auto-possessified.
+
+43. Applied Jason Hood's revised patch for RunTest.bat.
+
+44. Added a new Windows script RunGrepTest.bat, courtesy of Jason Hood.
+
+45. Minor cosmetic fix to pcre2test: move a variable that is not used under
+Windows into the "not Windows" code.
+
+46. Applied Jason Hood's patches to upgrade pcre2grep under Windows and tidy
+some of the code:
+
+ * normalised the Windows condition by ensuring WIN32 is defined;
+ * enables the callout feature under Windows;
+ * adds globbing (Microsoft's implementation expands quoted args),
+ using a tweaked opendirectory;
+ * implements the is_*_tty functions for Windows;
+ * --color=always will write the ANSI sequences to file;
+ * add sequences 4 (underline works on Win10) and 5 (blink as bright
+ background, relatively standard on DOS/Win);
+ * remove the (char *) casts for the now-const strings;
+ * remove GREP_COLOUR (grep's command line allowed the 'u', but not
+ the environment), parsing GREP_COLORS instead;
+ * uses the current colour if not set, rather than black;
+ * add print_match for the undefined case;
+ * fixes a typo.
+
+In addition, colour settings containing anything other than digits and
+semicolon are ignored, and the colour controls are no longer output for empty
+strings.
+
+47. Detecting patterns that are too large inside the length-measuring loop
+saves processing ridiculously long patterns to their end.
+
+48. Ignore PCRE2_CASELESS when processing \h, \H, \v, and \V in classes as it
+just wastes time. In the UTF case it can also produce redundant entries in
+XCLASS lists caused by characters with multiple other cases and pairs of
+characters in the same "not-x" sublists.
+
+49. A pattern such as /(?=(a\K))/ can report the end of the match being before
+its start; pcre2test was not handling this correctly when using the POSIX
+interface (it was OK with the native interface).
+
+50. In pcre2grep, ignore all JIT compile errors. This means that pcre2grep will
+continue to work, falling back to interpretation if anything goes wrong with
+JIT.
+
+51. Applied patches from Christian Persch to configure.ac to make use of the
+AC_USE_SYSTEM_EXTENSIONS macro and to test for functions used by the JIT
+modules.
+
+52. Minor fixes to pcre2grep from Jason Hood:
+ * fixed some spacing;
+ * Windows doesn't usually use single quotes, so I've added a define
+ to use appropriate quotes [in an example];
+ * LC_ALL was displayed as "LCC_ALL";
+ * numbers 11, 12 & 13 should end in "th";
+ * use double quotes in usage message.
+
+53. When autopossessifying, skip empty branches without recursion, to reduce
+stack usage for the benefit of clang with -fsanitize-address, which uses huge
+stack frames. Example pattern: /X?(R||){3335}/. Fixes oss-fuzz issue 553.
+
+54. A pattern with very many explicit back references to a group that is a long
+way from the start of the pattern could take a long time to compile because
+searching for the referenced group in order to find the minimum length was
+being done repeatedly. Now up to 128 group minimum lengths are cached and the
+attempt to find a minimum length is abandoned if there is a back reference to a
+group whose number is greater than 128. (In that case, the pattern is so
+complicated that this optimization probably isn't worth it.) This fixes
+oss-fuzz issue 557.
+
+55. Issue 32 for 10.22 below was not correctly fixed. If pcre2grep in multiline
+mode with --only-matching matched several lines, it restarted scanning at the
+next line instead of moving on to the end of the matched string, which can be
+several lines after the start.
+
+56. Applied Jason Hood's new patch for RunGrepTest.bat that updates it in line
+with updates to the non-Windows version.
+
+
+
+Version 10.22 29-July-2016
+--------------------------
+
+1. Applied Jason Hood's patches to RunTest.bat and testdata/wintestoutput3
+to fix problems with running the tests under Windows.
+
+2. Implemented a facility for quoting literal characters within hexadecimal
+patterns in pcre2test, to make it easier to create patterns with just a few
+non-printing characters.
+
+3. Binary zeros are not supported in pcre2test input files. It now detects them
+and gives an error.
+
+4. Updated the valgrind parameters in RunTest: (a) changed smc-check=all to
+smc-check=all-non-file; (b) changed obj:* in the suppression file to obj:??? so
+that it matches only unknown objects.
+
+5. Updated the maintenance script maint/ManyConfigTests to make it easier to
+select individual groups of tests.
+
+6. When the POSIX wrapper function regcomp() is called, the REG_NOSUB option
+used to set PCRE2_NO_AUTO_CAPTURE when calling pcre2_compile(). However, this
+disables the use of back references (and subroutine calls), which are supported
+by other implementations of regcomp() with RE_NOSUB. Therefore, REG_NOSUB no
+longer causes PCRE2_NO_AUTO_CAPTURE to be set, though it still ignores nmatch
+and pmatch when regexec() is called.
+
+7. Because of 6 above, pcre2test has been modified with a new modifier called
+posix_nosub, to call regcomp() with REG_NOSUB. Previously the no_auto_capture
+modifier had this effect. That option is now ignored when the POSIX API is in
+use.
+
+8. Minor tidies to the pcre2demo.c sample program, including more comments
+about its 8-bit-ness.
+
+9. Detect unmatched closing parentheses and give the error in the pre-scan
+instead of later. Previously the pre-scan carried on and could give a
+misleading incorrect error message. For example, /(?J)(?'a'))(?'a')/ gave a
+message about invalid duplicate group names.
+
+10. It has happened that pcre2test was accidentally linked with another POSIX
+regex library instead of libpcre2-posix. In this situation, a call to regcomp()
+(in the other library) may succeed, returning zero, but of course putting its
+own data into the regex_t block. In one example the re_pcre2_code field was
+left as NULL, which made pcre2test think it had not got a compiled POSIX regex,
+so it treated the next line as another pattern line, resulting in a confusing
+error message. A check has been added to pcre2test to see if the data returned
+from a successful call of regcomp() are valid for PCRE2's regcomp(). If they
+are not, an error message is output and the pcre2test run is abandoned. The
+message points out the possibility of a mis-linking. Hopefully this will avoid
+some head-scratching the next time this happens.
+
+11. A pattern such as /(?<=((?C)0))/, which has a callout inside a lookbehind
+assertion, caused pcre2test to output a very large number of spaces when the
+callout was taken, making the program appearing to loop.
+
+12. A pattern that included (*ACCEPT) in the middle of a sufficiently deeply
+nested set of parentheses of sufficient size caused an overflow of the
+compiling workspace (which was diagnosed, but of course is not desirable).
+
+13. Detect missing closing parentheses during the pre-pass for group
+identification.
+
+14. Changed some integer variable types and put in a number of casts, following
+a report of compiler warnings from Visual Studio 2013 and a few tests with
+gcc's -Wconversion (which still throws up a lot).
+
+15. Implemented pcre2_code_copy(), and added pushcopy and #popcopy to pcre2test
+for testing it.
+
+16. Change 66 for 10.21 introduced the use of snprintf() in PCRE2's version of
+regerror(). When the error buffer is too small, my version of snprintf() puts a
+binary zero in the final byte. Bug #1801 seems to show that other versions do
+not do this, leading to bad output from pcre2test when it was checking for
+buffer overflow. It no longer assumes a binary zero at the end of a too-small
+regerror() buffer.
+
+17. Fixed typo ("&&" for "&") in pcre2_study(). Fortunately, this could not
+actually affect anything, by sheer luck.
+
+18. Two minor fixes for MSVC compilation: (a) removal of apparently incorrect
+"const" qualifiers in pcre2test and (b) defining snprintf as _snprintf for
+older MSVC compilers. This has been done both in src/pcre2_internal.h for most
+of the library, and also in src/pcre2posix.c, which no longer includes
+pcre2_internal.h (see 24 below).
+
+19. Applied Chris Wilson's patch (Bugzilla #1681) to CMakeLists.txt for MSVC
+static compilation. Subsequently applied Chris Wilson's second patch, putting
+the first patch under a new option instead of being unconditional when
+PCRE_STATIC is set.
+
+20. Updated pcre2grep to set stdout as binary when run under Windows, so as not
+to convert \r\n at the ends of reflected lines into \r\r\n. This required
+ensuring that other output that is written to stdout (e.g. file names) uses the
+appropriate line terminator: \r\n for Windows, \n otherwise.
+
+21. When a line is too long for pcre2grep's internal buffer, show the maximum
+length in the error message.
+
+22. Added support for string callouts to pcre2grep (Zoltan's patch with PH
+additions).
+
+23. RunTest.bat was missing a "set type" line for test 22.
+
+24. The pcre2posix.c file was including pcre2_internal.h, and using some
+"private" knowledge of the data structures. This is unnecessary; the code has
+been re-factored and no longer includes pcre2_internal.h.
+
+25. A racing condition is fixed in JIT reported by Mozilla.
+
+26. Minor code refactor to avoid "array subscript is below array bounds"
+compiler warning.
+
+27. Minor code refactor to avoid "left shift of negative number" warning.
+
+28. Add a bit more sanity checking to pcre2_serialize_decode() and document
+that it expects trusted data.
+
+29. Fix typo in pcre2_jit_test.c
+
+30. Due to an oversight, pcre2grep was not making use of JIT when available.
+This is now fixed.
+
+31. The RunGrepTest script is updated to use the valgrind suppressions file
+when testing with JIT under valgrind (compare 10.21/51 below). The suppressions
+file is updated so that is now the same as for PCRE1: it suppresses the
+Memcheck warnings Addr16 and Cond in unknown objects (that is, JIT-compiled
+code). Also changed smc-check=all to smc-check=all-non-file as was done for
+RunTest (see 4 above).
+
+32. Implemented the PCRE2_NO_JIT option for pcre2_match().
+
+33. Fix typo that gave a compiler error when JIT not supported.
+
+34. Fix comment describing the returns from find_fixedlength().
+
+35. Fix potential negative index in pcre2test.
+
+36. Calls to pcre2_get_error_message() with error numbers that are never
+returned by PCRE2 functions were returning empty strings. Now the error code
+PCRE2_ERROR_BADDATA is returned. A facility has been added to pcre2test to
+show the texts for given error numbers (i.e. to call pcre2_get_error_message()
+and display what it returns) and a few representative error codes are now
+checked in RunTest.
+
+37. Added "&& !defined(__INTEL_COMPILER)" to the test for __GNUC__ in
+pcre2_match.c, in anticipation that this is needed for the same reason it was
+recently added to pcrecpp.cc in PCRE1.
+
+38. Using -o with -M in pcre2grep could cause unnecessary repeated output when
+the match extended over a line boundary, as it tried to find more matches "on
+the same line" - but it was already over the end.
+
+39. Allow \C in lookbehinds and DFA matching in UTF-32 mode (by converting it
+to the same code as '.' when PCRE2_DOTALL is set).
+
+40. Fix two clang compiler warnings in pcre2test when only one code unit width
+is supported.
+
+41. Upgrade RunTest to automatically re-run test 2 with a large (64MiB) stack
+if it fails when running the interpreter with a 16MiB stack (and if changing
+the stack size via pcre2test is possible). This avoids having to manually set a
+large stack size when testing with clang.
+
+42. Fix register overwrite in JIT when SSE2 acceleration is enabled.
+
+43. Detect integer overflow in pcre2test pattern and data repetition counts.
+
+44. In pcre2test, ignore "allcaptures" after DFA matching.
+
+45. Fix unaligned accesses on x86. Patch by Marc Mutz.
+
+46. Fix some more clang compiler warnings.
+
+
+Version 10.21 12-January-2016
+-----------------------------
+
+1. Improve matching speed of patterns starting with + or * in JIT.
+
+2. Use memchr() to find the first character in an unanchored match in 8-bit
+mode in the interpreter. This gives a significant speed improvement.
+
+3. Removed a redundant copy of the opcode_possessify table in the
+pcre2_auto_possessify.c source.
+
+4. Fix typos in dftables.c for z/OS.
+
+5. Change 36 for 10.20 broke the handling of [[:>:]] and [[:<:]] in that
+processing them could involve a buffer overflow if the following character was
+an opening parenthesis.
+
+6. Change 36 for 10.20 also introduced a bug in processing this pattern:
+/((?x)(*:0))#(?'/. Specifically: if a setting of (?x) was followed by a (*MARK)
+setting (which (*:0) is), then (?x) did not get unset at the end of its group
+during the scan for named groups, and hence the external # was incorrectly
+treated as a comment and the invalid (?' at the end of the pattern was not
+diagnosed. This caused a buffer overflow during the real compile. This bug was
+discovered by Karl Skomski with the LLVM fuzzer.
+
+7. Moved the pcre2_find_bracket() function from src/pcre2_compile.c into its
+own source module to avoid a circular dependency between src/pcre2_compile.c
+and src/pcre2_study.c
+
+8. A callout with a string argument containing an opening square bracket, for
+example /(?C$[$)(?<]/, was incorrectly processed and could provoke a buffer
+overflow. This bug was discovered by Karl Skomski with the LLVM fuzzer.
+
+9. The handling of callouts during the pre-pass for named group identification
+has been tightened up.
+
+10. The quantifier {1} can be ignored, whether greedy, non-greedy, or
+possessive. This is a very minor optimization.
+
+11. A possessively repeated conditional group that could match an empty string,
+for example, /(?(R))*+/, was incorrectly compiled.
+
+12. The Unicode tables have been updated to Unicode 8.0.0 (thanks to Christian
+Persch).
+
+13. An empty comment (?#) in a pattern was incorrectly processed and could
+provoke a buffer overflow. This bug was discovered by Karl Skomski with the
+LLVM fuzzer.
+
+14. Fix infinite recursion in the JIT compiler when certain patterns such as
+/(?:|a|){100}x/ are analysed.
+
+15. Some patterns with character classes involving [: and \\ were incorrectly
+compiled and could cause reading from uninitialized memory or an incorrect
+error diagnosis. Examples are: /[[:\\](?<[::]/ and /[[:\\](?'abc')[a:]. The
+first of these bugs was discovered by Karl Skomski with the LLVM fuzzer.
+
+16. Pathological patterns containing many nested occurrences of [: caused
+pcre2_compile() to run for a very long time. This bug was found by the LLVM
+fuzzer.
+
+17. A missing closing parenthesis for a callout with a string argument was not
+being diagnosed, possibly leading to a buffer overflow. This bug was found by
+the LLVM fuzzer.
+
+18. A conditional group with only one branch has an implicit empty alternative
+branch and must therefore be treated as potentially matching an empty string.
+
+19. If (?R was followed by - or + incorrect behaviour happened instead of a
+diagnostic. This bug was discovered by Karl Skomski with the LLVM fuzzer.
+
+20. Another bug that was introduced by change 36 for 10.20: conditional groups
+whose condition was an assertion preceded by an explicit callout with a string
+argument might be incorrectly processed, especially if the string contained \Q.
+This bug was discovered by Karl Skomski with the LLVM fuzzer.
+
+21. Compiling PCRE2 with the sanitize options of clang showed up a number of
+very pedantic coding infelicities and a buffer overflow while checking a UTF-8
+string if the final multi-byte UTF-8 character was truncated.
+
+22. For Perl compatibility in EBCDIC environments, ranges such as a-z in a
+class, where both values are literal letters in the same case, omit the
+non-letter EBCDIC code points within the range.
+
+23. Finding the minimum matching length of complex patterns with back
+references and/or recursions can take a long time. There is now a cut-off that
+gives up trying to find a minimum length when things get too complex.
+
+24. An optimization has been added that speeds up finding the minimum matching
+length for patterns containing repeated capturing groups or recursions.
+
+25. If a pattern contained a back reference to a group whose number was
+duplicated as a result of appearing in a (?|...) group, the computation of the
+minimum matching length gave a wrong result, which could cause incorrect "no
+match" errors. For such patterns, a minimum matching length cannot at present
+be computed.
+
+26. Added a check for integer overflow in conditions (?() and
+(?(R). This omission was discovered by Karl Skomski with the LLVM
+fuzzer.
+
+27. Fixed an issue when \p{Any} inside an xclass did not read the current
+character.
+
+28. If pcre2grep was given the -q option with -c or -l, or when handling a
+binary file, it incorrectly wrote output to stdout.
+
+29. The JIT compiler did not restore the control verb head in case of *THEN
+control verbs. This issue was found by Karl Skomski with a custom LLVM fuzzer.
+
+30. The way recursive references such as (?3) are compiled has been re-written
+because the old way was the cause of many issues. Now, conversion of the group
+number into a pattern offset does not happen until the pattern has been
+completely compiled. This does mean that detection of all infinitely looping
+recursions is postponed till match time. In the past, some easy ones were
+detected at compile time. This re-writing was done in response to yet another
+bug found by the LLVM fuzzer.
+
+31. A test for a back reference to a non-existent group was missing for items
+such as \987. This caused incorrect code to be compiled. This issue was found
+by Karl Skomski with a custom LLVM fuzzer.
+
+32. Error messages for syntax errors following \g and \k were giving inaccurate
+offsets in the pattern.
+
+33. Improve the performance of starting single character repetitions in JIT.
+
+34. (*LIMIT_MATCH=) now gives an error instead of setting the value to 0.
+
+35. Error messages for syntax errors in *LIMIT_MATCH and *LIMIT_RECURSION now
+give the right offset instead of zero.
+
+36. The JIT compiler should not check repeats after a {0,1} repeat byte code.
+This issue was found by Karl Skomski with a custom LLVM fuzzer.
+
+37. The JIT compiler should restore the control chain for empty possessive
+repeats. This issue was found by Karl Skomski with a custom LLVM fuzzer.
+
+38. A bug which was introduced by the single character repetition optimization
+was fixed.
+
+39. Match limit check added to recursion. This issue was found by Karl Skomski
+with a custom LLVM fuzzer.
+
+40. Arrange for the UTF check in pcre2_match() and pcre2_dfa_match() to look
+only at the part of the subject that is relevant when the starting offset is
+non-zero.
+
+41. Improve first character match in JIT with SSE2 on x86.
+
+42. Fix two assertion fails in JIT. These issues were found by Karl Skomski
+with a custom LLVM fuzzer.
+
+43. Correct the setting of CMAKE_C_FLAGS in CMakeLists.txt (patch from Roy Ivy
+III).
+
+44. Fix bug in RunTest.bat for new test 14, and adjust the script for the added
+test (there are now 20 in total).
+
+45. Fixed a corner case of range optimization in JIT.
+
+46. Add the ${*MARK} facility to pcre2_substitute().
+
+47. Modifier lists in pcre2test were splitting at spaces without the required
+commas.
+
+48. Implemented PCRE2_ALT_VERBNAMES.
+
+49. Fixed two issues in JIT. These were found by Karl Skomski with a custom
+LLVM fuzzer.
+
+50. The pcre2test program has been extended by adding the #newline_default
+command. This has made it possible to run the standard tests when PCRE2 is
+compiled with either CR or CRLF as the default newline convention. As part of
+this work, the new command was added to several test files and the testing
+scripts were modified. The pcre2grep tests can now also be run when there is no
+LF in the default newline convention.
+
+51. The RunTest script has been modified so that, when JIT is used and valgrind
+is specified, a valgrind suppressions file is set up to ignore "Invalid read of
+size 16" errors because these are false positives when the hardware supports
+the SSE2 instruction set.
+
+52. It is now possible to have comment lines amid the subject strings in
+pcre2test (and perltest.sh) input.
+
+53. Implemented PCRE2_USE_OFFSET_LIMIT and pcre2_set_offset_limit().
+
+54. Add the null_context modifier to pcre2test so that calling pcre2_compile()
+and the matching functions with NULL contexts can be tested.
+
+55. Implemented PCRE2_SUBSTITUTE_EXTENDED.
+
+56. In a character class such as [\W\p{Any}] where both a negative-type escape
+("not a word character") and a property escape were present, the property
+escape was being ignored.
+
+57. Fixed integer overflow for patterns whose minimum matching length is very,
+very large.
+
+58. Implemented --never-backslash-C.
+
+59. Change 55 above introduced a bug by which certain patterns provoked the
+erroneous error "\ at end of pattern".
+
+60. The special sequences [[:<:]] and [[:>:]] gave rise to incorrect compiling
+errors or other strange effects if compiled in UCP mode. Found with libFuzzer
+and AddressSanitizer.
+
+61. Whitespace at the end of a pcre2test pattern line caused a spurious error
+message if there were only single-character modifiers. It should be ignored.
+
+62. The use of PCRE2_NO_AUTO_CAPTURE could cause incorrect compilation results
+or segmentation errors for some patterns. Found with libFuzzer and
+AddressSanitizer.
+
+63. Very long names in (*MARK) or (*THEN) etc. items could provoke a buffer
+overflow.
+
+64. Improve error message for overly-complicated patterns.
+
+65. Implemented an optional replication feature for patterns in pcre2test, to
+make it easier to test long repetitive patterns. The tests for 63 above are
+converted to use the new feature.
+
+66. In the POSIX wrapper, if regerror() was given too small a buffer, it could
+misbehave.
+
+67. In pcre2_substitute() in UTF mode, the UTF validity check on the
+replacement string was happening before the length setting when the replacement
+string was zero-terminated.
+
+68. In pcre2_substitute() in UTF mode, PCRE2_NO_UTF_CHECK can be set for the
+second and subsequent calls to pcre2_match().
+
+69. There was no check for integer overflow for a replacement group number in
+pcre2_substitute(). An added check for a number greater than the largest group
+number in the pattern means this is not now needed.
+
+70. The PCRE2-specific VERSION condition didn't work correctly if only one
+digit was given after the decimal point, or if more than two digits were given.
+It now works with one or two digits, and gives a compile time error if more are
+given.
+
+71. In pcre2_substitute() there was the possibility of reading one code unit
+beyond the end of the replacement string.
+
+72. The code for checking a subject's UTF-32 validity for a pattern with a
+lookbehind involved an out-of-bounds pointer, which could potentially cause
+trouble in some environments.
+
+73. The maximum lookbehind length was incorrectly calculated for patterns such
+as /(?<=(a)(?-1))x/ which have a recursion within a backreference.
+
+74. Give an error if a lookbehind assertion is longer than 65535 code units.
+
+75. Give an error in pcre2_substitute() if a match ends before it starts (as a
+result of the use of \K).
+
+76. Check the length of subpattern names and the names in (*MARK:xx) etc.
+dynamically to avoid the possibility of integer overflow.
+
+77. Implement pcre2_set_max_pattern_length() so that programs can restrict the
+size of patterns that they are prepared to handle.
+
+78. (*NO_AUTO_POSSESS) was not working.
+
+79. Adding group information caching improves the speed of compiling when
+checking whether a group has a fixed length and/or could match an empty string,
+especially when recursion or subroutine calls are involved. However, this
+cannot be used when (?| is present in the pattern because the same number may
+be used for groups of different sizes. To catch runaway patterns in this
+situation, counts have been introduced to the functions that scan for empty
+branches or compute fixed lengths.
+
+80. Allow for the possibility of the size of the nest_save structure not being
+a factor of the size of the compiling workspace (it currently is).
+
+81. Check for integer overflow in minimum length calculation and cap it at
+65535.
+
+82. Small optimizations in code for finding the minimum matching length.
+
+83. Lock out configuring for EBCDIC with non-8-bit libraries.
+
+84. Test for error code <= 0 in regerror().
+
+85. Check for too many replacements (more than INT_MAX) in pcre2_substitute().
+
+86. Avoid the possibility of computing with an out-of-bounds pointer (though
+not dereferencing it) while handling lookbehind assertions.
+
+87. Failure to get memory for the match data in regcomp() is now given as a
+regcomp() error instead of waiting for regexec() to pick it up.
+
+88. In pcre2_substitute(), ensure that CRLF is not split when it is a valid
+newline sequence.
+
+89. Paranoid check in regcomp() for bad error code from pcre2_compile().
+
+90. Run test 8 (internal offsets and code sizes) for link sizes 3 and 4 as well
+as for link size 2.
+
+91. Document that JIT has a limit on pattern size, and give more information
+about JIT compile failures in pcre2test.
+
+92. Implement PCRE2_INFO_HASBACKSLASHC.
+
+93. Re-arrange valgrind support code in pcre2test to avoid spurious reports
+with JIT (possibly caused by SSE2?).
+
+94. Support offset_limit in JIT.
+
+95. A sequence such as [[:punct:]b] that is, a POSIX character class followed
+by a single ASCII character in a class item, was incorrectly compiled in UCP
+mode. The POSIX class got lost, but only if the single character followed it.
+
+96. [:punct:] in UCP mode was matching some characters in the range 128-255
+that should not have been matched.
+
+97. If [:^ascii:] or [:^xdigit:] are present in a non-negated class, all
+characters with code points greater than 255 are in the class. When a Unicode
+property was also in the class (if PCRE2_UCP is set, escapes such as \w are
+turned into Unicode properties), wide characters were not correctly handled,
+and could fail to match.
+
+98. In pcre2test, make the "startoffset" modifier a synonym of "offset",
+because it sets the "startoffset" parameter for pcre2_match().
+
+99. If PCRE2_AUTO_CALLOUT was set on a pattern that had a (?# comment between
+an item and its qualifier (for example, A(?#comment)?B) pcre2_compile()
+misbehaved. This bug was found by the LLVM fuzzer.
+
+100. The error for an invalid UTF pattern string always gave the code unit
+offset as zero instead of where the invalidity was found.
+
+101. Further to 97 above, negated classes such as [^[:^ascii:]\d] were also not
+working correctly in UCP mode.
+
+102. Similar to 99 above, if an isolated \E was present between an item and its
+qualifier when PCRE2_AUTO_CALLOUT was set, pcre2_compile() misbehaved. This bug
+was found by the LLVM fuzzer.
+
+103. The POSIX wrapper function regexec() crashed if the option REG_STARTEND
+was set when the pmatch argument was NULL. It now returns REG_INVARG.
+
+104. Allow for up to 32-bit numbers in the ordin() function in pcre2grep.
+
+105. An empty \Q\E sequence between an item and its qualifier caused
+pcre2_compile() to misbehave when auto callouts were enabled. This bug
+was found by the LLVM fuzzer.
+
+106. If both PCRE2_ALT_VERBNAMES and PCRE2_EXTENDED were set, and a (*MARK) or
+other verb "name" ended with whitespace immediately before the closing
+parenthesis, pcre2_compile() misbehaved. Example: /(*:abc )/, but only when
+both those options were set.
+
+107. In a number of places pcre2_compile() was not handling NULL characters
+correctly, and pcre2test with the "bincode" modifier was not always correctly
+displaying fields containing NULLS:
+
+ (a) Within /x extended #-comments
+ (b) Within the "name" part of (*MARK) and other *verbs
+ (c) Within the text argument of a callout
+
+108. If a pattern that was compiled with PCRE2_EXTENDED started with white
+space or a #-type comment that was followed by (?-x), which turns off
+PCRE2_EXTENDED, and there was no subsequent (?x) to turn it on again,
+pcre2_compile() assumed that (?-x) applied to the whole pattern and
+consequently mis-compiled it. This bug was found by the LLVM fuzzer. The fix
+for this bug means that a setting of any of the (?imsxJU) options at the start
+of a pattern is no longer transferred to the options that are returned by
+PCRE2_INFO_ALLOPTIONS. In fact, this was an anachronism that should have
+changed when the effects of those options were all moved to compile time.
+
+109. An escaped closing parenthesis in the "name" part of a (*verb) when
+PCRE2_ALT_VERBNAMES was set caused pcre2_compile() to malfunction. This bug
+was found by the LLVM fuzzer.
+
+110. Implemented PCRE2_SUBSTITUTE_UNSET_EMPTY, and updated pcre2test to make it
+possible to test it.
+
+111. "Harden" pcre2test against ridiculously large values in modifiers and
+command line arguments.
+
+112. Implemented PCRE2_SUBSTITUTE_UNKNOWN_UNSET and PCRE2_SUBSTITUTE_OVERFLOW_
+LENGTH.
+
+113. Fix printing of *MARK names that contain binary zeroes in pcre2test.
+
+
+Version 10.20 30-June-2015
+--------------------------
+
+1. Callouts with string arguments have been added.
+
+2. Assertion code generator in JIT has been optimized.
+
+3. The invalid pattern (?(?C) has a missing assertion condition at the end. The
+pcre2_compile() function read past the end of the input before diagnosing an
+error. This bug was discovered by the LLVM fuzzer.
+
+4. Implemented pcre2_callout_enumerate().
+
+5. Fix JIT compilation of conditional blocks whose assertion is converted to
+(*FAIL). E.g: /(?(?!))/.
+
+6. The pattern /(?(?!)^)/ caused references to random memory. This bug was
+discovered by the LLVM fuzzer.
+
+7. The assertion (?!) is optimized to (*FAIL). This was not handled correctly
+when this assertion was used as a condition, for example (?(?!)a|b). In
+pcre2_match() it worked by luck; in pcre2_dfa_match() it gave an incorrect
+error about an unsupported item.
+
+8. For some types of pattern, for example /Z*(|d*){216}/, the auto-
+possessification code could take exponential time to complete. A recursion
+depth limit of 1000 has been imposed to limit the resources used by this
+optimization. This infelicity was discovered by the LLVM fuzzer.
+
+9. A pattern such as /(*UTF)[\S\V\H]/, which contains a negated special class
+such as \S in non-UCP mode, explicit wide characters (> 255) can be ignored
+because \S ensures they are all in the class. The code for doing this was
+interacting badly with the code for computing the amount of space needed to
+compile the pattern, leading to a buffer overflow. This bug was discovered by
+the LLVM fuzzer.
+
+10. A pattern such as /((?2)+)((?1))/ which has mutual recursion nested inside
+other kinds of group caused stack overflow at compile time. This bug was
+discovered by the LLVM fuzzer.
+
+11. A pattern such as /(?1)(?#?'){8}(a)/ which had a parenthesized comment
+between a subroutine call and its quantifier was incorrectly compiled, leading
+to buffer overflow or other errors. This bug was discovered by the LLVM fuzzer.
+
+12. The illegal pattern /(?(?.*!.*)?)/ was not being diagnosed as missing an
+assertion after (?(. The code was failing to check the character after (?(?<
+for the ! or = that would indicate a lookbehind assertion. This bug was
+discovered by the LLVM fuzzer.
+
+13. A pattern such as /X((?2)()*+){2}+/ which has a possessive quantifier with
+a fixed maximum following a group that contains a subroutine reference was
+incorrectly compiled and could trigger buffer overflow. This bug was discovered
+by the LLVM fuzzer.
+
+14. Negative relative recursive references such as (?-7) to non-existent
+subpatterns were not being diagnosed and could lead to unpredictable behaviour.
+This bug was discovered by the LLVM fuzzer.
+
+15. The bug fixed in 14 was due to an integer variable that was unsigned when
+it should have been signed. Some other "int" variables, having been checked,
+have either been changed to uint32_t or commented as "must be signed".
+
+16. A mutual recursion within a lookbehind assertion such as (?<=((?2))((?1)))
+caused a stack overflow instead of the diagnosis of a non-fixed length
+lookbehind assertion. This bug was discovered by the LLVM fuzzer.
+
+17. The use of \K in a positive lookbehind assertion in a non-anchored pattern
+(e.g. /(?<=\Ka)/) could make pcre2grep loop.
+
+18. There was a similar problem to 17 in pcre2test for global matches, though
+the code there did catch the loop.
+
+19. If a greedy quantified \X was preceded by \C in UTF mode (e.g. \C\X*),
+and a subsequent item in the pattern caused a non-match, backtracking over the
+repeated \X did not stop, but carried on past the start of the subject, causing
+reference to random memory and/or a segfault. There were also some other cases
+where backtracking after \C could crash. This set of bugs was discovered by the
+LLVM fuzzer.
+
+20. The function for finding the minimum length of a matching string could take
+a very long time if mutual recursion was present many times in a pattern, for
+example, /((?2){73}(?2))((?1))/. A better mutual recursion detection method has
+been implemented. This infelicity was discovered by the LLVM fuzzer.
+
+21. Implemented PCRE2_NEVER_BACKSLASH_C.
+
+22. The feature for string replication in pcre2test could read from freed
+memory if the replication required a buffer to be extended, and it was not
+working properly in 16-bit and 32-bit modes. This issue was discovered by a
+fuzzer: see http://lcamtuf.coredump.cx/afl/.
+
+23. Added the PCRE2_ALT_CIRCUMFLEX option.
+
+24. Adjust the treatment of \8 and \9 to be the same as the current Perl
+behaviour.
+
+25. Static linking against the PCRE2 library using the pkg-config module was
+failing on missing pthread symbols.
+
+26. If a group that contained a recursive back reference also contained a
+forward reference subroutine call followed by a non-forward-reference
+subroutine call, for example /.((?2)(?R)\1)()/, pcre2_compile() failed to
+compile correct code, leading to undefined behaviour or an internally detected
+error. This bug was discovered by the LLVM fuzzer.
+
+27. Quantification of certain items (e.g. atomic back references) could cause
+incorrect code to be compiled when recursive forward references were involved.
+For example, in this pattern: /(?1)()((((((\1++))\x85)+)|))/. This bug was
+discovered by the LLVM fuzzer.
+
+28. A repeated conditional group whose condition was a reference by name caused
+a buffer overflow if there was more than one group with the given name. This
+bug was discovered by the LLVM fuzzer.
+
+29. A recursive back reference by name within a group that had the same name as
+another group caused a buffer overflow. For example: /(?J)(?'d'(?'d'\g{d}))/.
+This bug was discovered by the LLVM fuzzer.
+
+30. A forward reference by name to a group whose number is the same as the
+current group, for example in this pattern: /(?|(\k'Pm')|(?'Pm'))/, caused a
+buffer overflow at compile time. This bug was discovered by the LLVM fuzzer.
+
+31. Fix -fsanitize=undefined warnings for left shifts of 1 by 31 (it treats 1
+as an int; fixed by writing it as 1u).
+
+32. Fix pcre2grep compile when -std=c99 is used with gcc, though it still gives
+a warning for "fileno" unless -std=gnu99 us used.
+
+33. A lookbehind assertion within a set of mutually recursive subpatterns could
+provoke a buffer overflow. This bug was discovered by the LLVM fuzzer.
+
+34. Give an error for an empty subpattern name such as (?'').
+
+35. Make pcre2test give an error if a pattern that follows #forbud_utf contains
+\P, \p, or \X.
+
+36. The way named subpatterns are handled has been refactored. There is now a
+pre-pass over the regex which does nothing other than identify named
+subpatterns and count the total captures. This means that information about
+named patterns is known before the rest of the compile. In particular, it means
+that forward references can be checked as they are encountered. Previously, the
+code for handling forward references was contorted and led to several errors in
+computing the memory requirements for some patterns, leading to buffer
+overflows.
+
+37. There was no check for integer overflow in subroutine calls such as (?123).
+
+38. The table entry for \l in EBCDIC environments was incorrect, leading to its
+being treated as a literal 'l' instead of causing an error.
+
+39. If a non-capturing group containing a conditional group that could match
+an empty string was repeated, it was not identified as matching an empty string
+itself. For example: /^(?:(?(1)x|)+)+$()/.
+
+40. In an EBCDIC environment, pcretest was mishandling the escape sequences
+\a and \e in test subject lines.
+
+41. In an EBCDIC environment, \a in a pattern was converted to the ASCII
+instead of the EBCDIC value.
+
+42. The handling of \c in an EBCDIC environment has been revised so that it is
+now compatible with the specification in Perl's perlebcdic page.
+
+43. Single character repetition in JIT has been improved. 20-30% speedup
+was achieved on certain patterns.
+
+44. The EBCDIC character 0x41 is a non-breaking space, equivalent to 0xa0 in
+ASCII/Unicode. This has now been added to the list of characters that are
+recognized as white space in EBCDIC.
+
+45. When PCRE2 was compiled without Unicode support, the use of \p and \P gave
+an error (correctly) when used outside a class, but did not give an error
+within a class.
+
+46. \h within a class was incorrectly compiled in EBCDIC environments.
+
+47. JIT should return with error when the compiled pattern requires
+more stack space than the maximum.
+
+48. Fixed a memory leak in pcre2grep when a locale is set.
+
+
+Version 10.10 06-March-2015
+---------------------------
+
+1. When a pattern is compiled, it remembers the highest back reference so that
+when matching, if the ovector is too small, extra memory can be obtained to
+use instead. A conditional subpattern whose condition is a check on a capture
+having happened, such as, for example in the pattern /^(?:(a)|b)(?(1)A|B)/, is
+another kind of back reference, but it was not setting the highest
+backreference number. This mattered only if pcre2_match() was called with an
+ovector that was too small to hold the capture, and there was no other kind of
+back reference (a situation which is probably quite rare). The effect of the
+bug was that the condition was always treated as FALSE when the capture could
+not be consulted, leading to a incorrect behaviour by pcre2_match(). This bug
+has been fixed.
+
+2. Functions for serialization and deserialization of sets of compiled patterns
+have been added.
+
+3. The value that is returned by PCRE2_INFO_SIZE has been corrected to remove
+excess code units at the end of the data block that may occasionally occur if
+the code for calculating the size over-estimates. This change stops the
+serialization code copying uninitialized data, to which valgrind objects. The
+documentation of PCRE2_INFO_SIZE was incorrect in stating that the size did not
+include the general overhead. This has been corrected.
+
+4. All code units in every slot in the table of group names are now set, again
+in order to avoid accessing uninitialized data when serializing.
+
+5. The (*NO_JIT) feature is implemented.
+
+6. If a bug that caused pcre2_compile() to use more memory than allocated was
+triggered when using valgrind, the code in (3) above passed a stupidly large
+value to valgrind. This caused a crash instead of an "internal error" return.
+
+7. A reference to a duplicated named group (either a back reference or a test
+for being set in a conditional) that occurred in a part of the pattern where
+PCRE2_DUPNAMES was not set caused the amount of memory needed for the pattern
+to be incorrectly calculated, leading to overwriting.
+
+8. A mutually recursive set of back references such as (\2)(\1) caused a
+segfault at compile time (while trying to find the minimum matching length).
+The infinite loop is now broken (with the minimum length unset, that is, zero).
+
+9. If an assertion that was used as a condition was quantified with a minimum
+of zero, matching went wrong. In particular, if the whole group had unlimited
+repetition and could match an empty string, a segfault was likely. The pattern
+(?(?=0)?)+ is an example that caused this. Perl allows assertions to be
+quantified, but not if they are being used as conditions, so the above pattern
+is faulted by Perl. PCRE2 has now been changed so that it also rejects such
+patterns.
+
+10. The error message for an invalid quantifier has been changed from "nothing
+to repeat" to "quantifier does not follow a repeatable item".
+
+11. If a bad UTF string is compiled with NO_UTF_CHECK, it may succeed, but
+scanning the compiled pattern in subsequent auto-possessification can get out
+of step and lead to an unknown opcode. Previously this could have caused an
+infinite loop. Now it generates an "internal error" error. This is a tidyup,
+not a bug fix; passing bad UTF with NO_UTF_CHECK is documented as having an
+undefined outcome.
+
+12. A UTF pattern containing a "not" match of a non-ASCII character and a
+subroutine reference could loop at compile time. Example: /[^\xff]((?1))/.
+
+13. The locale test (RunTest 3) has been upgraded. It now checks that a locale
+that is found in the output of "locale -a" can actually be set by pcre2test
+before it is accepted. Previously, in an environment where a locale was listed
+but would not set (an example does exist), the test would "pass" without
+actually doing anything. Also the fr_CA locale has been added to the list of
+locales that can be used.
+
+14. Fixed a bug in pcre2_substitute(). If a replacement string ended in a
+capturing group number without parentheses, the last character was incorrectly
+literally included at the end of the replacement string.
+
+15. A possessive capturing group such as (a)*+ with a minimum repeat of zero
+failed to allow the zero-repeat case if pcre2_match() was called with an
+ovector too small to capture the group.
+
+16. Improved error message in pcre2test when setting the stack size (-S) fails.
+
+17. Fixed two bugs in CMakeLists.txt: (1) Some lines had got lost in the
+transfer from PCRE1, meaning that CMake configuration failed if "build tests"
+was selected. (2) The file src/pcre2_serialize.c had not been added to the list
+of PCRE2 sources, which caused a failure to build pcre2test.
+
+18. Fixed typo in pcre2_serialize.c (DECL instead of DEFN) that causes problems
+only on Windows.
+
+19. Use binary input when reading back saved serialized patterns in pcre2test.
+
+20. Added RunTest.bat for running the tests under Windows.
+
+21. "make distclean" was not removing config.h, a file that may be created for
+use with CMake.
+
+22. A pattern such as "((?2){0,1999}())?", which has a group containing a
+forward reference repeated a large (but limited) number of times within a
+repeated outer group that has a zero minimum quantifier, caused incorrect code
+to be compiled, leading to the error "internal error: previously-checked
+referenced subpattern not found" when an incorrect memory address was read.
+This bug was reported as "heap overflow", discovered by Kai Lu of Fortinet's
+FortiGuard Labs. (Added 24-March-2015: CVE-2015-2325 was given to this.)
+
+23. A pattern such as "((?+1)(\1))/" containing a forward reference subroutine
+call within a group that also contained a recursive back reference caused
+incorrect code to be compiled. This bug was reported as "heap overflow",
+discovered by Kai Lu of Fortinet's FortiGuard Labs. (Added 24-March-2015:
+CVE-2015-2326 was given to this.)
+
+24. Computing the size of the JIT read-only data in advance has been a source
+of various issues, and new ones are still appear unfortunately. To fix
+existing and future issues, size computation is eliminated from the code,
+and replaced by on-demand memory allocation.
+
+25. A pattern such as /(?i)[A-`]/, where characters in the other case are
+adjacent to the end of the range, and the range contained characters with more
+than one other case, caused incorrect behaviour when compiled in UTF mode. In
+that example, the range a-j was left out of the class.
+
+
+Version 10.00 05-January-2015
+-----------------------------
+
+Version 10.00 is the first release of PCRE2, a revised API for the PCRE
+library. Changes prior to 10.00 are logged in the ChangeLog file for the old
+API, up to item 20 for release 8.36.
+
+The code of the library was heavily revised as part of the new API
+implementation. Details of each and every modification were not individually
+logged. In addition to the API changes, the following changes were made. They
+are either new functionality, or bug fixes and other noticeable changes of
+behaviour that were implemented after the code had been forked.
+
+1. Including Unicode support at build time is now enabled by default, but it
+can optionally be disabled. It is not enabled by default at run time (no
+change).
+
+2. The test program, now called pcre2test, was re-specified and almost
+completely re-written. Its input is not compatible with input for pcretest.
+
+3. Patterns may start with (*NOTEMPTY) or (*NOTEMPTY_ATSTART) to set the
+PCRE2_NOTEMPTY or PCRE2_NOTEMPTY_ATSTART options for every subject line that is
+matched by that pattern.
+
+4. For the benefit of those who use PCRE2 via some other application, that is,
+not writing the function calls themselves, it is possible to check the PCRE2
+version by matching a pattern such as /(?(VERSION>=10)yes|no)/ against a
+string such as "yesno".
+
+5. There are case-equivalent Unicode characters whose encodings use different
+numbers of code units in UTF-8. U+023A and U+2C65 are one example. (It is
+theoretically possible for this to happen in UTF-16 too.) If a backreference to
+a group containing one of these characters was greedily repeated, and during
+the match a backtrack occurred, the subject might be backtracked by the wrong
+number of code units. For example, if /^(\x{23a})\1*(.)/ is matched caselessly
+(and in UTF-8 mode) against "\x{23a}\x{2c65}\x{2c65}\x{2c65}", group 2 should
+capture the final character, which is the three bytes E2, B1, and A5 in UTF-8.
+Incorrect backtracking meant that group 2 captured only the last two bytes.
+This bug has been fixed; the new code is slower, but it is used only when the
+strings matched by the repetition are not all the same length.
+
+6. A pattern such as /()a/ was not setting the "first character must be 'a'"
+information. This applied to any pattern with a group that matched no
+characters, for example: /(?:(?=.)|(? start of atomic group
+META_CIRCUMFLEX ^ metacharacter
+META_CLASS [ start of non-empty class
+META_CLASS_EMPTY [] empty class - only with PCRE2_ALLOW_EMPTY_CLASS
+META_CLASS_EMPTY_NOT [^] negative empty class - ditto
+META_CLASS_END ] end of non-empty class
+META_CLASS_NOT [^ start non-empty negative class
+META_COMMIT (*COMMIT) - no argument (see below for with argument)
+META_COND_ASSERT (?(?assertion)
+META_DOLLAR $ metacharacter
+META_DOT . metacharacter
+META_END End of pattern (this value is 0x80000000)
+META_FAIL (*FAIL)
+META_KET ) closing parenthesis
+META_LOOKAHEAD (?= start of lookahead
+META_LOOKAHEAD_NA (*napla: start of non-atomic lookahead
+META_LOOKAHEADNOT (?! start of negative lookahead
+META_NOCAPTURE (?: no capture parens
+META_PLUS +
+META_PLUS_PLUS ++
+META_PLUS_QUERY +?
+META_PRUNE (*PRUNE) - no argument (see below for with argument)
+META_QUERY ?
+META_QUERY_PLUS ?+
+META_QUERY_QUERY ??
+META_RANGE_ESCAPED hyphen in class range with at least one escape
+META_RANGE_LITERAL hyphen in class range defined literally
+META_SKIP (*SKIP) - no argument (see below for with argument)
+META_THEN (*THEN) - no argument (see below for with argument)
+META_ECLASS_AND && (or &) in an extended character class
+META_ECLASS_OR || (or |, +) in an extended character class
+META_ECLASS_SUB -- (or -) in an extended character class
+META_ECLASS_XOR ~~ (or ^) in an extended character class
+META_ECLASS_NOT ! in an extended character class
+
+The two RANGE values occur only in character classes. They are positioned
+between two literals that define the start and end of the range. In an EBCDIC
+environment it is necessary to know whether either of the range values was
+specified as an escape. In an ASCII/Unicode environment the distinction is not
+relevant.
+
+The following have data in the lower 16 bits, and may be followed by other data
+elements:
+
+META_ALT | alternation
+META_BACKREF back reference
+META_CAPTURE start of capturing group
+META_ESCAPE non-literal escape sequence
+META_RECURSE recursion call
+
+If the data for META_ALT is non-zero, it is inside a lookbehind, and the data
+is the maximum length of its branch (see META_LOOKBEHIND below for more
+detail).
+
+META_BACKREF, META_CAPTURE, and META_RECURSE have the capture group number as
+their data in the lower 16 bits of the element. META_RECURSE is followed by an
+offset, for use in error messages.
+
+META_BACKREF is followed by an offset if the back reference group number is 10
+or more. The offsets of the first occurrences of references to groups whose
+numbers are less than 10 are put in cb->small_ref_offset[] (only the first
+occurrence is useful). On 64-bit systems this avoids using more than two parsed
+pattern elements for items such as \3. The offset is used when an error occurs
+because the reference is to a non-existent group.
+
+META_ESCAPE is used for escapes such as \d that match a character. It has an
+ESC_xxx value as its data. For ESC_P and ESC_p, the next element contains the
+16-bit type and data property values, packed together. Escape sequences such as
+\g and \k are turned into other items like META_RECURSE or META_BACKREF and
+their ESC_xxx values never occur with META_ESCAPE.
+
+The following have one data item that follows in the next vector element:
+
+META_BIGVALUE Next is a literal >= META_END
+META_POSIX POSIX class item (data identifies the class)
+META_POSIX_NEG negative POSIX class item (ditto)
+
+The following are followed by a length element, then a number of character code
+values (which should match with the length):
+
+META_MARK (*MARK:xxxx)
+META_COMMIT_ARG (*COMMIT:xxxx)
+META_PRUNE_ARG (*PRUNE:xxx)
+META_SKIP_ARG (*SKIP:xxxx)
+META_THEN_ARG (*THEN:xxxx)
+
+The following are followed by a length element, then an offset in the pattern
+that identifies the name:
+
+META_COND_NAME (?() or (?('name') or (?(name)
+META_COND_RNAME (?(R&name)
+META_COND_RNUMBER (?(Rdigits)
+META_RECURSE_BYNAME (?&name)
+META_BACKREF_BYNAME \k'name' or \k or \k{name} or \g{name}
+META_SCS_NAME (*scs:()...)
+
+META_COND_RNUMBER is used for names that start with R and continue with digits,
+because this is an ambiguous case. It could be a back reference to a group with
+that name, or it could be a recursion test on a numbered group.
+
+These are followed by an offset, for use in error messages, then a number:
+
+META_COND_NUMBER (?([+-]digits)
+META_SCS_NUMBER (*scs:(digits)...)
+
+The following is followed just by an offset, for use in error messages:
+
+META_COND_DEFINE (?(DEFINE)
+
+The following are at first also followed just by an offset for use in error
+messages. After the lengths of the branches of a lookbehind group have been
+checked the error offset is no longer needed. The lower 16 bits of the main
+word are now set to the maximum length of the first branch of the lookbehind
+group, and the second word is set to the minimum matching length for a
+variable-length lookbehind group, or to LOOKBEHIND_MAX for a group whose
+branches are all of fixed length. These values are used when generating
+OP_REVERSE or OP_VREVERSE for the first branch. The miminum value is also used
+for any subsequent branches because there is only room for one value (the
+branch maximum length) in a META_ALT item.
+
+META_LOOKBEHIND (?<= start of lookbehind
+META_LOOKBEHIND_NA (*naplb: start of non-atomic lookbehind
+META_LOOKBEHINDNOT (?' and 1 for '>=';
+the next two are the major and minor numbers:
+
+META_COND_VERSION (?(VERSIONx.y)
+
+Callouts are converted into one of two items:
+
+META_CALLOUT_NUMBER (?C with numerical argument
+META_CALLOUT_STRING (?C with string argument
+
+In both cases, the next two elements contain the offset and length of the next
+item in the pattern. Then there is either one callout number, or a length and
+an offset for the string argument. The length includes both delimiters.
+
+
+Traditional matching function
+-----------------------------
+
+The "traditional", and original, matching function is called pcre2_match(), and
+it implements an NFA algorithm, similar to the original Henry Spencer algorithm
+and the way that Perl works. This is not surprising, since it is intended to be
+as compatible with Perl as possible. This is the function most users of PCRE2
+will use most of the time. If PCRE2 is compiled with just-in-time (JIT)
+support, and studying a compiled pattern with JIT is successful, the JIT code
+is run instead of the normal pcre2_match() code, but the result is the same.
+
+The interpreter used to implement backtracking by means of recursive function
+calls, but this gave rise to regular complaints when patterns with large search
+trees ran out of stack. There was for a while a fudge that used the heap
+instead, but this was inefficient and slow. In 2017 I re-wrote pcre2_match() as
+a single, non-recursive function that implements backtracking via a vector of
+"frames" on the heap, each frame representing a backtracking point. As well as
+standard information such as the position in the pattern and position in the
+subject, each frame has a number of unassigned variables that can be used
+locally to preserve values at a backtracking point. C macros are used
+extensively to implement all of this.
+
+
+Supplementary matching function
+-------------------------------
+
+There is a supplementary matching function called pcre2_dfa_match() that
+implements a DFA matching algorithm that searches simultaneously for all
+possible matches that start at one point in the subject string. (Going back to
+my roots: see Historical Note 1 above.) This function intreprets the same
+compiled pattern data as pcre2_match(); however, not all the facilities are
+available, and those that are do not always work in quite the same way. In
+particular, capturing parentheses and backreferences are not supported. See the
+user documentation for details.
+
+The algorithm that is used for pcre2_dfa_match() is not a traditional FSM,
+because it may have a number of states active at one time. More work would be
+needed at compile time to produce a traditional FSM where only one state is
+ever active at once. I believe some other regex matchers work this way. JIT
+support is not available for this kind of matching.
+
+
+Changeable options
+------------------
+
+The /i, /m, or /s options (PCRE2_CASELESS, PCRE2_MULTILINE, PCRE2_DOTALL) and
+some others may be changed in the middle of patterns by items such as (?i).
+Their processing is handled entirely at compile time by generating different
+opcodes for the different settings. Some options are copied into the opcode's
+data, for opcodes such as OP_REFI which depends on the (?r)
+(PCRE2_EXTRA_CASELESS_RESTRICT) option. The runtime functions do not need to
+keep track of an option's state.
+
+PCRE2_DUPNAMES, PCRE2_EXTENDED, PCRE2_EXTENDED_MORE, and PCRE2_NO_AUTO_CAPTURE
+are tracked and processed during the parsing pre-pass. The others are handled
+from META_OPTIONS items during the main compile phase.
+
+
+Format of compiled patterns
+---------------------------
+
+The compiled form of a pattern is a vector of unsigned code units (bytes in
+8-bit mode, shorts in 16-bit mode, 32-bit words in 32-bit mode), containing
+items of variable length. The first code unit in an item contains an opcode,
+and the length of the item is either implicit in the opcode or contained in the
+data that follows it.
+
+In many cases listed below, LINK_SIZE data values are specified for offsets
+within the compiled pattern. LINK_SIZE always specifies a number of bytes. The
+default value for LINK_SIZE is 2, except for the 32-bit library, where it can
+only be 4. The 8-bit library can be compiled to use 3-byte or 4-byte values,
+and the 16-bit library can be compiled to use 4-byte values, though this
+impairs performance. Specifying a LINK_SIZE larger than 2 for these libraries
+is necessary only when patterns whose compiled length is greater than 65535
+code units are going to be processed. When a LINK_SIZE value uses more than one
+code unit, the most significant unit is first.
+
+In this description, we assume the "normal" compilation options. Data values
+that are counts (e.g. quantifiers) are always two bytes long in 8-bit mode
+(most significant byte first), and one code unit in 16-bit and 32-bit modes.
+
+
+Opcodes with no following data
+------------------------------
+
+These items are all just one code unit long:
+
+ OP_END end of pattern
+ OP_ANY match any one character other than newline
+ OP_ALLANY match any one character, including newline
+ OP_ANYBYTE match any single code unit, even in UTF-8/16 mode
+ OP_SOD match start of data: \A
+ OP_SOM, start of match (subject + offset): \G
+ OP_SET_SOM, set start of match (\K)
+ OP_CIRC ^ (start of data)
+ OP_CIRCM ^ multiline mode (start of data or after newline)
+ OP_NOT_WORD_BOUNDARY \W
+ OP_WORD_BOUNDARY \w
+ OP_NOT_DIGIT \D
+ OP_DIGIT \d
+ OP_NOT_HSPACE \H
+ OP_HSPACE \h
+ OP_NOT_WHITESPACE \S
+ OP_WHITESPACE \s
+ OP_NOT_VSPACE \V
+ OP_VSPACE \v
+ OP_NOT_WORDCHAR \W
+ OP_WORDCHAR \w
+ OP_EODN match end of data or newline at end: \Z
+ OP_EOD match end of data: \z
+ OP_DOLL $ (end of data, or before final newline)
+ OP_DOLLM $ multiline mode (end of data or before newline)
+ OP_EXTUNI match an extended Unicode grapheme cluster
+ OP_ANYNL match any Unicode newline sequence
+
+ OP_ASSERT_ACCEPT )
+ OP_ACCEPT ) These are Perl 5.10's "backtracking control
+ OP_COMMIT ) verbs". If OP_ACCEPT is inside capturing
+ OP_FAIL ) parentheses, it may be preceded by one or more
+ OP_PRUNE ) OP_CLOSE, each followed by a number that
+ OP_SKIP ) indicates which parentheses must be closed.
+ OP_THEN )
+
+OP_ASSERT_ACCEPT is used when (*ACCEPT) is encountered within an assertion.
+This ends the assertion, not the entire pattern match. The assertion (?!) is
+always optimized to OP_FAIL.
+
+OP_ALLANY is used for '.' when PCRE2_DOTALL is set. It is also used for \C in
+non-UTF modes and in UTF-32 mode (since one code unit still equals one
+character). Another use is for [^] when empty classes are permitted
+(PCRE2_ALLOW_EMPTY_CLASS is set).
+
+
+Backtracking control verbs
+--------------------------
+
+Verbs with no arguments generate opcodes with no following data (as listed
+in the section above).
+
+(*MARK:NAME) generates OP_MARK followed by the mark name, preceded by a
+length in one code unit, and followed by a binary zero. The name length is
+limited by the size of the code unit.
+
+(*ACCEPT:NAME) and (*FAIL:NAME) are compiled as (*MARK:NAME)(*ACCEPT) and
+(*MARK:NAME)(*FAIL) respectively.
+
+For (*COMMIT:NAME), (*PRUNE:NAME), (*SKIP:NAME), and (*THEN:NAME), the opcodes
+OP_COMMIT_ARG, OP_PRUNE_ARG, OP_SKIP_ARG, and OP_THEN_ARG are used, with the
+name following in the same format as for OP_MARK.
+
+
+Matching literal characters
+---------------------------
+
+The OP_CHAR opcode is followed by a single character that is to be matched
+casefully. For caseless matching of characters that have at most two
+case-equivalent code points, OP_CHARI is used. In UTF-8 or UTF-16 modes, the
+character may be more than one code unit long. In UTF-32 mode, characters are
+always exactly one code unit long.
+
+If there is only one character in a character class, OP_CHAR or OP_CHARI is
+used for a positive class, and OP_NOT or OP_NOTI for a negative one (that is,
+for something like [^a]).
+
+Caseless matching (positive or negative) of characters that have more than two
+case-equivalent code points (which is possible only in UTF mode) is handled by
+compiling a Unicode property item (see below), with the pseudo-property
+PT_CLIST. The value of this property is an offset in a vector called
+"ucd_caseless_sets" which identifies the start of a short list of case
+equivalent characters, terminated by the value NOTACHAR (0xffffffff).
+
+
+Repeating single characters
+---------------------------
+
+The common repeats (*, +, ?), when applied to a single character, use the
+following opcodes, which come in caseful and caseless versions:
+
+ Caseful Caseless
+ OP_STAR OP_STARI
+ OP_MINSTAR OP_MINSTARI
+ OP_POSSTAR OP_POSSTARI
+ OP_PLUS OP_PLUSI
+ OP_MINPLUS OP_MINPLUSI
+ OP_POSPLUS OP_POSPLUSI
+ OP_QUERY OP_QUERYI
+ OP_MINQUERY OP_MINQUERYI
+ OP_POSQUERY OP_POSQUERYI
+
+Each opcode is followed by the character that is to be repeated. In ASCII or
+UTF-32 modes, these are two-code-unit items; in UTF-8 or UTF-16 modes, the
+length is variable. Those with "MIN" in their names are the minimizing
+versions. Those with "POS" in their names are possessive versions. Other kinds
+of repeat make use of these opcodes:
+
+ Caseful Caseless
+ OP_UPTO OP_UPTOI
+ OP_MINUPTO OP_MINUPTOI
+ OP_POSUPTO OP_POSUPTOI
+ OP_EXACT OP_EXACTI
+
+Each of these is followed by a count and then the repeated character. The count
+is two bytes long in 8-bit mode (most significant byte first), or one code unit
+in 16-bit and 32-bit modes.
+
+OP_UPTO matches from 0 to the given number. A repeat with a non-zero minimum
+and a fixed maximum is coded as an OP_EXACT followed by an OP_UPTO (or
+OP_MINUPTO or OPT_POSUPTO).
+
+Another set of matching repeating opcodes (called OP_NOTSTAR, OP_NOTSTARI,
+etc.) are used for repeated, negated, single-character classes such as [^a]*.
+The normal single-character opcodes (OP_STAR, etc.) are used for repeated
+positive single-character classes.
+
+
+Repeating character types
+-------------------------
+
+Repeats of things like \d are done exactly as for single characters, except
+that instead of a character, the opcode for the type (e.g. OP_DIGIT) is stored
+in the next code unit. The opcodes are:
+
+ OP_TYPESTAR
+ OP_TYPEMINSTAR
+ OP_TYPEPOSSTAR
+ OP_TYPEPLUS
+ OP_TYPEMINPLUS
+ OP_TYPEPOSPLUS
+ OP_TYPEQUERY
+ OP_TYPEMINQUERY
+ OP_TYPEPOSQUERY
+ OP_TYPEUPTO
+ OP_TYPEMINUPTO
+ OP_TYPEPOSUPTO
+ OP_TYPEEXACT
+
+
+Match by Unicode property
+-------------------------
+
+OP_PROP and OP_NOTPROP are used for positive and negative matches of a
+character by testing its Unicode property (the \p and \P escape sequences).
+Each is followed by two code units that encode the desired property as a type
+and a value. The types are a set of #defines of the form PT_xxx, and the values
+are enumerations of the form ucp_xx, defined in the pcre2_ucp.h source file.
+The value is relevant only for PT_GC (General Category), PT_PC (Particular
+Category), PT_SC (Script), PT_BIDICL (Bidi Class), PT_BOOL (Boolean property),
+and the pseudo-property PT_CLIST, which is used to identify a list of
+case-equivalent characters when there are three or more (see above).
+
+Repeats of these items use the OP_TYPESTAR etc. set of opcodes, followed by
+three code units: OP_PROP or OP_NOTPROP, and then the desired property type and
+value.
+
+
+Character classes
+-----------------
+
+If there is only one character in a class, OP_CHAR or OP_CHARI is used for a
+positive class, and OP_NOT or OP_NOTI for a negative one (that is, for
+something like [^a]), except when caselessly matching a character that has more
+than two case-equivalent code points (which can happen only in UTF mode). In
+this case a Unicode property item is used, as described above in "Matching
+literal characters".
+
+A set of repeating opcodes (called OP_NOTSTAR etc.) are used for repeated,
+negated, single-character classes. The normal single-character opcodes
+(OP_STAR, etc.) are used for repeated positive single-character classes.
+
+When there is more than one character in a class, and all the code points are
+less than 256, OP_CLASS is used for a positive class, and OP_NCLASS for a
+negative one. In either case, the opcode is followed by a 32-byte (16-short,
+8-word) bit map containing a 1 bit for every character that is acceptable. The
+bits are counted from the least significant end of each unit. In caseless mode,
+bits for both cases are set.
+
+The reason for having both OP_CLASS and OP_NCLASS is so that, in UTF-8 and
+16-bit and 32-bit modes, subject characters with values greater than 255 can be
+handled correctly. For OP_CLASS they do not match, whereas for OP_NCLASS they
+do.
+
+For classes containing characters with values greater than 255 or that contain
+\p or \P, OP_XCLASS is used. It optionally uses a bit map if any acceptable
+code points are less than 256. After the bit map, the properties of the
+character class are listed, if they are present. The items in the list
+follows the declaration order of the pattern string. The property list
+is followed by single characters and/or character ranges, if they are
+present. The characters/ranges are sorted in ascending order, and at
+least one non-matching character must be present between any two of
+them. In caseless mode, all equivalent characters are explicitly listed.
+
+OP_XCLASS is followed by a LINK_SIZE value containing the total length of the
+opcode and its data. This is followed by a code unit containing flag bits:
+XCL_NOT indicates that this is a negative class, and XCL_MAP indicates that a
+bit map is present. There follows the bit map, if XCL_MAP is set, and then a
+sequence of items coded as follows:
+
+ XCL_END marks the end of the list
+ XCL_SINGLE one character follows
+ XCL_RANGE two characters follow
+ XCL_PROP a Unicode property (type, value) follows
+ XCL_NOTPROP a Unicode property (type, value) follows
+
+If a range starts with a code point less than 256 and ends with one greater
+than 255, it is split into two ranges, with characters less than 256 being
+indicated in the bit map, and the rest with XCL_RANGE.
+
+When XCL_NOT is set, the bit map, if present, contains bits for characters that
+are allowed (exactly as for OP_NCLASS), but the list of items that follow it
+specifies characters and properties that are not allowed.
+
+The meaning of the bitmap indicated by XCL_MAP is that, if one is present, then
+it fully describes which code points < 256 match the class (without needing to
+invert the check according to XCL_NOT); the other items in the OP_XCLASS need
+not be consulted. However, if a bitmap is not present, then code points < 256
+may still match, so the other items in the OP_XCLASS must be consulted.
+
+For classes containing logical expressions, such as "[\p{Greek} && \p{Lu}]" for
+"uppercase Greek letters", OP_ECLASS is used. The expression is encoded as a a
+stack-based series of operands and operators, in Reverse Polish Notation. Like
+an OP_XCLASS, the OP_ECLASS is first followed by a LINK_SIZE value containing
+the total length of the opcode and its data. That is followed by a code unit
+containing flags: currently just ECL_MAP indicating that a bit map is present.
+There follows the bit map, if ECL_MAP is set. Finally, there is a sequence of
+items that are either an operand or operator. Each item starts with a single
+code unit containing its type:
+
+ ECL_AND AND; no additional data
+ ECL_OR OR; no additional data
+ ECL_XOR XOR; no additional data
+ ECL_NOT NOT; no additional data
+ ECL_XCLASS The additional data which follows ECL_XCLASS is the same as for
+ an OP_XCLASS, except that this data is preceded by ECL_XCLASS
+ rather than OP_XCLASS.
+ Because the OP_ECLASS has its own bitmap (if required), an
+ ECL_XCLASS should not contain a bitmap.
+
+Additionally, there are two intermediate values used during compilation, but
+these are folded away during generation of the opcode, and so never appear
+inside an OP_ECLASS at match time. They are:
+
+ ECL_ANY match all characters; no additional data
+ ECL_NONE match no characters; no additional data
+
+The meaning of the bitmap indicated by ECL_MAP is the same as XCL_MAP.
+If the bitmap is present, all codepoints < 256 are checked against the bitmap.
+
+
+Back references
+---------------
+
+OP_REF (caseful) or OP_REFI (caseless) is followed by a count containing the
+reference number when the reference is to a unique capturing group (either by
+number or by name). When named groups are used, there may be more than one
+group with the same name. In this case, a reference to such a group by name
+generates OP_DNREF or OP_DNREFI. These are followed by two counts: the index
+(not the byte offset) in the group name table of the first entry for the
+required name, followed by the number of groups with the same name. The
+matching code can then search for the first one that is set.
+
+OP_REFI and OP_DNREFI are further followed by an item containing any
+case-insensitivity flags.
+
+
+Repeating character classes and back references
+-----------------------------------------------
+
+Single-character classes are handled specially (see above). This section
+applies to other classes and also to back references. In both cases, the repeat
+information follows the base item. The matching code looks at the following
+opcode to see if it is one of these:
+
+ OP_CRSTAR
+ OP_CRMINSTAR
+ OP_CRPOSSTAR
+ OP_CRPLUS
+ OP_CRMINPLUS
+ OP_CRPOSPLUS
+ OP_CRQUERY
+ OP_CRMINQUERY
+ OP_CRPOSQUERY
+ OP_CRRANGE
+ OP_CRMINRANGE
+ OP_CRPOSRANGE
+
+All but the last three are single-code-unit items, with no data. The range
+opcodes are followed by the minimum and maximum repeat counts.
+
+
+Brackets and alternation
+------------------------
+
+A pair of non-capturing round brackets is wrapped round each expression at
+compile time, so alternation always happens in the context of brackets.
+
+[Note for North Americans: "bracket" to some English speakers, including
+myself, can be round, square, curly, or pointy. Hence this usage rather than
+"parentheses".]
+
+Non-capturing brackets use the opcode OP_BRA, capturing brackets use OP_CBRA. A
+bracket opcode is followed by a LINK_SIZE value which gives the offset to the
+next alternative OP_ALT or, if there aren't any branches, to the terminating
+opcode. Each OP_ALT is followed by a LINK_SIZE value giving the offset to the
+next one, or to the final opcode. For capturing brackets, the bracket number is
+a count that immediately follows the offset.
+
+There are several opcodes that mark the end of a subpattern group. OP_KET is
+used for subpatterns that do not repeat indefinitely, OP_KETRMIN and
+OP_KETRMAX are used for indefinite repetitions, minimally or maximally
+respectively, and OP_KETRPOS for possessive repetitions (see below for more
+details). All four are followed by a LINK_SIZE value giving (as a positive
+number) the offset back to the matching opening bracket opcode.
+
+If a subpattern is quantified such that it is permitted to match zero times, it
+is preceded by one of OP_BRAZERO, OP_BRAMINZERO, or OP_SKIPZERO. These are
+single-unit opcodes that tell the matcher that skipping the following
+subpattern entirely is a valid match. In the case of the first two, not
+skipping the pattern is also valid (greedy and non-greedy). The third is used
+when a pattern has the quantifier {0,0}. It cannot be entirely discarded,
+because it may be called as a subroutine from elsewhere in the pattern.
+
+A subpattern with an indefinite maximum repetition is replicated in the
+compiled data its minimum number of times (or once with OP_BRAZERO if the
+minimum is zero), with the final copy terminating with OP_KETRMIN or OP_KETRMAX
+as appropriate.
+
+A subpattern with a bounded maximum repetition is replicated in a nested
+fashion up to the maximum number of times, with OP_BRAZERO or OP_BRAMINZERO
+before each replication after the minimum, so that, for example, (abc){2,5} is
+compiled as (abc)(abc)((abc)((abc)(abc)?)?)?, except that each bracketed group
+has the same number.
+
+When a repeated subpattern has an unbounded upper limit, it is checked to see
+whether it could match an empty string. If this is the case, the opcode in the
+final replication is changed to OP_SBRA or OP_SCBRA. This tells the matcher
+that it needs to check for matching an empty string when it hits OP_KETRMIN or
+OP_KETRMAX, and if so, to break the loop.
+
+
+Possessive brackets
+-------------------
+
+When a repeated group (capturing or non-capturing) is marked as possessive by
+the "+" notation, e.g. (abc)++, different opcodes are used. Their names all
+have POS on the end, e.g. OP_BRAPOS instead of OP_BRA and OP_SCBRAPOS instead
+of OP_SCBRA. The end of such a group is marked by OP_KETRPOS. If the minimum
+repetition is zero, the group is preceded by OP_BRAPOSZERO.
+
+
+Once-only (atomic) groups
+-------------------------
+
+These are just like other subpatterns, but they start with the opcode OP_ONCE.
+The check for matching an empty string in an unbounded repeat is handled
+entirely at runtime, so there is just this one opcode for atomic groups.
+
+
+Assertions
+----------
+
+Forward assertions are also just like other subpatterns, but starting with one
+of the opcodes OP_ASSERT, OP_ASSERT_NA (non-atomic assertion), or
+OP_ASSERT_NOT.
+
+Backward assertions use the opcodes OP_ASSERTBACK, OP_ASSERTBACK_NA, and
+OP_ASSERTBACK_NOT. If all the branches of a backward assertion are of fixed
+length (not necessarily the same), the first opcode inside each branch is
+OP_REVERSE, followed by an IMM2_SIZE count of the number of characters to move
+back the pointer in the subject string, thus allowing each branch to have a
+different (but fixed) length.
+
+Variable-length backward assertions whose maximum matching length is limited
+are also supported. For such assertions, the first opcode inside each branch is
+OP_VREVERSE, followed by the minimum and maximum lengths for that branch,
+unless these happen to be equal, in which case OP_REVERSE is used. These
+IMM2_SIZE values occupy two code units each in 8-bit mode, and 1 code unit in
+16/32 bit modes.
+
+In ASCII or UTF-32 mode, the character counts in OP_REVERSE and OP_VREVERSE are
+also the number of code units, but in UTF-8/16 mode each character may occupy
+more than one code unit.
+
+The "scan substring" assertion compiles as OP_ASSERT_SCS. This opcode is
+followed by a list of arguments. Each argument is either an OP_CREF or
+OP_DNCREF byte code sequence. The details of these sequences are described
+in the next section.
+
+For example (*scs:(1,'NAME')...PATTERN...) is translated to:
+[OP_ASSERT_SCS] [OP_CREF] [OP_CREF] ...PATTERN... [OP_KET]
+
+If 'NAME' is a duplicated name, the second [OP_CREF] is [OP_DNCREF] instead.
+
+
+Conditional subpatterns
+-----------------------
+
+These are like other subpatterns, but they start with the opcode OP_COND, or
+OP_SCOND for one that might match an empty string in an unbounded repeat.
+
+If the condition is a back reference, this is stored at the start of the
+subpattern using the opcode OP_CREF followed by a count containing the
+reference number, provided that the reference is to a unique capturing group.
+If the reference was by name and there is more than one group with that name,
+OP_DNCREF is used instead. It is followed by two counts: the index in the group
+names table, and the number of groups with the same name. The allows the
+matcher to check if any group with the given name is set.
+
+If the condition is "in recursion" (coded as "(?(R)"), or "in recursion of
+group x" (coded as "(?(Rx)"), the group number is stored at the start of the
+subpattern using the opcode OP_RREF (with a value of RREF_ANY (0xffff) for "the
+whole pattern") or OP_DNRREF (with data as for OP_DNCREF).
+
+For a DEFINE condition, OP_FALSE is used (with no associated data). During
+compilation, however, a DEFINE condition is coded as OP_DEFINE so that, when
+the conditional group is complete, there can be a check to ensure that it
+contains only one top-level branch. Once this has happened, the opcode is
+changed to OP_FALSE, so the matcher never sees OP_DEFINE.
+
+There is a special PCRE2-specific condition of the form (VERSION[>]=x.y), which
+tests the PCRE2 version number. This compiles into one of the opcodes OP_TRUE
+or OP_FALSE.
+
+If a condition is not a back reference, recursion test, DEFINE, or VERSION, it
+must start with a parenthesized atomic assertion, whose opcode normally
+immediately follows OP_COND or OP_SCOND. However, if automatic callouts are
+enabled, a callout is inserted immediately before the assertion. It is also
+possible to insert a manual callout at this point. Only assertion conditions
+may have callouts preceding the condition.
+
+A condition that is the negative assertion (?!) is optimized to OP_FAIL in all
+parts of the pattern, so this is another opcode that may appear as a condition.
+It is treated the same as OP_FALSE.
+
+
+Recursion
+---------
+
+Recursion either matches the current pattern, or some subexpression. The opcode
+OP_RECURSE is followed by a LINK_SIZE value that is the offset to the starting
+bracket from the start of the whole pattern. OP_RECURSE is also used for
+"subroutine" calls, even though they are not strictly a recursion. Up till
+release 10.30 recursions were treated as atomic groups, making them
+incompatible with Perl (but PCRE had them well before Perl did). From 10.30,
+backtracking into recursions is supported.
+
+Repeated recursions used to be wrapped inside OP_ONCE brackets, which not only
+forced no backtracking, but also allowed repetition to be handled as for other
+bracketed groups. From 10.30 onwards, repeated recursions are duplicated for
+their minimum repetitions, and then wrapped in non-capturing brackets for the
+remainder. For example, (?1){3} is treated as (?1)(?1)(?1), and (?1){2,4} is
+treated as (?1)(?1)(?:(?1)){0,2}.
+
+
+Callouts
+--------
+
+A callout may have either a numerical argument or a string argument. These use
+OP_CALLOUT or OP_CALLOUT_STR, respectively. In each case these are followed by
+two LINK_SIZE values giving the offset in the pattern string to the start of
+the following item, and another count giving the length of this item. These
+values make it possible for pcre2test to output useful tracing information
+using callouts.
+
+In the case of a numeric callout, after these two values there is a single code
+unit containing the callout number, in the range 0-255, with 255 being used for
+callouts that are automatically inserted as a result of the PCRE2_AUTO_CALLOUT
+option. Thus, this opcode item is of fixed length:
+
+ [OP_CALLOUT] [PATTERN_OFFSET] [PATTERN_LENGTH] [NUMBER]
+
+For callouts with string arguments, OP_CALLOUT_STR has three more data items:
+a LINK_SIZE value giving the complete length of the entire opcode item, a
+LINK_SIZE item containing the offset within the pattern string to the start of
+the string argument, and the string itself, preceded by its starting delimiter
+and followed by a binary zero. When a callout function is called, a pointer to
+the actual string is passed, but the delimiter can be accessed as string[-1] if
+the application needs it. In the 8-bit library, the callout in /X(?C'abc')Y/ is
+compiled as the following bytes (decimal numbers represent binary values):
+
+ [OP_CALLOUT_STR] [0] [10] [0] [1] [0] [14] [0] [5] ['] [a] [b] [c] [0]
+ -------- ------- -------- -------
+ | | | |
+ ------- LINK_SIZE items ------
+
+Opcode table checking
+---------------------
+
+The last opcode that is defined in pcre2_internal.h is OP_TABLE_LENGTH. This is
+not a real opcode, but is used to check at compile time that tables indexed by
+opcode are the correct length, in order to catch updating errors.
+
+
+See also
+--------
+
+The file maint/README contains additional information.
+
+
+Philip Hazel
+August 2024
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..e82fd21
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,368 @@
+Installation Instructions
+*************************
+
+ Copyright (C) 1994-1996, 1999-2002, 2004-2017, 2020-2021 Free
+Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved. This file is offered as-is,
+without warranty of any kind.
+
+Basic Installation
+==================
+
+ Briefly, the shell command './configure && make && make install'
+should configure, build, and install this package. The following
+more-detailed instructions are generic; see the 'README' file for
+instructions specific to this package. Some packages provide this
+'INSTALL' file but do not implement all of the features documented
+below. The lack of an optional feature in a given package is not
+necessarily a bug. More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
+
+ The 'configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a 'Makefile' in each directory of the package.
+It may also create one or more '.h' files containing system-dependent
+definitions. Finally, it creates a shell script 'config.status' that
+you can run in the future to recreate the current configuration, and a
+file 'config.log' containing compiler output (useful mainly for
+debugging 'configure').
+
+ It can also use an optional file (typically called 'config.cache' and
+enabled with '--cache-file=config.cache' or simply '-C') that saves the
+results of its tests to speed up reconfiguring. Caching is disabled by
+default to prevent problems with accidental use of stale cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how 'configure' could check whether to do them, and mail
+diffs or instructions to the address given in the 'README' so they can
+be considered for the next release. If you are using the cache, and at
+some point 'config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file 'configure.ac' (or 'configure.in') is used to create
+'configure' by a program called 'autoconf'. You need 'configure.ac' if
+you want to change it or regenerate 'configure' using a newer version of
+'autoconf'.
+
+ The simplest way to compile this package is:
+
+ 1. 'cd' to the directory containing the package's source code and type
+ './configure' to configure the package for your system.
+
+ Running 'configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type 'make' to compile the package.
+
+ 3. Optionally, type 'make check' to run any self-tests that come with
+ the package, generally using the just-built uninstalled binaries.
+
+ 4. Type 'make install' to install the programs and any data files and
+ documentation. When installing into a prefix owned by root, it is
+ recommended that the package be configured and built as a regular
+ user, and only the 'make install' phase executed with root
+ privileges.
+
+ 5. Optionally, type 'make installcheck' to repeat any self-tests, but
+ this time using the binaries in their final installed location.
+ This target does not install anything. Running this target as a
+ regular user, particularly if the prior 'make install' required
+ root privileges, verifies that the installation completed
+ correctly.
+
+ 6. You can remove the program binaries and object files from the
+ source code directory by typing 'make clean'. To also remove the
+ files that 'configure' created (so you can compile the package for
+ a different kind of computer), type 'make distclean'. There is
+ also a 'make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+ 7. Often, you can also type 'make uninstall' to remove the installed
+ files again. In practice, not all packages have tested that
+ uninstallation works correctly, even though it is required by the
+ GNU Coding Standards.
+
+ 8. Some packages, particularly those that use Automake, provide 'make
+ distcheck', which can by used by developers to test that all other
+ targets like 'make install' and 'make uninstall' work correctly.
+ This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the 'configure' script does not know about. Run './configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give 'configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here is
+an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU 'make'. 'cd' to the
+directory where you want the object files and executables to go and run
+the 'configure' script. 'configure' automatically checks for the source
+code in the directory that 'configure' is in and in '..'. This is known
+as a "VPATH" build.
+
+ With a non-GNU 'make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use 'make distclean' before
+reconfiguring for another architecture.
+
+ On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple '-arch' options to the
+compiler but only a single '-arch' option to the preprocessor. Like
+this:
+
+ ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CPP="gcc -E" CXXCPP="g++ -E"
+
+ This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the 'lipo' tool if you have problems.
+
+Installation Names
+==================
+
+ By default, 'make install' installs the package's commands under
+'/usr/local/bin', include files under '/usr/local/include', etc. You
+can specify an installation prefix other than '/usr/local' by giving
+'configure' the option '--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like '--bindir=DIR' to specify different values for particular
+kinds of files. Run 'configure --help' for a list of the directories
+you can set and what kinds of files go in them. In general, the default
+for these options is expressed in terms of '${prefix}', so that
+specifying just '--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+ The most portable way to affect installation locations is to pass the
+correct locations to 'configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+'make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+ The first method involves providing an override variable for each
+affected directory. For example, 'make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+'${prefix}'. Any directories that were specified during 'configure',
+but not in terms of '${prefix}', must each be overridden at install time
+for the entire installation to be relocated. The approach of makefile
+variable overrides for each directory variable is required by the GNU
+Coding Standards, and ideally causes no recompilation. However, some
+platforms have known limitations with the semantics of shared libraries
+that end up requiring recompilation when using this method, particularly
+noticeable in packages that use GNU Libtool.
+
+ The second method involves providing the 'DESTDIR' variable. For
+example, 'make install DESTDIR=/alternate/directory' will prepend
+'/alternate/directory' before all installation names. The approach of
+'DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters. On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of '${prefix}'
+at 'configure' time.
+
+Optional Features
+=================
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving 'configure' the
+option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
+
+ Some packages pay attention to '--enable-FEATURE' options to
+'configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to '--with-PACKAGE' options, where PACKAGE
+is something like 'gnu-as' or 'x' (for the X Window System). The
+'README' should mention any '--enable-' and '--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, 'configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the 'configure' options '--x-includes=DIR' and
+'--x-libraries=DIR' to specify their locations.
+
+ Some packages offer the ability to configure how verbose the
+execution of 'make' will be. For these packages, running './configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with 'make V=1'; while running './configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with 'make V=0'.
+
+Particular systems
+==================
+
+ On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
+is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+ ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+ HP-UX 'make' updates targets which have the same timestamps as their
+prerequisites, which makes it generally unusable when shipped generated
+files such as 'configure' are involved. Use GNU 'make' instead.
+
+ On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its '' header file. The option '-nodtk' can be used as a
+workaround. If GNU CC is not installed, it is therefore recommended to
+try
+
+ ./configure CC="cc"
+
+and if that doesn't work, try
+
+ ./configure CC="cc -nodtk"
+
+ On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
+directory contains several dysfunctional programs; working variants of
+these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
+in your 'PATH', put it _after_ '/usr/bin'.
+
+ On Haiku, software installed for all users goes in '/boot/common',
+not '/usr/local'. It is recommended to use the following options:
+
+ ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+ There may be some features 'configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, 'configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+'--build=TYPE' option. TYPE can either be a short name for the system
+type, such as 'sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS
+ KERNEL-OS
+
+ See the file 'config.sub' for the possible values of each field. If
+'config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option '--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with '--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for 'configure' scripts to share,
+you can create a site shell script called 'config.site' that gives
+default values for variables like 'CC', 'cache_file', and 'prefix'.
+'configure' looks for 'PREFIX/share/config.site' if it exists, then
+'PREFIX/etc/config.site' if it exists. Or, you can set the
+'CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all 'configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to 'configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the 'configure' command line, using 'VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified 'gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
+Autoconf limitation. Until the limitation is lifted, you can use this
+workaround:
+
+ CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+'configure' Invocation
+======================
+
+ 'configure' recognizes the following options to control how it
+operates.
+
+'--help'
+'-h'
+ Print a summary of all of the options to 'configure', and exit.
+
+'--help=short'
+'--help=recursive'
+ Print a summary of the options unique to this package's
+ 'configure', and exit. The 'short' variant lists options used only
+ in the top level, while the 'recursive' variant lists options also
+ present in any nested packages.
+
+'--version'
+'-V'
+ Print the version of Autoconf used to generate the 'configure'
+ script, and exit.
+
+'--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally 'config.cache'. FILE defaults to '/dev/null' to
+ disable caching.
+
+'--config-cache'
+'-C'
+ Alias for '--cache-file=config.cache'.
+
+'--quiet'
+'--silent'
+'-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to '/dev/null' (any error
+ messages will still be shown).
+
+'--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ 'configure' can determine that directory automatically.
+
+'--prefix=DIR'
+ Use DIR as the installation prefix. *note Installation Names:: for
+ more details, including other options available for fine-tuning the
+ installation locations.
+
+'--no-create'
+'-n'
+ Run the configure checks, but stop before creating any output
+ files.
+
+'configure' also accepts some other, not widely useful, options. Run
+'configure --help' for more details.
diff --git a/LICENCE.md b/LICENCE.md
new file mode 100644
index 0000000..f6fba35
--- /dev/null
+++ b/LICENCE.md
@@ -0,0 +1,104 @@
+PCRE2 Licence
+=============
+
+| SPDX-License-Identifier: | BSD-3-Clause WITH PCRE2-exception |
+|---------|-------|
+
+PCRE2 is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+Releases 10.00 and above of PCRE2 are distributed under the terms of the "BSD"
+licence, as specified below, with one exemption for certain binary
+redistributions. The documentation for PCRE2, supplied in the "doc" directory,
+is distributed under the same terms as the software itself. The data in the
+testdata directory is not copyrighted and is in the public domain.
+
+The basic library functions are written in C and are freestanding. Also
+included in the distribution is a just-in-time compiler that can be used to
+optimize pattern matching. This is an optional feature that can be omitted when
+the library is built. The just-in-time compiler is separately licensed under the
+"2-clause BSD" licence.
+
+
+COPYRIGHT
+---------
+
+### The basic library functions
+
+ Written by: Philip Hazel
+ Email local part: Philip.Hazel
+ Email domain: gmail.com
+
+ Retired from University of Cambridge Computing Service,
+ Cambridge, England.
+
+ Copyright (c) 1997-2007 University of Cambridge
+ Copyright (c) 2007-2024 Philip Hazel
+ All rights reserved.
+
+### PCRE2 Just-In-Time compilation support
+
+ Written by: Zoltan Herczeg
+ Email local part: hzmester
+ Email domain: freemail.hu
+
+ Copyright (c) 2010-2024 Zoltan Herczeg
+ All rights reserved.
+
+### Stack-less Just-In-Time compiler
+
+ Written by: Zoltan Herczeg
+ Email local part: hzmester
+ Email domain: freemail.hu
+
+ Copyright (c) 2009-2024 Zoltan Herczeg
+ All rights reserved.
+
+The code in the `deps/sljit` directory has its own LICENSE file.
+
+### All other contributions
+
+Many other contributors have participated in the authorship of PCRE2. As PCRE2
+has never required a Contributor Licensing Agreement, or other copyright
+assignment agreement, all contributions have copyright retained by each
+original contributor or their employer.
+
+
+THE "BSD" LICENCE
+-----------------
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notices,
+ this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notices, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of the University of Cambridge nor the names of any
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+EXEMPTION FOR BINARY LIBRARY-LIKE PACKAGES
+------------------------------------------
+
+The second condition in the BSD licence (covering binary redistributions) does
+not apply all the way down a chain of software. If binary package A includes
+PCRE2, it must respect the condition, but if package B is software that
+includes package A, the condition is not imposed on package B unless it uses
+PCRE2 independently.
diff --git a/MODULE.bazel b/MODULE.bazel
new file mode 100644
index 0000000..ac5e974
--- /dev/null
+++ b/MODULE.bazel
@@ -0,0 +1,9 @@
+module(
+ name = "pcre2",
+ version = "10.48",
+ compatibility_level = 1,
+)
+
+bazel_dep(name = "rules_cc", version = "0.2.8")
+bazel_dep(name = "bazel_skylib", version = "1.8.1")
+bazel_dep(name = "platforms", version = "1.0.0")
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..e112b5c
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,1060 @@
+## Process this file with automake to produce Makefile.in.
+
+AUTOMAKE_OPTIONS = subdir-objects
+ACLOCAL_AMFLAGS = -I m4
+
+## This seems to have become necessary for building in non-source directory.
+
+AM_CPPFLAGS="-I$(srcdir)/src"
+
+## Set some variables to accumulate conditionally-set Automake targets.
+
+CLEAN_LOCAL_TARGETS=
+DISTCLEAN_LOCAL_TARGETS=
+PHONY_TARGETS=
+
+## Specify the documentation files that are distributed.
+
+dist_doc_DATA = \
+ AUTHORS.md \
+ COPYING \
+ ChangeLog \
+ LICENCE.md \
+ NEWS \
+ README \
+ SECURITY.md \
+ SUPPORT-LIFECYCLE.md \
+ doc/pcre2.txt \
+ doc/pcre2-config.txt \
+ doc/pcre2grep.txt \
+ doc/pcre2test.txt
+
+dist_html_DATA = \
+ doc/html/NON-AUTOTOOLS-BUILD.txt \
+ doc/html/README.txt \
+ doc/html/index.html \
+ doc/html/pcre2-config.html \
+ doc/html/pcre2.html \
+ doc/html/pcre2_callout_enumerate.html \
+ doc/html/pcre2_code_copy.html \
+ doc/html/pcre2_code_copy_with_tables.html \
+ doc/html/pcre2_code_free.html \
+ doc/html/pcre2_compile.html \
+ doc/html/pcre2_compile_context_copy.html \
+ doc/html/pcre2_compile_context_create.html \
+ doc/html/pcre2_compile_context_free.html \
+ doc/html/pcre2_config.html \
+ doc/html/pcre2_convert_context_copy.html \
+ doc/html/pcre2_convert_context_create.html \
+ doc/html/pcre2_convert_context_free.html \
+ doc/html/pcre2_converted_pattern_free.html \
+ doc/html/pcre2_dfa_match.html \
+ doc/html/pcre2_general_context_copy.html \
+ doc/html/pcre2_general_context_create.html \
+ doc/html/pcre2_general_context_free.html \
+ doc/html/pcre2_get_error_message.html \
+ doc/html/pcre2_get_mark.html \
+ doc/html/pcre2_get_match_data_heapframes_size.html \
+ doc/html/pcre2_get_match_data_size.html \
+ doc/html/pcre2_get_ovector_count.html \
+ doc/html/pcre2_get_ovector_pointer.html \
+ doc/html/pcre2_get_startchar.html \
+ doc/html/pcre2_jit_compile.html \
+ doc/html/pcre2_jit_free_unused_memory.html \
+ doc/html/pcre2_jit_match.html \
+ doc/html/pcre2_jit_stack_assign.html \
+ doc/html/pcre2_jit_stack_create.html \
+ doc/html/pcre2_jit_stack_free.html \
+ doc/html/pcre2_maketables.html \
+ doc/html/pcre2_maketables_free.html \
+ doc/html/pcre2_match.html \
+ doc/html/pcre2_match_context_copy.html \
+ doc/html/pcre2_match_context_create.html \
+ doc/html/pcre2_match_context_free.html \
+ doc/html/pcre2_match_data_create.html \
+ doc/html/pcre2_match_data_create_from_pattern.html \
+ doc/html/pcre2_match_data_free.html \
+ doc/html/pcre2_next_match.html \
+ doc/html/pcre2_pattern_convert.html \
+ doc/html/pcre2_pattern_info.html \
+ doc/html/pcre2_serialize_decode.html \
+ doc/html/pcre2_serialize_encode.html \
+ doc/html/pcre2_serialize_free.html \
+ doc/html/pcre2_serialize_get_number_of_codes.html \
+ doc/html/pcre2_set_bsr.html \
+ doc/html/pcre2_set_callout.html \
+ doc/html/pcre2_set_character_tables.html \
+ doc/html/pcre2_set_compile_extra_options.html \
+ doc/html/pcre2_set_compile_recursion_guard.html \
+ doc/html/pcre2_set_depth_limit.html \
+ doc/html/pcre2_set_glob_escape.html \
+ doc/html/pcre2_set_glob_separator.html \
+ doc/html/pcre2_set_heap_limit.html \
+ doc/html/pcre2_set_match_limit.html \
+ doc/html/pcre2_set_max_pattern_compiled_length.html \
+ doc/html/pcre2_set_max_pattern_length.html \
+ doc/html/pcre2_set_max_varlookbehind.html \
+ doc/html/pcre2_set_offset_limit.html \
+ doc/html/pcre2_set_optimize.html \
+ doc/html/pcre2_set_newline.html \
+ doc/html/pcre2_set_parens_nest_limit.html \
+ doc/html/pcre2_set_recursion_limit.html \
+ doc/html/pcre2_set_recursion_memory_management.html \
+ doc/html/pcre2_set_substitute_callout.html \
+ doc/html/pcre2_set_substitute_case_callout.html \
+ doc/html/pcre2_substitute.html \
+ doc/html/pcre2_substring_copy_byname.html \
+ doc/html/pcre2_substring_copy_bynumber.html \
+ doc/html/pcre2_substring_free.html \
+ doc/html/pcre2_substring_get_byname.html \
+ doc/html/pcre2_substring_get_bynumber.html \
+ doc/html/pcre2_substring_length_byname.html \
+ doc/html/pcre2_substring_length_bynumber.html \
+ doc/html/pcre2_substring_list_free.html \
+ doc/html/pcre2_substring_list_get.html \
+ doc/html/pcre2_substring_nametable_scan.html \
+ doc/html/pcre2_substring_number_from_name.html \
+ doc/html/pcre2api.html \
+ doc/html/pcre2build.html \
+ doc/html/pcre2callout.html \
+ doc/html/pcre2compat.html \
+ doc/html/pcre2convert.html \
+ doc/html/pcre2demo.html \
+ doc/html/pcre2grep.html \
+ doc/html/pcre2jit.html \
+ doc/html/pcre2limits.html \
+ doc/html/pcre2matching.html \
+ doc/html/pcre2partial.html \
+ doc/html/pcre2pattern.html \
+ doc/html/pcre2perform.html \
+ doc/html/pcre2posix.html \
+ doc/html/pcre2sample.html \
+ doc/html/pcre2serialize.html \
+ doc/html/pcre2syntax.html \
+ doc/html/pcre2test.html \
+ doc/html/pcre2unicode.html
+
+dist_man_MANS = \
+ doc/pcre2-config.1 \
+ doc/pcre2.3 \
+ doc/pcre2_callout_enumerate.3 \
+ doc/pcre2_code_copy.3 \
+ doc/pcre2_code_copy_with_tables.3 \
+ doc/pcre2_code_free.3 \
+ doc/pcre2_compile.3 \
+ doc/pcre2_compile_context_copy.3 \
+ doc/pcre2_compile_context_create.3 \
+ doc/pcre2_compile_context_free.3 \
+ doc/pcre2_config.3 \
+ doc/pcre2_convert_context_copy.3 \
+ doc/pcre2_convert_context_create.3 \
+ doc/pcre2_convert_context_free.3 \
+ doc/pcre2_converted_pattern_free.3 \
+ doc/pcre2_dfa_match.3 \
+ doc/pcre2_general_context_copy.3 \
+ doc/pcre2_general_context_create.3 \
+ doc/pcre2_general_context_free.3 \
+ doc/pcre2_get_error_message.3 \
+ doc/pcre2_get_mark.3 \
+ doc/pcre2_get_match_data_heapframes_size.3 \
+ doc/pcre2_get_match_data_size.3 \
+ doc/pcre2_get_ovector_count.3 \
+ doc/pcre2_get_ovector_pointer.3 \
+ doc/pcre2_get_startchar.3 \
+ doc/pcre2_jit_compile.3 \
+ doc/pcre2_jit_free_unused_memory.3 \
+ doc/pcre2_jit_match.3 \
+ doc/pcre2_jit_stack_assign.3 \
+ doc/pcre2_jit_stack_create.3 \
+ doc/pcre2_jit_stack_free.3 \
+ doc/pcre2_maketables.3 \
+ doc/pcre2_maketables_free.3 \
+ doc/pcre2_match.3 \
+ doc/pcre2_match_context_copy.3 \
+ doc/pcre2_match_context_create.3 \
+ doc/pcre2_match_context_free.3 \
+ doc/pcre2_match_data_create.3 \
+ doc/pcre2_match_data_create_from_pattern.3 \
+ doc/pcre2_match_data_free.3 \
+ doc/pcre2_next_match.3 \
+ doc/pcre2_pattern_convert.3 \
+ doc/pcre2_pattern_info.3 \
+ doc/pcre2_serialize_decode.3 \
+ doc/pcre2_serialize_encode.3 \
+ doc/pcre2_serialize_free.3 \
+ doc/pcre2_serialize_get_number_of_codes.3 \
+ doc/pcre2_set_bsr.3 \
+ doc/pcre2_set_callout.3 \
+ doc/pcre2_set_character_tables.3 \
+ doc/pcre2_set_compile_extra_options.3 \
+ doc/pcre2_set_compile_recursion_guard.3 \
+ doc/pcre2_set_depth_limit.3 \
+ doc/pcre2_set_glob_escape.3 \
+ doc/pcre2_set_glob_separator.3 \
+ doc/pcre2_set_heap_limit.3 \
+ doc/pcre2_set_match_limit.3 \
+ doc/pcre2_set_max_pattern_compiled_length.3 \
+ doc/pcre2_set_max_pattern_length.3 \
+ doc/pcre2_set_max_varlookbehind.3 \
+ doc/pcre2_set_offset_limit.3 \
+ doc/pcre2_set_optimize.3 \
+ doc/pcre2_set_newline.3 \
+ doc/pcre2_set_parens_nest_limit.3 \
+ doc/pcre2_set_recursion_limit.3 \
+ doc/pcre2_set_recursion_memory_management.3 \
+ doc/pcre2_set_substitute_callout.3 \
+ doc/pcre2_set_substitute_case_callout.3 \
+ doc/pcre2_substitute.3 \
+ doc/pcre2_substring_copy_byname.3 \
+ doc/pcre2_substring_copy_bynumber.3 \
+ doc/pcre2_substring_free.3 \
+ doc/pcre2_substring_get_byname.3 \
+ doc/pcre2_substring_get_bynumber.3 \
+ doc/pcre2_substring_length_byname.3 \
+ doc/pcre2_substring_length_bynumber.3 \
+ doc/pcre2_substring_list_free.3 \
+ doc/pcre2_substring_list_get.3 \
+ doc/pcre2_substring_nametable_scan.3 \
+ doc/pcre2_substring_number_from_name.3 \
+ doc/pcre2api.3 \
+ doc/pcre2build.3 \
+ doc/pcre2callout.3 \
+ doc/pcre2compat.3 \
+ doc/pcre2convert.3 \
+ doc/pcre2demo.3 \
+ doc/pcre2grep.1 \
+ doc/pcre2jit.3 \
+ doc/pcre2limits.3 \
+ doc/pcre2matching.3 \
+ doc/pcre2partial.3 \
+ doc/pcre2pattern.3 \
+ doc/pcre2perform.3 \
+ doc/pcre2posix.3 \
+ doc/pcre2sample.3 \
+ doc/pcre2serialize.3 \
+ doc/pcre2syntax.3 \
+ doc/pcre2test.1 \
+ doc/pcre2unicode.3
+
+# The Libtool libraries to install. We'll add to this later.
+
+lib_LTLIBRARIES =
+
+# Unit tests you want to run when people type 'make check'.
+# TESTS is for binary unit tests, check_SCRIPTS for script-based tests
+
+TESTS =
+XFAIL_TESTS =
+check_SCRIPTS =
+dist_noinst_SCRIPTS =
+
+# Some of the binaries we make are to be installed, and others are
+# (non-user-visible) helper programs needed to build the libraries.
+
+bin_PROGRAMS =
+noinst_PROGRAMS =
+
+# Additional files to delete on 'make clean', 'make distclean',
+# and 'make maintainer-clean'. It turns out that the default is to delete only
+# those binaries that *this* configuration has created. If the configuration
+# has been changed, some binaries may not get automatically deleted. Therefore
+# we list them here.
+
+CLEANFILES = \
+ pcre2_dftables \
+ pcre2_jit_test \
+ pcre2fuzzcheck-8 \
+ pcre2fuzzcheck-16 \
+ pcre2fuzzcheck-32 \
+ pcre2demo
+
+DISTCLEANFILES = src/config.h.in~
+MAINTAINERCLEANFILES =
+
+# Additional files to bundle with the distribution, over and above what
+# the Autotools include by default.
+
+EXTRA_DIST =
+
+# These files contain additional m4 macros that are used by autoconf.
+
+EXTRA_DIST += \
+ m4/ax_pthread.m4 \
+ m4/pcre2_check_vscript.m4 \
+ m4/pcre2_visibility.m4 \
+ m4/pcre2_zos.m4
+
+# These files contain maintenance information
+
+EXTRA_DIST += \
+ NON-AUTOTOOLS-BUILD \
+ HACKING
+
+# These are patches containing backports for older versions of PCRE2
+
+EXTRA_DIST += \
+ patches/pcre2-10.37-Remove-real-POSIX.patch \
+ patches/pcre2-10.39-Fix-incorrect-detection.patch \
+ patches/pcre2-10.40-A-Fixed-a-unicode.patch \
+ patches/pcre2-10.40-B-Fixed-an-issue-affecting.patch \
+ patches/pcre2-10.43-Avoid-LIMIT_HEAP-integer.patch \
+ patches/pcre2-10.43-Fix-heapframe-overflow.patch \
+ patches/pcre2-10.44-Fix-incorrect-compiling.patch \
+ patches/pcre2-10.44-Fix-locking-region.patch \
+ patches/pcre2-10.45-Memory-reports-only-compiled.patch \
+ patches/pcre2-10.47-Fix-for-callback.patch \
+ patches/pcre2-10.48-Check-JIT-mode-before-validation.patch \
+ patches/pcre2-10.48-Fix-DFA-workspace-overflows.patch \
+ patches/pcre2-10.48-Fix-JIT-STR_END.patch \
+ patches/pcre2-10.48-Fix-JIT-match-context-reuse.patch \
+ patches/pcre2-10.48-Fix-allocation-byte-sizing.patch \
+ patches/pcre2-10.48-Fix-character-list-generator.patch \
+ patches/pcre2-10.48-Fix-compiler-integer-overflows.patch \
+ patches/pcre2-10.48-Fix-invalid-UTF-backwards-scans.patch \
+ patches/pcre2-10.48-Fix-repeated-substitute-escapes.patch \
+ patches/pcre2-10.48-Fix-scan-prefix-repeat-reset.patch \
+ patches/pcre2-10.48-Keep-escape-error-offset-in-pattern.patch \
+ patches/pcre2-10.48-Write-serialization-padding.patch
+
+# These are support files for building with Bazel or Zig
+
+EXTRA_DIST += \
+ BUILD.bazel \
+ MODULE.bazel \
+ build.zig \
+ build.zig.zon
+
+# These are support files for building under VMS
+
+EXTRA_DIST += \
+ vms/configure.com \
+ vms/openvms_readme.txt \
+ vms/pcre2.h_patch \
+ vms/stdint.h
+
+# These files are usable versions of pcre2.h and config.h that are distributed
+# for the benefit of people who are building PCRE2 manually, without the
+# Autotools support.
+
+EXTRA_DIST += \
+ src/pcre2.h.generic \
+ src/config.h.generic
+
+# The only difference between pcre2.h.in and pcre2.h is the setting of the PCRE
+# version number. Therefore, we can create the generic version just by copying.
+
+src/pcre2.h.generic: src/pcre2.h.in configure.ac
+ rm -f $@
+ cp -p src/pcre2.h $@
+
+# It is more complicated for config.h.generic. We need the version that results
+# from a default configuration so as to get all the default values for PCRE
+# configuration macros such as MATCH_LIMIT and NEWLINE. We can get this by
+# doing a configure in a temporary directory. However, some trickery is needed,
+# because the source directory may already be configured. If you just try
+# running configure in a new directory, it complains. For this reason, we move
+# config.status out of the way while doing the default configuration. The
+# resulting config.h is munged by perl to put #ifdefs round any #defines for
+# macros with values, and to #undef all boolean macros such as HAVE_xxx,
+# SUPPORT_xxx, and PCRE2_STATIC/PCRE2POSIX_SHARED. We also get rid of any
+# GCC-specific visibility settings.
+
+src/config.h.generic: configure.ac
+ rm -rf $@ _generic
+ mkdir _generic
+ cs=$(srcdir)/config.status; test ! -f $$cs || mv -f $$cs $$cs.aside
+ cd _generic && $(abs_top_srcdir)/configure || :
+ cs=$(srcdir)/config.status; test ! -f $$cs.aside || mv -f $$cs.aside $$cs
+ test -f _generic/src/config.h
+ perl -n \
+ -e 'BEGIN{$$blank=0;}' \
+ -e 'if(/(.+?)\s*__attribute__ \(\(visibility/){print"$$1\n";$$blank=0;next;}' \
+ -e 'if(/LT_OBJDIR/){print"/* This is ignored unless you are using libtool. */\n";}' \
+ -e 'if(/^#define\s((?:HAVE|SUPPORT|STDC)_\w+|PCRE2_STATIC|PCRE2POSIX_SHARED)/){print"/* #undef $$1 */\n";$$blank=0;next;}' \
+ -e 'if(/^#define\s(?!PACKAGE|VERSION)(\w+)/){print"#ifndef $$1\n$$_#endif\n";$$blank=0;next;}' \
+ -e 'if(/^\s*$$/){print unless $$blank; $$blank=1;} else{print;$$blank=0;}' \
+ _generic/src/config.h >$@
+ rm -rf _generic
+
+MAINTAINERCLEANFILES += src/pcre2.h.generic src/config.h.generic
+
+# These are the header files we'll install. We do not distribute pcre2.h
+# because it is generated from pcre2.h.in.
+
+nodist_include_HEADERS = src/pcre2.h
+include_HEADERS = src/pcre2posix.h
+
+# This is the "config" script.
+
+bin_SCRIPTS = pcre2-config
+
+## ---------------------------------------------------------------
+## The pcre2_dftables program is used to rebuild character tables before
+## compiling PCRE2, if --enable-rebuild-chartables is specified. It is not an
+## installed program. The default (when --enable-rebuild-chartables is not
+## specified) is to copy a distributed set of tables that are defined for ASCII
+## code. In this case, pcre2_dftables is not needed.
+
+if WITH_REBUILD_CHARTABLES
+noinst_PROGRAMS += pcre2_dftables
+pcre2_dftables_SOURCES = src/pcre2_dftables.c
+src/pcre2_chartables.c: pcre2_dftables$(EXEEXT)
+ rm -f $@
+ ./pcre2_dftables$(EXEEXT) $@
+else
+if WITH_EBCDIC
+if WITH_EBCDIC_NL25
+src/pcre2_chartables.c: $(srcdir)/src/pcre2_chartables.c.ebcdic-1047-nl25
+ rm -f $@
+ $(LN_S) $(abs_srcdir)/src/pcre2_chartables.c.ebcdic-1047-nl25 $(abs_builddir)/src/pcre2_chartables.c
+else # WITH_EBCDIC_NL25
+src/pcre2_chartables.c: $(srcdir)/src/pcre2_chartables.c.ebcdic-1047-nl15
+ rm -f $@
+ $(LN_S) $(abs_srcdir)/src/pcre2_chartables.c.ebcdic-1047-nl15 $(abs_builddir)/src/pcre2_chartables.c
+endif # WITH_EBCDIC_NL25
+else # WITH_EBCDIC
+src/pcre2_chartables.c: $(srcdir)/src/pcre2_chartables.c.dist
+ rm -f $@
+ $(LN_S) $(abs_srcdir)/src/pcre2_chartables.c.dist $(abs_builddir)/src/pcre2_chartables.c
+endif # WITH_EBCDIC
+endif # WITH_REBUILD_CHARTABLES
+
+BUILT_SOURCES = src/pcre2_chartables.c
+NODIST_SOURCES = src/pcre2_chartables.c
+
+## Define the list of common sources, then arrange to build whichever of the
+## 8-, 16-, or 32-bit libraries are configured.
+
+COMMON_SOURCES = \
+ src/pcre2_auto_possess.c \
+ src/pcre2_chkdint.c \
+ src/pcre2_compile.c \
+ src/pcre2_compile.h \
+ src/pcre2_compile_cgroup.c \
+ src/pcre2_compile_class.c \
+ src/pcre2_config.c \
+ src/pcre2_context.c \
+ src/pcre2_convert.c \
+ src/pcre2_dfa_match.c \
+ src/pcre2_error.c \
+ src/pcre2_extuni.c \
+ src/pcre2_find_bracket.c \
+ src/pcre2_internal.h \
+ src/pcre2_intmodedep.h \
+ src/pcre2_jit_char_inc.h \
+ src/pcre2_jit_compile.c \
+ src/pcre2_jit_match_inc.h \
+ src/pcre2_jit_misc_inc.h \
+ src/pcre2_jit_simd_inc.h \
+ src/pcre2_maketables.c \
+ src/pcre2_match.c \
+ src/pcre2_match_data.c \
+ src/pcre2_match_next.c \
+ src/pcre2_newline.c \
+ src/pcre2_ord2utf.c \
+ src/pcre2_pattern_info.c \
+ src/pcre2_printint_inc.h \
+ src/pcre2_script_run.c \
+ src/pcre2_serialize.c \
+ src/pcre2_string_utils.c \
+ src/pcre2_study.c \
+ src/pcre2_substitute.c \
+ src/pcre2_substring.c \
+ src/pcre2_tables.c \
+ src/pcre2_ucd.c \
+ src/pcre2_ucp.h \
+ src/pcre2_ucptables_inc.h \
+ src/pcre2_util.h \
+ src/pcre2_valid_utf.c \
+ src/pcre2_xclass.c
+
+if WITH_PCRE2_8
+lib_LTLIBRARIES += libpcre2-8.la
+libpcre2_8_la_SOURCES = \
+ $(COMMON_SOURCES)
+nodist_libpcre2_8_la_SOURCES = \
+ $(NODIST_SOURCES)
+libpcre2_8_la_CFLAGS = \
+ -DPCRE2_CODE_UNIT_WIDTH=8 \
+ $(VISIBILITY_CFLAGS) \
+ $(CET_CFLAGS) \
+ $(AM_CFLAGS)
+libpcre2_8_la_LIBADD =
+endif # WITH_PCRE2_8
+
+if WITH_PCRE2_16
+lib_LTLIBRARIES += libpcre2-16.la
+libpcre2_16_la_SOURCES = \
+ $(COMMON_SOURCES)
+nodist_libpcre2_16_la_SOURCES = \
+ $(NODIST_SOURCES)
+libpcre2_16_la_CFLAGS = \
+ -DPCRE2_CODE_UNIT_WIDTH=16 \
+ $(VISIBILITY_CFLAGS) \
+ $(CET_CFLAGS) \
+ $(AM_CFLAGS)
+libpcre2_16_la_LIBADD =
+endif # WITH_PCRE2_16
+
+if WITH_PCRE2_32
+lib_LTLIBRARIES += libpcre2-32.la
+libpcre2_32_la_SOURCES = \
+ $(COMMON_SOURCES)
+nodist_libpcre2_32_la_SOURCES = \
+ $(NODIST_SOURCES)
+libpcre2_32_la_CFLAGS = \
+ -DPCRE2_CODE_UNIT_WIDTH=32 \
+ $(VISIBILITY_CFLAGS) \
+ $(CET_CFLAGS) \
+ $(AM_CFLAGS)
+libpcre2_32_la_LIBADD =
+endif # WITH_PCRE2_32
+
+# The pcre2_chartables.c.dist file is the default version of
+# pcre2_chartables.c, used unless --enable-rebuild-chartables is specified.
+
+EXTRA_DIST += \
+ src/pcre2_chartables.c.dist \
+ src/pcre2_chartables.c.ebcdic-1047-nl15 \
+ src/pcre2_chartables.c.ebcdic-1047-nl25
+CLEANFILES += src/pcre2_chartables.c
+
+# The JIT compiler lives in a separate directory, but its files are #included
+# when pcre2_jit_compile.c is processed, so they must be distributed.
+
+EXTRA_DIST += \
+ deps/sljit/LICENSE \
+ deps/sljit/README.md \
+ deps/sljit/sljit_src/sljitConfig.h \
+ deps/sljit/sljit_src/sljitConfigCPU.h \
+ deps/sljit/sljit_src/sljitConfigInternal.h \
+ deps/sljit/sljit_src/sljitLir.c \
+ deps/sljit/sljit_src/sljitLir.h \
+ deps/sljit/sljit_src/sljitNativeARM_32.c \
+ deps/sljit/sljit_src/sljitNativeARM_64.c \
+ deps/sljit/sljit_src/sljitNativeARM_T2_32.c \
+ deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c \
+ deps/sljit/sljit_src/sljitNativeMIPS_32.c \
+ deps/sljit/sljit_src/sljitNativeMIPS_64.c \
+ deps/sljit/sljit_src/sljitNativeMIPS_common.c \
+ deps/sljit/sljit_src/sljitNativePPC_32.c \
+ deps/sljit/sljit_src/sljitNativePPC_64.c \
+ deps/sljit/sljit_src/sljitNativePPC_common.c \
+ deps/sljit/sljit_src/sljitNativeRISCV_32.c \
+ deps/sljit/sljit_src/sljitNativeRISCV_64.c \
+ deps/sljit/sljit_src/sljitNativeRISCV_common.c \
+ deps/sljit/sljit_src/sljitNativeS390X.c \
+ deps/sljit/sljit_src/sljitNativeX86_32.c \
+ deps/sljit/sljit_src/sljitNativeX86_64.c \
+ deps/sljit/sljit_src/sljitNativeX86_common.c \
+ deps/sljit/sljit_src/sljitSerialize.c \
+ deps/sljit/sljit_src/sljitUtils.c \
+ deps/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c \
+ deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c \
+ deps/sljit/sljit_src/allocator_src/sljitExecAllocatorFreeBSD.c \
+ deps/sljit/sljit_src/allocator_src/sljitExecAllocatorPosix.c \
+ deps/sljit/sljit_src/allocator_src/sljitExecAllocatorWindows.c \
+ deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorNetBSD.c \
+ deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorPosix.c \
+ deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorPosix.c \
+ deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorWindows.c
+
+if WITH_PCRE2_8
+libpcre2_8_la_LDFLAGS = $(EXTRA_LIBPCRE2_8_LDFLAGS)
+endif # WITH_PCRE2_8
+if WITH_PCRE2_16
+libpcre2_16_la_LDFLAGS = $(EXTRA_LIBPCRE2_16_LDFLAGS)
+endif # WITH_PCRE2_16
+if WITH_PCRE2_32
+libpcre2_32_la_LDFLAGS = $(EXTRA_LIBPCRE2_32_LDFLAGS)
+endif # WITH_PCRE2_32
+
+if WITH_VALGRIND
+if WITH_PCRE2_8
+libpcre2_8_la_CFLAGS += $(VALGRIND_CFLAGS)
+endif # WITH_PCRE2_8
+if WITH_PCRE2_16
+libpcre2_16_la_CFLAGS += $(VALGRIND_CFLAGS)
+endif # WITH_PCRE2_16
+if WITH_PCRE2_32
+libpcre2_32_la_CFLAGS += $(VALGRIND_CFLAGS)
+endif # WITH_PCRE2_32
+endif # WITH_VALGRIND
+
+if WITH_GCOV
+if WITH_PCRE2_8
+libpcre2_8_la_CFLAGS += $(GCOV_CFLAGS)
+endif # WITH_PCRE2_8
+if WITH_PCRE2_16
+libpcre2_16_la_CFLAGS += $(GCOV_CFLAGS)
+endif # WITH_PCRE2_16
+if WITH_PCRE2_32
+libpcre2_32_la_CFLAGS += $(GCOV_CFLAGS)
+endif # WITH_PCRE2_32
+endif # WITH_GCOV
+
+## A version of the 8-bit library that has a POSIX API.
+
+if WITH_PCRE2_8
+lib_LTLIBRARIES += libpcre2-posix.la
+libpcre2_posix_la_SOURCES = src/pcre2posix.c
+libpcre2_posix_la_CFLAGS = \
+ -DPCRE2_CODE_UNIT_WIDTH=8 @PCRE2POSIX_CFLAG@ \
+ $(VISIBILITY_CFLAGS) $(AM_CFLAGS)
+libpcre2_posix_la_LDFLAGS = $(EXTRA_LIBPCRE2_POSIX_LDFLAGS)
+libpcre2_posix_la_LIBADD = libpcre2-8.la
+if WITH_GCOV
+libpcre2_posix_la_CFLAGS += $(GCOV_CFLAGS)
+endif # WITH_GCOV
+endif # WITH_PCRE2_8
+
+## Build pcre2grep and optional fuzzer stuff if the 8-bit library is enabled
+
+if WITH_PCRE2_8
+bin_PROGRAMS += pcre2grep
+pcre2grep_SOURCES = src/pcre2grep.c
+pcre2grep_CFLAGS = $(AM_CFLAGS)
+pcre2grep_LDADD = $(LIBZ) $(LIBBZ2)
+pcre2grep_LDADD += libpcre2-8.la
+if WITH_GCOV
+pcre2grep_CFLAGS += $(GCOV_CFLAGS)
+pcre2grep_LDADD += $(GCOV_LIBS)
+endif # WITH_GCOV
+endif # WITH_PCRE2_8
+
+## If fuzzer support is enabled, build a non-distributed library containing the
+## fuzzing function. Also build the standalone checking binary from the same
+## source but using -DSTANDALONE.
+
+if WITH_FUZZ_SUPPORT
+noinst_LIBRARIES =
+if WITH_PCRE2_8
+noinst_LIBRARIES += .libs/libpcre2-fuzzsupport.a
+_libs_libpcre2_fuzzsupport_a_SOURCES = src/pcre2_fuzzsupport.c
+_libs_libpcre2_fuzzsupport_a_CFLAGS = $(AM_CFLAGS)
+_libs_libpcre2_fuzzsupport_a_LIBADD =
+
+noinst_PROGRAMS += pcre2fuzzcheck-8
+pcre2fuzzcheck_8_SOURCES = src/pcre2_fuzzsupport.c
+pcre2fuzzcheck_8_CFLAGS = -DSTANDALONE $(AM_CFLAGS)
+pcre2fuzzcheck_8_LDADD = libpcre2-8.la
+if WITH_GCOV
+pcre2fuzzcheck_8_CFLAGS += $(GCOV_CFLAGS)
+pcre2fuzzcheck_8_LDADD += $(GCOV_LIBS)
+endif # WITH_GCOV
+endif # WITH_PCRE2_8
+
+if WITH_PCRE2_16
+noinst_LIBRARIES += .libs/libpcre2-fuzzsupport-16.a
+_libs_libpcre2_fuzzsupport_16_a_SOURCES = src/pcre2_fuzzsupport.c
+_libs_libpcre2_fuzzsupport_16_a_CFLAGS = $(AM_CFLAGS) -DPCRE2_CODE_UNIT_WIDTH=16
+_libs_libpcre2_fuzzsupport_16_a_LIBADD =
+
+noinst_PROGRAMS += pcre2fuzzcheck-16
+pcre2fuzzcheck_16_SOURCES = src/pcre2_fuzzsupport.c
+pcre2fuzzcheck_16_CFLAGS = -DSTANDALONE $(AM_CFLAGS) -DPCRE2_CODE_UNIT_WIDTH=16
+pcre2fuzzcheck_16_LDADD = libpcre2-16.la
+if WITH_GCOV
+pcre2fuzzcheck_16_CFLAGS += $(GCOV_CFLAGS)
+pcre2fuzzcheck_16_LDADD += $(GCOV_LIBS)
+endif # WITH_GCOV
+endif # WITH_PCRE2_16
+
+if WITH_PCRE2_32
+noinst_LIBRARIES += .libs/libpcre2-fuzzsupport-32.a
+_libs_libpcre2_fuzzsupport_32_a_SOURCES = src/pcre2_fuzzsupport.c
+_libs_libpcre2_fuzzsupport_32_a_CFLAGS = $(AM_CFLAGS) -DPCRE2_CODE_UNIT_WIDTH=32
+_libs_libpcre2_fuzzsupport_32_a_LIBADD =
+
+noinst_PROGRAMS += pcre2fuzzcheck-32
+pcre2fuzzcheck_32_SOURCES = src/pcre2_fuzzsupport.c
+pcre2fuzzcheck_32_CFLAGS = -DSTANDALONE $(AM_CFLAGS) -DPCRE2_CODE_UNIT_WIDTH=32
+pcre2fuzzcheck_32_LDADD = libpcre2-32.la
+if WITH_GCOV
+pcre2fuzzcheck_32_CFLAGS += $(GCOV_CFLAGS)
+pcre2fuzzcheck_32_LDADD += $(GCOV_LIBS)
+endif # WITH_GCOV
+endif # WITH_PCRE2_32
+
+endif # WITH_FUZZ_SUPPORT
+
+## -------- Testing ----------
+
+## If the 8-bit library is enabled, build the POSIX wrapper test program and
+## arrange for it to run.
+
+if WITH_PCRE2_8
+TESTS += pcre2posix_test
+noinst_PROGRAMS += pcre2posix_test
+pcre2posix_test_SOURCES = src/pcre2posix_test.c
+pcre2posix_test_CFLAGS = $(AM_CFLAGS) @PCRE2POSIX_CFLAG@
+pcre2posix_test_LDADD = libpcre2-posix.la libpcre2-8.la
+endif # WITH_PCRE2_8
+
+## If JIT support is enabled, arrange for the JIT test program to run.
+
+if WITH_JIT
+TESTS += pcre2_jit_test
+noinst_PROGRAMS += pcre2_jit_test
+pcre2_jit_test_SOURCES = src/pcre2_jit_test.c
+pcre2_jit_test_CFLAGS = $(AM_CFLAGS)
+pcre2_jit_test_LDADD =
+if WITH_PCRE2_8
+pcre2_jit_test_LDADD += libpcre2-8.la
+endif # WITH_PCRE2_8
+if WITH_PCRE2_16
+pcre2_jit_test_LDADD += libpcre2-16.la
+endif # WITH_PCRE2_16
+if WITH_PCRE2_32
+pcre2_jit_test_LDADD += libpcre2-32.la
+endif # WITH_PCRE2_32
+if WITH_GCOV
+pcre2_jit_test_CFLAGS += $(GCOV_CFLAGS)
+pcre2_jit_test_LDADD += $(GCOV_LIBS)
+endif # WITH_GCOV
+endif # WITH_JIT
+
+# Build the general pcre2test program.
+
+bin_PROGRAMS += pcre2test
+pcre2test_SOURCES = src/pcre2test.c src/pcre2test_inc.h
+pcre2test_CFLAGS = $(AM_CFLAGS)
+pcre2test_LDADD = $(LIBREADLINE)
+
+if WITH_PCRE2_8
+pcre2test_LDADD += libpcre2-8.la libpcre2-posix.la
+endif # WITH_PCRE2_8
+
+if WITH_PCRE2_16
+pcre2test_LDADD += libpcre2-16.la
+endif # WITH_PCRE2_16
+
+if WITH_PCRE2_32
+pcre2test_LDADD += libpcre2-32.la
+endif # WITH_PCRE2_32
+
+if WITH_VALGRIND
+pcre2test_CFLAGS += $(VALGRIND_CFLAGS)
+endif # WITH_VALGRIND
+
+if WITH_GCOV
+pcre2test_CFLAGS += $(GCOV_CFLAGS)
+pcre2test_LDADD += $(GCOV_LIBS)
+endif # WITH_GCOV
+
+## The main library tests. Each test is a binary plus a script that runs that
+## binary in various ways. We install these test binaries in case folks find it
+## helpful. The two .bat files are for running the tests under Windows.
+
+TESTS += RunTest
+EXTRA_DIST += RunTest.bat
+dist_noinst_SCRIPTS += RunTest
+
+## When the 8-bit library is configured, pcre2grep will have been built.
+
+if WITH_PCRE2_8
+TESTS += RunGrepTest
+EXTRA_DIST += RunGrepTest.bat
+dist_noinst_SCRIPTS += RunGrepTest
+if WITH_EBCDIC
+XFAIL_TESTS += RunGrepTest
+endif # WITH_EBCDIC
+endif # WITH_PCRE2_8
+
+## Distribute all the test data files
+
+EXTRA_DIST += \
+ testdata/grepbinary \
+ testdata/grepfilelist \
+ testdata/grepinput \
+ testdata/grepinput3 \
+ testdata/grepinput8 \
+ testdata/grepinputBad8 \
+ testdata/grepinputBad8_Trail \
+ testdata/grepinputC.bz2 \
+ testdata/grepinputC.gz \
+ testdata/grepinputM \
+ testdata/grepinputUN \
+ testdata/grepinputv \
+ testdata/grepinputx \
+ testdata/greplist \
+ testdata/grepnot.bz2 \
+ testdata/grepoutput \
+ testdata/grepoutput8 \
+ testdata/grepoutputC \
+ testdata/grepoutputCN \
+ testdata/grepoutputCNU \
+ testdata/grepoutputCU \
+ testdata/grepoutputCbz2 \
+ testdata/grepoutputCgz \
+ testdata/grepoutputN \
+ testdata/grepoutputUN \
+ testdata/greppatN4 \
+ testdata/testbtables \
+ testdata/testinput1 \
+ testdata/testinput2 \
+ testdata/testinput3 \
+ testdata/testinput4 \
+ testdata/testinput5 \
+ testdata/testinput6 \
+ testdata/testinput7 \
+ testdata/testinput8 \
+ testdata/testinput9 \
+ testdata/testinput10 \
+ testdata/testinput11 \
+ testdata/testinput12 \
+ testdata/testinput13 \
+ testdata/testinput14 \
+ testdata/testinput15 \
+ testdata/testinput16 \
+ testdata/testinput17 \
+ testdata/testinput18 \
+ testdata/testinput19 \
+ testdata/testinput20 \
+ testdata/testinput21 \
+ testdata/testinput22 \
+ testdata/testinput23 \
+ testdata/testinput24 \
+ testdata/testinput25 \
+ testdata/testinput26 \
+ testdata/testinput27 \
+ testdata/testinput28 \
+ testdata/testinput29 \
+ testdata/testinputheap \
+ testdata/testoutput1 \
+ testdata/testoutput2 \
+ testdata/testoutput3 \
+ testdata/testoutput3A \
+ testdata/testoutput3B \
+ testdata/testoutput4 \
+ testdata/testoutput5 \
+ testdata/testoutput6 \
+ testdata/testoutput7 \
+ testdata/testoutput8-16-2 \
+ testdata/testoutput8-16-4 \
+ testdata/testoutput8-32-4 \
+ testdata/testoutput8-8-2 \
+ testdata/testoutput8-8-3 \
+ testdata/testoutput8-8-4 \
+ testdata/testoutput9 \
+ testdata/testoutput10 \
+ testdata/testoutput11-16 \
+ testdata/testoutput11-32 \
+ testdata/testoutput12-16 \
+ testdata/testoutput12-32 \
+ testdata/testoutput13 \
+ testdata/testoutput14-16 \
+ testdata/testoutput14-32 \
+ testdata/testoutput14-8 \
+ testdata/testoutput15 \
+ testdata/testoutput16 \
+ testdata/testoutput17 \
+ testdata/testoutput18 \
+ testdata/testoutput19 \
+ testdata/testoutput20 \
+ testdata/testoutput21 \
+ testdata/testoutput22-16 \
+ testdata/testoutput22-32 \
+ testdata/testoutput22-8 \
+ testdata/testoutput23 \
+ testdata/testoutput24 \
+ testdata/testoutput25 \
+ testdata/testoutput26 \
+ testdata/testoutput27 \
+ testdata/testoutput28 \
+ testdata/testoutput29 \
+ testdata/testoutputheap-16 \
+ testdata/testoutputheap-32 \
+ testdata/testoutputheap-8 \
+ testdata/valgrind-jit.supp \
+ testdata/wintestinput3 \
+ testdata/wintestoutput3 \
+ perltest.sh
+
+# RunTest and RunGrepTest should clean up after themselves, but just in case
+# they don't, add their working files to CLEANFILES.
+
+CLEANFILES += \
+ testSinput \
+ testSoutput \
+ test3input \
+ test3output \
+ test3outputA \
+ test3outputB \
+ testtry \
+ teststdout \
+ teststderr \
+ teststderrgrep \
+ testtemp1grep \
+ testtemp2grep \
+ testtrygrep \
+ testNinputgrep
+
+testoutput-clean:
+ -rm -rf testoutput8 testoutput8-jit testoutput8-dfa
+ -rm -rf testoutput16 testoutput16-jit testoutput16-dfa
+ -rm -rf testoutput32 testoutput32-jit testoutput32-dfa
+
+CLEAN_LOCAL_TARGETS += testoutput-clean
+PHONY_TARGETS += testoutput-clean
+
+## ------------ End of testing -------------
+
+
+# PCRE2 demonstration program. Not built automatically. The point is that the
+# users should build it themselves. So just distribute the source.
+
+EXTRA_DIST += src/pcre2demo.c
+
+
+# We have .pc files for pkg-config users.
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA =
+
+if WITH_PCRE2_8
+pkgconfig_DATA += libpcre2-8.pc libpcre2-posix.pc
+endif
+
+if WITH_PCRE2_16
+pkgconfig_DATA += libpcre2-16.pc
+endif
+
+if WITH_PCRE2_32
+pkgconfig_DATA += libpcre2-32.pc
+endif
+
+
+# Symbol version template files for use with GNU and Sun ld.
+
+EXTRA_DIST += \
+ src/libpcre2-8.sym.in src/libpcre2-16.sym.in src/libpcre2-32.sym.in \
+ src/libpcre2-posix.sym.in
+
+
+# gcov/lcov code coverage reporting
+#
+# Coverage reporting targets:
+#
+# coverage: Create a coverage report from 'make check'
+# coverage-baseline: Capture baseline coverage information
+# coverage-reset: This zeros the coverage counters only
+# coverage-report: This creates the coverage report only
+# coverage-clean-report: This removes the generated coverage report
+# without cleaning the coverage data itself
+# coverage-clean-data: This removes the captured coverage data without
+# removing the coverage files created at compile time (*.gcno)
+# coverage-clean: This cleans all coverage data including the generated
+# coverage report.
+
+if WITH_GCOV
+COVERAGE_TEST_NAME = $(PACKAGE)
+COVERAGE_NAME = $(PACKAGE)-$(VERSION)
+COVERAGE_OUTPUT_FILE = $(COVERAGE_NAME)-coverage.info
+COVERAGE_OUTPUT_DIR = $(COVERAGE_NAME)-coverage
+COVERAGE_LCOV_EXTRA_FLAGS =
+COVERAGE_GENHTML_EXTRA_FLAGS =
+
+coverage_quiet = $(coverage_quiet_$(V))
+coverage_quiet_ = $(coverage_quiet_$(AM_DEFAULT_VERBOSITY))
+coverage_quiet_0 = --quiet
+
+coverage-check: all
+ -$(MAKE) $(AM_MAKEFLAGS) -k check
+
+coverage-baseline:
+ $(LCOV) $(coverage_quiet) \
+ --directory $(top_builddir) \
+ --output-file "$(COVERAGE_OUTPUT_FILE)" \
+ --capture \
+ --initial
+
+coverage-report:
+ $(LCOV) $(coverage_quiet) \
+ --directory $(top_builddir) \
+ --capture \
+ --output-file "$(COVERAGE_OUTPUT_FILE).tmp" \
+ --test-name "$(COVERAGE_TEST_NAME)" \
+ --no-checksum \
+ --compat-libtool \
+ $(COVERAGE_LCOV_EXTRA_FLAGS)
+ $(LCOV) $(coverage_quiet) \
+ --directory $(top_builddir) \
+ --output-file "$(COVERAGE_OUTPUT_FILE)" \
+ --remove "$(COVERAGE_OUTPUT_FILE).tmp" \
+ "/tmp/*" \
+ "/usr/include/*" \
+ "$(includedir)/*"
+ -@rm -f "$(COVERAGE_OUTPUT_FILE).tmp"
+ LANG=C $(GENHTML) $(coverage_quiet) \
+ --prefix $(top_builddir) \
+ --output-directory "$(COVERAGE_OUTPUT_DIR)" \
+ --title "$(PACKAGE) $(VERSION) Code Coverage Report" \
+ --show-details "$(COVERAGE_OUTPUT_FILE)" \
+ --legend \
+ $(COVERAGE_GENHTML_EXTRA_FLAGS)
+ @echo "Code coverage report written to file://$(abs_builddir)/$(COVERAGE_OUTPUT_DIR)/index.html"
+
+coverage-reset:
+ -$(LCOV) $(coverage_quiet) --zerocounters --directory $(top_builddir)
+
+coverage-clean-report:
+ -rm -f "$(COVERAGE_OUTPUT_FILE)" "$(COVERAGE_OUTPUT_FILE).tmp"
+ -rm -rf "$(COVERAGE_OUTPUT_DIR)"
+
+coverage-clean-data:
+ -find $(top_builddir) -name "*.gcda" -delete
+
+coverage-clean: coverage-reset coverage-clean-report coverage-clean-data
+ -find $(top_builddir) -name "*.gcno" -delete
+
+coverage-distclean: coverage-clean
+
+coverage: coverage-reset coverage-baseline coverage-check coverage-report
+
+CLEAN_LOCAL_TARGETS += coverage-clean
+DISTCLEAN_LOCAL_TARGETS += coverage-distclean
+PHONY_TARGETS += coverage coverage-baseline coverage-check coverage-report coverage-reset coverage-clean-report coverage-clean-data coverage-clean coverage-distclean
+
+else
+
+coverage:
+ @echo "Configuring with --enable-coverage is required to generate code coverage report."
+
+# Without coverage support, still arrange for 'make distclean' to get rid of
+# any coverage files that may have been left from a different configuration.
+
+DISTCLEANFILES += src/*.gcda src/*.gcno
+
+coverage-distclean:
+ rm -rf $(PACKAGE)-$(VERSION)-coverage*
+
+DISTCLEAN_LOCAL_TARGETS += coverage-distclean
+PHONY_TARGETS += coverage-distclean
+
+endif # WITH_GCOV
+
+## CMake support
+
+EXTRA_DIST += \
+ cmake/COPYING-CMAKE-SCRIPTS \
+ cmake/FindEditline.cmake \
+ cmake/FindReadline.cmake \
+ cmake/pcre2-config.cmake.in \
+ cmake/PCRE2CheckVscript.cmake \
+ cmake/PCRE2UseSystemExtensions.cmake \
+ cmake/PCRE2WarningAsError.cmake \
+ src/config-cmake.h.in \
+ CMakeLists.txt
+
+## Set the special make and Automake targets. We could very easily simply
+## redefine these targets to append prerequisites to them, rather than
+## collecting the prerequisites in variables. However, there is an annoying
+## Automake behaviour where it emits a warning if a target has prerequisites
+## appended in a conditional block.
+
+clean-local: $(CLEAN_LOCAL_TARGETS)
+distclean-local: $(DISTCLEAN_LOCAL_TARGETS)
+.PHONY: $(PHONY_TARGETS)
+
+## end Makefile.am
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..756f314
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,4199 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+TESTS = $(am__EXEEXT_6) $(am__EXEEXT_7) RunTest $(am__append_43)
+bin_PROGRAMS = $(am__EXEEXT_1) pcre2test$(EXEEXT)
+noinst_PROGRAMS = $(am__EXEEXT_2) $(am__EXEEXT_3) $(am__EXEEXT_4) \
+ $(am__EXEEXT_5) $(am__EXEEXT_6) $(am__EXEEXT_7)
+@WITH_REBUILD_CHARTABLES_TRUE@am__append_1 = pcre2_dftables
+@WITH_PCRE2_8_TRUE@am__append_2 = libpcre2-8.la
+@WITH_PCRE2_16_TRUE@am__append_3 = libpcre2-16.la
+@WITH_PCRE2_32_TRUE@am__append_4 = libpcre2-32.la
+@WITH_PCRE2_8_TRUE@@WITH_VALGRIND_TRUE@am__append_5 = $(VALGRIND_CFLAGS)
+@WITH_PCRE2_16_TRUE@@WITH_VALGRIND_TRUE@am__append_6 = $(VALGRIND_CFLAGS)
+@WITH_PCRE2_32_TRUE@@WITH_VALGRIND_TRUE@am__append_7 = $(VALGRIND_CFLAGS)
+@WITH_GCOV_TRUE@@WITH_PCRE2_8_TRUE@am__append_8 = $(GCOV_CFLAGS)
+@WITH_GCOV_TRUE@@WITH_PCRE2_16_TRUE@am__append_9 = $(GCOV_CFLAGS)
+@WITH_GCOV_TRUE@@WITH_PCRE2_32_TRUE@am__append_10 = $(GCOV_CFLAGS)
+@WITH_PCRE2_8_TRUE@am__append_11 = libpcre2-posix.la
+@WITH_GCOV_TRUE@@WITH_PCRE2_8_TRUE@am__append_12 = $(GCOV_CFLAGS)
+@WITH_PCRE2_8_TRUE@am__append_13 = pcre2grep
+@WITH_GCOV_TRUE@@WITH_PCRE2_8_TRUE@am__append_14 = $(GCOV_CFLAGS)
+@WITH_GCOV_TRUE@@WITH_PCRE2_8_TRUE@am__append_15 = $(GCOV_LIBS)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@am__append_16 = .libs/libpcre2-fuzzsupport.a
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@am__append_17 = pcre2fuzzcheck-8
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_GCOV_TRUE@@WITH_PCRE2_8_TRUE@am__append_18 = $(GCOV_CFLAGS)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_GCOV_TRUE@@WITH_PCRE2_8_TRUE@am__append_19 = $(GCOV_LIBS)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@am__append_20 = .libs/libpcre2-fuzzsupport-16.a
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@am__append_21 = pcre2fuzzcheck-16
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_GCOV_TRUE@@WITH_PCRE2_16_TRUE@am__append_22 = $(GCOV_CFLAGS)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_GCOV_TRUE@@WITH_PCRE2_16_TRUE@am__append_23 = $(GCOV_LIBS)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@am__append_24 = .libs/libpcre2-fuzzsupport-32.a
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@am__append_25 = pcre2fuzzcheck-32
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_GCOV_TRUE@@WITH_PCRE2_32_TRUE@am__append_26 = $(GCOV_CFLAGS)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_GCOV_TRUE@@WITH_PCRE2_32_TRUE@am__append_27 = $(GCOV_LIBS)
+@WITH_PCRE2_8_TRUE@am__append_28 = pcre2posix_test
+@WITH_PCRE2_8_TRUE@am__append_29 = pcre2posix_test
+@WITH_JIT_TRUE@am__append_30 = pcre2_jit_test
+@WITH_JIT_TRUE@am__append_31 = pcre2_jit_test
+@WITH_JIT_TRUE@@WITH_PCRE2_8_TRUE@am__append_32 = libpcre2-8.la
+@WITH_JIT_TRUE@@WITH_PCRE2_16_TRUE@am__append_33 = libpcre2-16.la
+@WITH_JIT_TRUE@@WITH_PCRE2_32_TRUE@am__append_34 = libpcre2-32.la
+@WITH_GCOV_TRUE@@WITH_JIT_TRUE@am__append_35 = $(GCOV_CFLAGS)
+@WITH_GCOV_TRUE@@WITH_JIT_TRUE@am__append_36 = $(GCOV_LIBS)
+@WITH_PCRE2_8_TRUE@am__append_37 = libpcre2-8.la libpcre2-posix.la
+@WITH_PCRE2_16_TRUE@am__append_38 = libpcre2-16.la
+@WITH_PCRE2_32_TRUE@am__append_39 = libpcre2-32.la
+@WITH_VALGRIND_TRUE@am__append_40 = $(VALGRIND_CFLAGS)
+@WITH_GCOV_TRUE@am__append_41 = $(GCOV_CFLAGS)
+@WITH_GCOV_TRUE@am__append_42 = $(GCOV_LIBS)
+@WITH_PCRE2_8_TRUE@am__append_43 = RunGrepTest
+@WITH_PCRE2_8_TRUE@am__append_44 = RunGrepTest.bat
+@WITH_PCRE2_8_TRUE@am__append_45 = RunGrepTest
+@WITH_EBCDIC_TRUE@@WITH_PCRE2_8_TRUE@am__append_46 = RunGrepTest
+@WITH_PCRE2_8_TRUE@am__append_47 = libpcre2-8.pc libpcre2-posix.pc
+@WITH_PCRE2_16_TRUE@am__append_48 = libpcre2-16.pc
+@WITH_PCRE2_32_TRUE@am__append_49 = libpcre2-32.pc
+@WITH_GCOV_TRUE@am__append_50 = coverage-clean
+@WITH_GCOV_TRUE@am__append_51 = coverage-distclean
+@WITH_GCOV_TRUE@am__append_52 = coverage coverage-baseline coverage-check coverage-report coverage-reset coverage-clean-report coverage-clean-data coverage-clean coverage-distclean
+
+# Without coverage support, still arrange for 'make distclean' to get rid of
+# any coverage files that may have been left from a different configuration.
+@WITH_GCOV_FALSE@am__append_53 = src/*.gcda src/*.gcno
+@WITH_GCOV_FALSE@am__append_54 = coverage-distclean
+@WITH_GCOV_FALSE@am__append_55 = coverage-distclean
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_pthread.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/pcre2_check_vscript.m4 \
+ $(top_srcdir)/m4/pcre2_visibility.m4 \
+ $(top_srcdir)/m4/pcre2_zos.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
+ $(am__configure_deps) $(am__dist_noinst_SCRIPTS_DIST) \
+ $(dist_doc_DATA) $(dist_html_DATA) $(include_HEADERS) \
+ $(am__DIST_COMMON)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES = libpcre2-8.pc libpcre2-16.pc libpcre2-32.pc \
+ libpcre2-posix.pc pcre2-config src/pcre2.h src/libpcre2-8.sym \
+ src/libpcre2-16.sym src/libpcre2-32.sym src/libpcre2-posix.sym
+CONFIG_CLEAN_VPATH_FILES =
+@WITH_PCRE2_8_TRUE@am__EXEEXT_1 = pcre2grep$(EXEEXT)
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" \
+ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \
+ "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(docdir)" \
+ "$(DESTDIR)$(htmldir)" "$(DESTDIR)$(pkgconfigdir)" \
+ "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)"
+@WITH_REBUILD_CHARTABLES_TRUE@am__EXEEXT_2 = pcre2_dftables$(EXEEXT)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@am__EXEEXT_3 = pcre2fuzzcheck-8$(EXEEXT)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@am__EXEEXT_4 = pcre2fuzzcheck-16$(EXEEXT)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@am__EXEEXT_5 = pcre2fuzzcheck-32$(EXEEXT)
+@WITH_PCRE2_8_TRUE@am__EXEEXT_6 = pcre2posix_test$(EXEEXT)
+@WITH_JIT_TRUE@am__EXEEXT_7 = pcre2_jit_test$(EXEEXT)
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
+LIBRARIES = $(noinst_LIBRARIES)
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+LTLIBRARIES = $(lib_LTLIBRARIES)
+ARFLAGS = cru
+AM_V_AR = $(am__v_AR_@AM_V@)
+am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@)
+am__v_AR_0 = @echo " AR " $@;
+am__v_AR_1 =
+_libs_libpcre2_fuzzsupport_16_a_AR = $(AR) $(ARFLAGS)
+_libs_libpcre2_fuzzsupport_16_a_DEPENDENCIES =
+am___libs_libpcre2_fuzzsupport_16_a_SOURCES_DIST = \
+ src/pcre2_fuzzsupport.c
+am__dirstamp = $(am__leading_dot)dirstamp
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@am__libs_libpcre2_fuzzsupport_16_a_OBJECTS = src/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.$(OBJEXT)
+_libs_libpcre2_fuzzsupport_16_a_OBJECTS = \
+ $(am__libs_libpcre2_fuzzsupport_16_a_OBJECTS)
+_libs_libpcre2_fuzzsupport_32_a_AR = $(AR) $(ARFLAGS)
+_libs_libpcre2_fuzzsupport_32_a_DEPENDENCIES =
+am___libs_libpcre2_fuzzsupport_32_a_SOURCES_DIST = \
+ src/pcre2_fuzzsupport.c
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@am__libs_libpcre2_fuzzsupport_32_a_OBJECTS = src/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.$(OBJEXT)
+_libs_libpcre2_fuzzsupport_32_a_OBJECTS = \
+ $(am__libs_libpcre2_fuzzsupport_32_a_OBJECTS)
+_libs_libpcre2_fuzzsupport_a_AR = $(AR) $(ARFLAGS)
+_libs_libpcre2_fuzzsupport_a_DEPENDENCIES =
+am___libs_libpcre2_fuzzsupport_a_SOURCES_DIST = \
+ src/pcre2_fuzzsupport.c
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@am__libs_libpcre2_fuzzsupport_a_OBJECTS = src/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.$(OBJEXT)
+_libs_libpcre2_fuzzsupport_a_OBJECTS = \
+ $(am__libs_libpcre2_fuzzsupport_a_OBJECTS)
+libpcre2_16_la_DEPENDENCIES =
+am__libpcre2_16_la_SOURCES_DIST = src/pcre2_auto_possess.c \
+ src/pcre2_chkdint.c src/pcre2_compile.c src/pcre2_compile.h \
+ src/pcre2_compile_cgroup.c src/pcre2_compile_class.c \
+ src/pcre2_config.c src/pcre2_context.c src/pcre2_convert.c \
+ src/pcre2_dfa_match.c src/pcre2_error.c src/pcre2_extuni.c \
+ src/pcre2_find_bracket.c src/pcre2_internal.h \
+ src/pcre2_intmodedep.h src/pcre2_jit_char_inc.h \
+ src/pcre2_jit_compile.c src/pcre2_jit_match_inc.h \
+ src/pcre2_jit_misc_inc.h src/pcre2_jit_simd_inc.h \
+ src/pcre2_maketables.c src/pcre2_match.c \
+ src/pcre2_match_data.c src/pcre2_match_next.c \
+ src/pcre2_newline.c src/pcre2_ord2utf.c \
+ src/pcre2_pattern_info.c src/pcre2_printint_inc.h \
+ src/pcre2_script_run.c src/pcre2_serialize.c \
+ src/pcre2_string_utils.c src/pcre2_study.c \
+ src/pcre2_substitute.c src/pcre2_substring.c \
+ src/pcre2_tables.c src/pcre2_ucd.c src/pcre2_ucp.h \
+ src/pcre2_ucptables_inc.h src/pcre2_util.h \
+ src/pcre2_valid_utf.c src/pcre2_xclass.c
+am__objects_1 = src/libpcre2_16_la-pcre2_auto_possess.lo \
+ src/libpcre2_16_la-pcre2_chkdint.lo \
+ src/libpcre2_16_la-pcre2_compile.lo \
+ src/libpcre2_16_la-pcre2_compile_cgroup.lo \
+ src/libpcre2_16_la-pcre2_compile_class.lo \
+ src/libpcre2_16_la-pcre2_config.lo \
+ src/libpcre2_16_la-pcre2_context.lo \
+ src/libpcre2_16_la-pcre2_convert.lo \
+ src/libpcre2_16_la-pcre2_dfa_match.lo \
+ src/libpcre2_16_la-pcre2_error.lo \
+ src/libpcre2_16_la-pcre2_extuni.lo \
+ src/libpcre2_16_la-pcre2_find_bracket.lo \
+ src/libpcre2_16_la-pcre2_jit_compile.lo \
+ src/libpcre2_16_la-pcre2_maketables.lo \
+ src/libpcre2_16_la-pcre2_match.lo \
+ src/libpcre2_16_la-pcre2_match_data.lo \
+ src/libpcre2_16_la-pcre2_match_next.lo \
+ src/libpcre2_16_la-pcre2_newline.lo \
+ src/libpcre2_16_la-pcre2_ord2utf.lo \
+ src/libpcre2_16_la-pcre2_pattern_info.lo \
+ src/libpcre2_16_la-pcre2_script_run.lo \
+ src/libpcre2_16_la-pcre2_serialize.lo \
+ src/libpcre2_16_la-pcre2_string_utils.lo \
+ src/libpcre2_16_la-pcre2_study.lo \
+ src/libpcre2_16_la-pcre2_substitute.lo \
+ src/libpcre2_16_la-pcre2_substring.lo \
+ src/libpcre2_16_la-pcre2_tables.lo \
+ src/libpcre2_16_la-pcre2_ucd.lo \
+ src/libpcre2_16_la-pcre2_valid_utf.lo \
+ src/libpcre2_16_la-pcre2_xclass.lo
+@WITH_PCRE2_16_TRUE@am_libpcre2_16_la_OBJECTS = $(am__objects_1)
+am__objects_2 = src/libpcre2_16_la-pcre2_chartables.lo
+@WITH_PCRE2_16_TRUE@nodist_libpcre2_16_la_OBJECTS = $(am__objects_2)
+libpcre2_16_la_OBJECTS = $(am_libpcre2_16_la_OBJECTS) \
+ $(nodist_libpcre2_16_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libpcre2_16_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libpcre2_16_la_CFLAGS) $(CFLAGS) $(libpcre2_16_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@WITH_PCRE2_16_TRUE@am_libpcre2_16_la_rpath = -rpath $(libdir)
+libpcre2_32_la_DEPENDENCIES =
+am__libpcre2_32_la_SOURCES_DIST = src/pcre2_auto_possess.c \
+ src/pcre2_chkdint.c src/pcre2_compile.c src/pcre2_compile.h \
+ src/pcre2_compile_cgroup.c src/pcre2_compile_class.c \
+ src/pcre2_config.c src/pcre2_context.c src/pcre2_convert.c \
+ src/pcre2_dfa_match.c src/pcre2_error.c src/pcre2_extuni.c \
+ src/pcre2_find_bracket.c src/pcre2_internal.h \
+ src/pcre2_intmodedep.h src/pcre2_jit_char_inc.h \
+ src/pcre2_jit_compile.c src/pcre2_jit_match_inc.h \
+ src/pcre2_jit_misc_inc.h src/pcre2_jit_simd_inc.h \
+ src/pcre2_maketables.c src/pcre2_match.c \
+ src/pcre2_match_data.c src/pcre2_match_next.c \
+ src/pcre2_newline.c src/pcre2_ord2utf.c \
+ src/pcre2_pattern_info.c src/pcre2_printint_inc.h \
+ src/pcre2_script_run.c src/pcre2_serialize.c \
+ src/pcre2_string_utils.c src/pcre2_study.c \
+ src/pcre2_substitute.c src/pcre2_substring.c \
+ src/pcre2_tables.c src/pcre2_ucd.c src/pcre2_ucp.h \
+ src/pcre2_ucptables_inc.h src/pcre2_util.h \
+ src/pcre2_valid_utf.c src/pcre2_xclass.c
+am__objects_3 = src/libpcre2_32_la-pcre2_auto_possess.lo \
+ src/libpcre2_32_la-pcre2_chkdint.lo \
+ src/libpcre2_32_la-pcre2_compile.lo \
+ src/libpcre2_32_la-pcre2_compile_cgroup.lo \
+ src/libpcre2_32_la-pcre2_compile_class.lo \
+ src/libpcre2_32_la-pcre2_config.lo \
+ src/libpcre2_32_la-pcre2_context.lo \
+ src/libpcre2_32_la-pcre2_convert.lo \
+ src/libpcre2_32_la-pcre2_dfa_match.lo \
+ src/libpcre2_32_la-pcre2_error.lo \
+ src/libpcre2_32_la-pcre2_extuni.lo \
+ src/libpcre2_32_la-pcre2_find_bracket.lo \
+ src/libpcre2_32_la-pcre2_jit_compile.lo \
+ src/libpcre2_32_la-pcre2_maketables.lo \
+ src/libpcre2_32_la-pcre2_match.lo \
+ src/libpcre2_32_la-pcre2_match_data.lo \
+ src/libpcre2_32_la-pcre2_match_next.lo \
+ src/libpcre2_32_la-pcre2_newline.lo \
+ src/libpcre2_32_la-pcre2_ord2utf.lo \
+ src/libpcre2_32_la-pcre2_pattern_info.lo \
+ src/libpcre2_32_la-pcre2_script_run.lo \
+ src/libpcre2_32_la-pcre2_serialize.lo \
+ src/libpcre2_32_la-pcre2_string_utils.lo \
+ src/libpcre2_32_la-pcre2_study.lo \
+ src/libpcre2_32_la-pcre2_substitute.lo \
+ src/libpcre2_32_la-pcre2_substring.lo \
+ src/libpcre2_32_la-pcre2_tables.lo \
+ src/libpcre2_32_la-pcre2_ucd.lo \
+ src/libpcre2_32_la-pcre2_valid_utf.lo \
+ src/libpcre2_32_la-pcre2_xclass.lo
+@WITH_PCRE2_32_TRUE@am_libpcre2_32_la_OBJECTS = $(am__objects_3)
+am__objects_4 = src/libpcre2_32_la-pcre2_chartables.lo
+@WITH_PCRE2_32_TRUE@nodist_libpcre2_32_la_OBJECTS = $(am__objects_4)
+libpcre2_32_la_OBJECTS = $(am_libpcre2_32_la_OBJECTS) \
+ $(nodist_libpcre2_32_la_OBJECTS)
+libpcre2_32_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libpcre2_32_la_CFLAGS) $(CFLAGS) $(libpcre2_32_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@WITH_PCRE2_32_TRUE@am_libpcre2_32_la_rpath = -rpath $(libdir)
+libpcre2_8_la_DEPENDENCIES =
+am__libpcre2_8_la_SOURCES_DIST = src/pcre2_auto_possess.c \
+ src/pcre2_chkdint.c src/pcre2_compile.c src/pcre2_compile.h \
+ src/pcre2_compile_cgroup.c src/pcre2_compile_class.c \
+ src/pcre2_config.c src/pcre2_context.c src/pcre2_convert.c \
+ src/pcre2_dfa_match.c src/pcre2_error.c src/pcre2_extuni.c \
+ src/pcre2_find_bracket.c src/pcre2_internal.h \
+ src/pcre2_intmodedep.h src/pcre2_jit_char_inc.h \
+ src/pcre2_jit_compile.c src/pcre2_jit_match_inc.h \
+ src/pcre2_jit_misc_inc.h src/pcre2_jit_simd_inc.h \
+ src/pcre2_maketables.c src/pcre2_match.c \
+ src/pcre2_match_data.c src/pcre2_match_next.c \
+ src/pcre2_newline.c src/pcre2_ord2utf.c \
+ src/pcre2_pattern_info.c src/pcre2_printint_inc.h \
+ src/pcre2_script_run.c src/pcre2_serialize.c \
+ src/pcre2_string_utils.c src/pcre2_study.c \
+ src/pcre2_substitute.c src/pcre2_substring.c \
+ src/pcre2_tables.c src/pcre2_ucd.c src/pcre2_ucp.h \
+ src/pcre2_ucptables_inc.h src/pcre2_util.h \
+ src/pcre2_valid_utf.c src/pcre2_xclass.c
+am__objects_5 = src/libpcre2_8_la-pcre2_auto_possess.lo \
+ src/libpcre2_8_la-pcre2_chkdint.lo \
+ src/libpcre2_8_la-pcre2_compile.lo \
+ src/libpcre2_8_la-pcre2_compile_cgroup.lo \
+ src/libpcre2_8_la-pcre2_compile_class.lo \
+ src/libpcre2_8_la-pcre2_config.lo \
+ src/libpcre2_8_la-pcre2_context.lo \
+ src/libpcre2_8_la-pcre2_convert.lo \
+ src/libpcre2_8_la-pcre2_dfa_match.lo \
+ src/libpcre2_8_la-pcre2_error.lo \
+ src/libpcre2_8_la-pcre2_extuni.lo \
+ src/libpcre2_8_la-pcre2_find_bracket.lo \
+ src/libpcre2_8_la-pcre2_jit_compile.lo \
+ src/libpcre2_8_la-pcre2_maketables.lo \
+ src/libpcre2_8_la-pcre2_match.lo \
+ src/libpcre2_8_la-pcre2_match_data.lo \
+ src/libpcre2_8_la-pcre2_match_next.lo \
+ src/libpcre2_8_la-pcre2_newline.lo \
+ src/libpcre2_8_la-pcre2_ord2utf.lo \
+ src/libpcre2_8_la-pcre2_pattern_info.lo \
+ src/libpcre2_8_la-pcre2_script_run.lo \
+ src/libpcre2_8_la-pcre2_serialize.lo \
+ src/libpcre2_8_la-pcre2_string_utils.lo \
+ src/libpcre2_8_la-pcre2_study.lo \
+ src/libpcre2_8_la-pcre2_substitute.lo \
+ src/libpcre2_8_la-pcre2_substring.lo \
+ src/libpcre2_8_la-pcre2_tables.lo \
+ src/libpcre2_8_la-pcre2_ucd.lo \
+ src/libpcre2_8_la-pcre2_valid_utf.lo \
+ src/libpcre2_8_la-pcre2_xclass.lo
+@WITH_PCRE2_8_TRUE@am_libpcre2_8_la_OBJECTS = $(am__objects_5)
+am__objects_6 = src/libpcre2_8_la-pcre2_chartables.lo
+@WITH_PCRE2_8_TRUE@nodist_libpcre2_8_la_OBJECTS = $(am__objects_6)
+libpcre2_8_la_OBJECTS = $(am_libpcre2_8_la_OBJECTS) \
+ $(nodist_libpcre2_8_la_OBJECTS)
+libpcre2_8_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libpcre2_8_la_CFLAGS) \
+ $(CFLAGS) $(libpcre2_8_la_LDFLAGS) $(LDFLAGS) -o $@
+@WITH_PCRE2_8_TRUE@am_libpcre2_8_la_rpath = -rpath $(libdir)
+@WITH_PCRE2_8_TRUE@libpcre2_posix_la_DEPENDENCIES = libpcre2-8.la
+am__libpcre2_posix_la_SOURCES_DIST = src/pcre2posix.c
+@WITH_PCRE2_8_TRUE@am_libpcre2_posix_la_OBJECTS = \
+@WITH_PCRE2_8_TRUE@ src/libpcre2_posix_la-pcre2posix.lo
+libpcre2_posix_la_OBJECTS = $(am_libpcre2_posix_la_OBJECTS)
+libpcre2_posix_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libpcre2_posix_la_CFLAGS) $(CFLAGS) \
+ $(libpcre2_posix_la_LDFLAGS) $(LDFLAGS) -o $@
+@WITH_PCRE2_8_TRUE@am_libpcre2_posix_la_rpath = -rpath $(libdir)
+am__pcre2_dftables_SOURCES_DIST = src/pcre2_dftables.c
+@WITH_REBUILD_CHARTABLES_TRUE@am_pcre2_dftables_OBJECTS = \
+@WITH_REBUILD_CHARTABLES_TRUE@ src/pcre2_dftables.$(OBJEXT)
+pcre2_dftables_OBJECTS = $(am_pcre2_dftables_OBJECTS)
+pcre2_dftables_LDADD = $(LDADD)
+am__pcre2_jit_test_SOURCES_DIST = src/pcre2_jit_test.c
+@WITH_JIT_TRUE@am_pcre2_jit_test_OBJECTS = \
+@WITH_JIT_TRUE@ src/pcre2_jit_test-pcre2_jit_test.$(OBJEXT)
+pcre2_jit_test_OBJECTS = $(am_pcre2_jit_test_OBJECTS)
+am__DEPENDENCIES_1 =
+@WITH_GCOV_TRUE@@WITH_JIT_TRUE@am__DEPENDENCIES_2 = \
+@WITH_GCOV_TRUE@@WITH_JIT_TRUE@ $(am__DEPENDENCIES_1)
+@WITH_JIT_TRUE@pcre2_jit_test_DEPENDENCIES = $(am__append_32) \
+@WITH_JIT_TRUE@ $(am__append_33) $(am__append_34) \
+@WITH_JIT_TRUE@ $(am__DEPENDENCIES_2)
+pcre2_jit_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(pcre2_jit_test_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \
+ $@
+am__pcre2fuzzcheck_16_SOURCES_DIST = src/pcre2_fuzzsupport.c
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@am_pcre2fuzzcheck_16_OBJECTS = src/pcre2fuzzcheck_16-pcre2_fuzzsupport.$(OBJEXT)
+pcre2fuzzcheck_16_OBJECTS = $(am_pcre2fuzzcheck_16_OBJECTS)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_GCOV_TRUE@@WITH_PCRE2_16_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@pcre2fuzzcheck_16_DEPENDENCIES = \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@ libpcre2-16.la \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@ $(am__DEPENDENCIES_3)
+pcre2fuzzcheck_16_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(pcre2fuzzcheck_16_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+am__pcre2fuzzcheck_32_SOURCES_DIST = src/pcre2_fuzzsupport.c
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@am_pcre2fuzzcheck_32_OBJECTS = src/pcre2fuzzcheck_32-pcre2_fuzzsupport.$(OBJEXT)
+pcre2fuzzcheck_32_OBJECTS = $(am_pcre2fuzzcheck_32_OBJECTS)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_GCOV_TRUE@@WITH_PCRE2_32_TRUE@am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@pcre2fuzzcheck_32_DEPENDENCIES = \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@ libpcre2-32.la \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@ $(am__DEPENDENCIES_4)
+pcre2fuzzcheck_32_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(pcre2fuzzcheck_32_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+am__pcre2fuzzcheck_8_SOURCES_DIST = src/pcre2_fuzzsupport.c
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@am_pcre2fuzzcheck_8_OBJECTS = src/pcre2fuzzcheck_8-pcre2_fuzzsupport.$(OBJEXT)
+pcre2fuzzcheck_8_OBJECTS = $(am_pcre2fuzzcheck_8_OBJECTS)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_GCOV_TRUE@@WITH_PCRE2_8_TRUE@am__DEPENDENCIES_5 = $(am__DEPENDENCIES_1)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@pcre2fuzzcheck_8_DEPENDENCIES = \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@ libpcre2-8.la \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@ $(am__DEPENDENCIES_5)
+pcre2fuzzcheck_8_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(pcre2fuzzcheck_8_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+am__pcre2grep_SOURCES_DIST = src/pcre2grep.c
+@WITH_PCRE2_8_TRUE@am_pcre2grep_OBJECTS = \
+@WITH_PCRE2_8_TRUE@ src/pcre2grep-pcre2grep.$(OBJEXT)
+pcre2grep_OBJECTS = $(am_pcre2grep_OBJECTS)
+@WITH_GCOV_TRUE@@WITH_PCRE2_8_TRUE@am__DEPENDENCIES_6 = \
+@WITH_GCOV_TRUE@@WITH_PCRE2_8_TRUE@ $(am__DEPENDENCIES_1)
+@WITH_PCRE2_8_TRUE@pcre2grep_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+@WITH_PCRE2_8_TRUE@ $(am__DEPENDENCIES_1) libpcre2-8.la \
+@WITH_PCRE2_8_TRUE@ $(am__DEPENDENCIES_6)
+pcre2grep_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(pcre2grep_CFLAGS) \
+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+am__pcre2posix_test_SOURCES_DIST = src/pcre2posix_test.c
+@WITH_PCRE2_8_TRUE@am_pcre2posix_test_OBJECTS = src/pcre2posix_test-pcre2posix_test.$(OBJEXT)
+pcre2posix_test_OBJECTS = $(am_pcre2posix_test_OBJECTS)
+@WITH_PCRE2_8_TRUE@pcre2posix_test_DEPENDENCIES = libpcre2-posix.la \
+@WITH_PCRE2_8_TRUE@ libpcre2-8.la
+pcre2posix_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(pcre2posix_test_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+am_pcre2test_OBJECTS = src/pcre2test-pcre2test.$(OBJEXT)
+pcre2test_OBJECTS = $(am_pcre2test_OBJECTS)
+@WITH_GCOV_TRUE@am__DEPENDENCIES_7 = $(am__DEPENDENCIES_1)
+pcre2test_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__append_37) \
+ $(am__append_38) $(am__append_39) $(am__DEPENDENCIES_7)
+pcre2test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(pcre2test_CFLAGS) \
+ $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+am__dist_noinst_SCRIPTS_DIST = RunTest RunGrepTest
+SCRIPTS = $(bin_SCRIPTS) $(dist_noinst_SCRIPTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.Po \
+ src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.Po \
+ src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.Po \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_auto_possess.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_chartables.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_chkdint.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_compile.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_compile_cgroup.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_compile_class.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_config.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_context.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_convert.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_dfa_match.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_error.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_extuni.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_find_bracket.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_jit_compile.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_maketables.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_match.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_match_data.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_match_next.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_newline.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_ord2utf.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_pattern_info.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_script_run.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_serialize.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_string_utils.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_study.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_substitute.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_substring.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_tables.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_ucd.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_valid_utf.Plo \
+ src/$(DEPDIR)/libpcre2_16_la-pcre2_xclass.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_auto_possess.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_chartables.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_chkdint.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_compile.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_compile_cgroup.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_compile_class.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_config.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_context.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_convert.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_dfa_match.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_error.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_extuni.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_find_bracket.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_jit_compile.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_maketables.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_match.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_match_data.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_match_next.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_newline.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_ord2utf.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_pattern_info.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_script_run.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_serialize.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_string_utils.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_study.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_substitute.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_substring.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_tables.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_ucd.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_valid_utf.Plo \
+ src/$(DEPDIR)/libpcre2_32_la-pcre2_xclass.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_auto_possess.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_chartables.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_chkdint.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_compile.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_compile_cgroup.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_compile_class.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_config.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_context.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_convert.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_dfa_match.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_error.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_extuni.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_find_bracket.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_jit_compile.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_maketables.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_match.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_match_data.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_match_next.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_newline.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_ord2utf.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_pattern_info.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_script_run.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_serialize.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_string_utils.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_study.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_substitute.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_substring.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_tables.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_ucd.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_valid_utf.Plo \
+ src/$(DEPDIR)/libpcre2_8_la-pcre2_xclass.Plo \
+ src/$(DEPDIR)/libpcre2_posix_la-pcre2posix.Plo \
+ src/$(DEPDIR)/pcre2_dftables.Po \
+ src/$(DEPDIR)/pcre2_jit_test-pcre2_jit_test.Po \
+ src/$(DEPDIR)/pcre2fuzzcheck_16-pcre2_fuzzsupport.Po \
+ src/$(DEPDIR)/pcre2fuzzcheck_32-pcre2_fuzzsupport.Po \
+ src/$(DEPDIR)/pcre2fuzzcheck_8-pcre2_fuzzsupport.Po \
+ src/$(DEPDIR)/pcre2grep-pcre2grep.Po \
+ src/$(DEPDIR)/pcre2posix_test-pcre2posix_test.Po \
+ src/$(DEPDIR)/pcre2test-pcre2test.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(_libs_libpcre2_fuzzsupport_16_a_SOURCES) \
+ $(_libs_libpcre2_fuzzsupport_32_a_SOURCES) \
+ $(_libs_libpcre2_fuzzsupport_a_SOURCES) \
+ $(libpcre2_16_la_SOURCES) $(nodist_libpcre2_16_la_SOURCES) \
+ $(libpcre2_32_la_SOURCES) $(nodist_libpcre2_32_la_SOURCES) \
+ $(libpcre2_8_la_SOURCES) $(nodist_libpcre2_8_la_SOURCES) \
+ $(libpcre2_posix_la_SOURCES) $(pcre2_dftables_SOURCES) \
+ $(pcre2_jit_test_SOURCES) $(pcre2fuzzcheck_16_SOURCES) \
+ $(pcre2fuzzcheck_32_SOURCES) $(pcre2fuzzcheck_8_SOURCES) \
+ $(pcre2grep_SOURCES) $(pcre2posix_test_SOURCES) \
+ $(pcre2test_SOURCES)
+DIST_SOURCES = $(am___libs_libpcre2_fuzzsupport_16_a_SOURCES_DIST) \
+ $(am___libs_libpcre2_fuzzsupport_32_a_SOURCES_DIST) \
+ $(am___libs_libpcre2_fuzzsupport_a_SOURCES_DIST) \
+ $(am__libpcre2_16_la_SOURCES_DIST) \
+ $(am__libpcre2_32_la_SOURCES_DIST) \
+ $(am__libpcre2_8_la_SOURCES_DIST) \
+ $(am__libpcre2_posix_la_SOURCES_DIST) \
+ $(am__pcre2_dftables_SOURCES_DIST) \
+ $(am__pcre2_jit_test_SOURCES_DIST) \
+ $(am__pcre2fuzzcheck_16_SOURCES_DIST) \
+ $(am__pcre2fuzzcheck_32_SOURCES_DIST) \
+ $(am__pcre2fuzzcheck_8_SOURCES_DIST) \
+ $(am__pcre2grep_SOURCES_DIST) \
+ $(am__pcre2posix_test_SOURCES_DIST) $(pcre2test_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+man1dir = $(mandir)/man1
+man3dir = $(mandir)/man3
+NROFF = nroff
+MANS = $(dist_man_MANS)
+DATA = $(dist_doc_DATA) $(dist_html_DATA) $(pkgconfig_DATA)
+HEADERS = $(include_HEADERS) $(nodist_include_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+AM_RECURSIVE_TARGETS = cscope check recheck
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red='[0;31m'; \
+ grn='[0;32m'; \
+ lgn='[1;32m'; \
+ blu='[1;34m'; \
+ mgn='[0;35m'; \
+ brg='[1m'; \
+ std='[m'; \
+ fi; \
+}
+am__recheck_rx = ^[ ]*:recheck:[ ]*
+am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
+am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+ recheck = 1; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ { \
+ if ((getline line2 < ($$0 ".log")) < 0) \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+ { \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+ { \
+ break; \
+ } \
+ }; \
+ if (recheck) \
+ print $$0; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+ print "fatal: making $@: " msg | "cat >&2"; \
+ exit 1; \
+} \
+function rst_section(header) \
+{ \
+ print header; \
+ len = length(header); \
+ for (i = 1; i <= len; i = i + 1) \
+ printf "="; \
+ printf "\n\n"; \
+} \
+{ \
+ copy_in_global_log = 1; \
+ global_test_result = "RUN"; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".trs"); \
+ if (line ~ /$(am__global_test_result_rx)/) \
+ { \
+ sub("$(am__global_test_result_rx)", "", line); \
+ sub("[ ]*$$", "", line); \
+ global_test_result = line; \
+ } \
+ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+ copy_in_global_log = 0; \
+ }; \
+ if (copy_in_global_log) \
+ { \
+ rst_section(global_test_result ": " $$0); \
+ while ((rc = (getline line < ($$0 ".log"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".log"); \
+ print line; \
+ }; \
+ printf "\n"; \
+ }; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+ --color-tests "$$am__color_tests" \
+ --enable-hard-errors "$$am__enable_hard_errors" \
+ --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test. Creates the
+# directory for the log if needed. Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log. Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup); \
+$(am__vpath_adj_setup) $(am__vpath_adj) \
+$(am__tty_colors); \
+srcdir=$(srcdir); export srcdir; \
+case "$@" in \
+ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
+ *) am__odir=.;; \
+esac; \
+test "x$$am__odir" = x"." || test -d "$$am__odir" \
+ || $(MKDIR_P) "$$am__odir" || exit $$?; \
+if test -f "./$$f"; then dir=./; \
+elif test -f "$$f"; then dir=; \
+else dir="$(srcdir)/"; fi; \
+tst=$$dir$$f; log='$@'; \
+if test -n '$(DISABLE_HARD_ERRORS)'; then \
+ am__enable_hard_errors=no; \
+else \
+ am__enable_hard_errors=yes; \
+fi; \
+case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
+ am__expect_failure=yes;; \
+ *) \
+ am__expect_failure=no;; \
+esac; \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed). The result is saved in the shell variable
+# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+ bases='$(TEST_LOGS)'; \
+ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+ bases=`echo $$bases`
+AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)'
+RECHECK_LOGS = $(TEST_LOGS)
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+ $(TEST_LOG_FLAGS)
+am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in \
+ $(srcdir)/libpcre2-16.pc.in $(srcdir)/libpcre2-32.pc.in \
+ $(srcdir)/libpcre2-8.pc.in $(srcdir)/libpcre2-posix.pc.in \
+ $(srcdir)/pcre2-config.in $(top_srcdir)/src/config.h.in \
+ $(top_srcdir)/src/libpcre2-16.sym.in \
+ $(top_srcdir)/src/libpcre2-32.sym.in \
+ $(top_srcdir)/src/libpcre2-8.sym.in \
+ $(top_srcdir)/src/libpcre2-posix.sym.in \
+ $(top_srcdir)/src/pcre2.h.in AUTHORS.md COPYING ChangeLog \
+ INSTALL NEWS README ar-lib compile config.guess config.sub \
+ depcomp install-sh ltmain.sh missing test-driver
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ if test -d "$(distdir)"; then \
+ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -rf "$(distdir)" \
+ || { sleep 5 && rm -rf "$(distdir)"; }; \
+ else :; fi
+am__post_remove_distdir = $(am__remove_distdir)
+DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2 $(distdir).zip
+GZIP_ENV = --best
+DIST_TARGETS = dist-bzip2 dist-gzip dist-zip
+# Exists only to be overridden by the user if desired.
+AM_DISTCHECK_DVI_TARGET = dvi
+distuninstallcheck_listfiles = find . -type f -print
+am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
+ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CET_CFLAGS = @CET_CFLAGS@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+EXTRA_LIBPCRE2_16_LDFLAGS = @EXTRA_LIBPCRE2_16_LDFLAGS@
+EXTRA_LIBPCRE2_32_LDFLAGS = @EXTRA_LIBPCRE2_32_LDFLAGS@
+EXTRA_LIBPCRE2_8_LDFLAGS = @EXTRA_LIBPCRE2_8_LDFLAGS@
+EXTRA_LIBPCRE2_POSIX_LDFLAGS = @EXTRA_LIBPCRE2_POSIX_LDFLAGS@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+GCOV_CFLAGS = @GCOV_CFLAGS@
+GCOV_CXXFLAGS = @GCOV_CXXFLAGS@
+GCOV_LIBS = @GCOV_LIBS@
+GENHTML = @GENHTML@
+GREP = @GREP@
+HAVE_VISIBILITY = @HAVE_VISIBILITY@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBBZ2 = @LIBBZ2@
+LIBOBJS = @LIBOBJS@
+LIBREADLINE = @LIBREADLINE@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBZ = @LIBZ@
+LIB_POSTFIX = @LIB_POSTFIX@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PCRE2POSIX_CFLAG = @PCRE2POSIX_CFLAG@
+PCRE2_DATE = @PCRE2_DATE@
+PCRE2_EXTRA_LOCAL_SYMS = @PCRE2_EXTRA_LOCAL_SYMS@
+PCRE2_MAJOR = @PCRE2_MAJOR@
+PCRE2_MINOR = @PCRE2_MINOR@
+PCRE2_PRERELEASE = @PCRE2_PRERELEASE@
+PCRE2_STATIC_CFLAG = @PCRE2_STATIC_CFLAG@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_CXX = @PTHREAD_CXX@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHTOOL = @SHTOOL@
+STRIP = @STRIP@
+VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
+VALGRIND_LIBS = @VALGRIND_LIBS@
+VERSION = @VERSION@
+VISIBILITY_CFLAGS = @VISIBILITY_CFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+ax_pthread_config = @ax_pthread_config@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+enable_pcre2_16 = @enable_pcre2_16@
+enable_pcre2_32 = @enable_pcre2_32@
+enable_pcre2_8 = @enable_pcre2_8@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = subdir-objects
+ACLOCAL_AMFLAGS = -I m4
+AM_CPPFLAGS = "-I$(srcdir)/src"
+CLEAN_LOCAL_TARGETS = testoutput-clean $(am__append_50)
+DISTCLEAN_LOCAL_TARGETS = $(am__append_51) $(am__append_54)
+PHONY_TARGETS = testoutput-clean $(am__append_52) $(am__append_55)
+dist_doc_DATA = \
+ AUTHORS.md \
+ COPYING \
+ ChangeLog \
+ LICENCE.md \
+ NEWS \
+ README \
+ SECURITY.md \
+ SUPPORT-LIFECYCLE.md \
+ doc/pcre2.txt \
+ doc/pcre2-config.txt \
+ doc/pcre2grep.txt \
+ doc/pcre2test.txt
+
+dist_html_DATA = \
+ doc/html/NON-AUTOTOOLS-BUILD.txt \
+ doc/html/README.txt \
+ doc/html/index.html \
+ doc/html/pcre2-config.html \
+ doc/html/pcre2.html \
+ doc/html/pcre2_callout_enumerate.html \
+ doc/html/pcre2_code_copy.html \
+ doc/html/pcre2_code_copy_with_tables.html \
+ doc/html/pcre2_code_free.html \
+ doc/html/pcre2_compile.html \
+ doc/html/pcre2_compile_context_copy.html \
+ doc/html/pcre2_compile_context_create.html \
+ doc/html/pcre2_compile_context_free.html \
+ doc/html/pcre2_config.html \
+ doc/html/pcre2_convert_context_copy.html \
+ doc/html/pcre2_convert_context_create.html \
+ doc/html/pcre2_convert_context_free.html \
+ doc/html/pcre2_converted_pattern_free.html \
+ doc/html/pcre2_dfa_match.html \
+ doc/html/pcre2_general_context_copy.html \
+ doc/html/pcre2_general_context_create.html \
+ doc/html/pcre2_general_context_free.html \
+ doc/html/pcre2_get_error_message.html \
+ doc/html/pcre2_get_mark.html \
+ doc/html/pcre2_get_match_data_heapframes_size.html \
+ doc/html/pcre2_get_match_data_size.html \
+ doc/html/pcre2_get_ovector_count.html \
+ doc/html/pcre2_get_ovector_pointer.html \
+ doc/html/pcre2_get_startchar.html \
+ doc/html/pcre2_jit_compile.html \
+ doc/html/pcre2_jit_free_unused_memory.html \
+ doc/html/pcre2_jit_match.html \
+ doc/html/pcre2_jit_stack_assign.html \
+ doc/html/pcre2_jit_stack_create.html \
+ doc/html/pcre2_jit_stack_free.html \
+ doc/html/pcre2_maketables.html \
+ doc/html/pcre2_maketables_free.html \
+ doc/html/pcre2_match.html \
+ doc/html/pcre2_match_context_copy.html \
+ doc/html/pcre2_match_context_create.html \
+ doc/html/pcre2_match_context_free.html \
+ doc/html/pcre2_match_data_create.html \
+ doc/html/pcre2_match_data_create_from_pattern.html \
+ doc/html/pcre2_match_data_free.html \
+ doc/html/pcre2_next_match.html \
+ doc/html/pcre2_pattern_convert.html \
+ doc/html/pcre2_pattern_info.html \
+ doc/html/pcre2_serialize_decode.html \
+ doc/html/pcre2_serialize_encode.html \
+ doc/html/pcre2_serialize_free.html \
+ doc/html/pcre2_serialize_get_number_of_codes.html \
+ doc/html/pcre2_set_bsr.html \
+ doc/html/pcre2_set_callout.html \
+ doc/html/pcre2_set_character_tables.html \
+ doc/html/pcre2_set_compile_extra_options.html \
+ doc/html/pcre2_set_compile_recursion_guard.html \
+ doc/html/pcre2_set_depth_limit.html \
+ doc/html/pcre2_set_glob_escape.html \
+ doc/html/pcre2_set_glob_separator.html \
+ doc/html/pcre2_set_heap_limit.html \
+ doc/html/pcre2_set_match_limit.html \
+ doc/html/pcre2_set_max_pattern_compiled_length.html \
+ doc/html/pcre2_set_max_pattern_length.html \
+ doc/html/pcre2_set_max_varlookbehind.html \
+ doc/html/pcre2_set_offset_limit.html \
+ doc/html/pcre2_set_optimize.html \
+ doc/html/pcre2_set_newline.html \
+ doc/html/pcre2_set_parens_nest_limit.html \
+ doc/html/pcre2_set_recursion_limit.html \
+ doc/html/pcre2_set_recursion_memory_management.html \
+ doc/html/pcre2_set_substitute_callout.html \
+ doc/html/pcre2_set_substitute_case_callout.html \
+ doc/html/pcre2_substitute.html \
+ doc/html/pcre2_substring_copy_byname.html \
+ doc/html/pcre2_substring_copy_bynumber.html \
+ doc/html/pcre2_substring_free.html \
+ doc/html/pcre2_substring_get_byname.html \
+ doc/html/pcre2_substring_get_bynumber.html \
+ doc/html/pcre2_substring_length_byname.html \
+ doc/html/pcre2_substring_length_bynumber.html \
+ doc/html/pcre2_substring_list_free.html \
+ doc/html/pcre2_substring_list_get.html \
+ doc/html/pcre2_substring_nametable_scan.html \
+ doc/html/pcre2_substring_number_from_name.html \
+ doc/html/pcre2api.html \
+ doc/html/pcre2build.html \
+ doc/html/pcre2callout.html \
+ doc/html/pcre2compat.html \
+ doc/html/pcre2convert.html \
+ doc/html/pcre2demo.html \
+ doc/html/pcre2grep.html \
+ doc/html/pcre2jit.html \
+ doc/html/pcre2limits.html \
+ doc/html/pcre2matching.html \
+ doc/html/pcre2partial.html \
+ doc/html/pcre2pattern.html \
+ doc/html/pcre2perform.html \
+ doc/html/pcre2posix.html \
+ doc/html/pcre2sample.html \
+ doc/html/pcre2serialize.html \
+ doc/html/pcre2syntax.html \
+ doc/html/pcre2test.html \
+ doc/html/pcre2unicode.html
+
+dist_man_MANS = \
+ doc/pcre2-config.1 \
+ doc/pcre2.3 \
+ doc/pcre2_callout_enumerate.3 \
+ doc/pcre2_code_copy.3 \
+ doc/pcre2_code_copy_with_tables.3 \
+ doc/pcre2_code_free.3 \
+ doc/pcre2_compile.3 \
+ doc/pcre2_compile_context_copy.3 \
+ doc/pcre2_compile_context_create.3 \
+ doc/pcre2_compile_context_free.3 \
+ doc/pcre2_config.3 \
+ doc/pcre2_convert_context_copy.3 \
+ doc/pcre2_convert_context_create.3 \
+ doc/pcre2_convert_context_free.3 \
+ doc/pcre2_converted_pattern_free.3 \
+ doc/pcre2_dfa_match.3 \
+ doc/pcre2_general_context_copy.3 \
+ doc/pcre2_general_context_create.3 \
+ doc/pcre2_general_context_free.3 \
+ doc/pcre2_get_error_message.3 \
+ doc/pcre2_get_mark.3 \
+ doc/pcre2_get_match_data_heapframes_size.3 \
+ doc/pcre2_get_match_data_size.3 \
+ doc/pcre2_get_ovector_count.3 \
+ doc/pcre2_get_ovector_pointer.3 \
+ doc/pcre2_get_startchar.3 \
+ doc/pcre2_jit_compile.3 \
+ doc/pcre2_jit_free_unused_memory.3 \
+ doc/pcre2_jit_match.3 \
+ doc/pcre2_jit_stack_assign.3 \
+ doc/pcre2_jit_stack_create.3 \
+ doc/pcre2_jit_stack_free.3 \
+ doc/pcre2_maketables.3 \
+ doc/pcre2_maketables_free.3 \
+ doc/pcre2_match.3 \
+ doc/pcre2_match_context_copy.3 \
+ doc/pcre2_match_context_create.3 \
+ doc/pcre2_match_context_free.3 \
+ doc/pcre2_match_data_create.3 \
+ doc/pcre2_match_data_create_from_pattern.3 \
+ doc/pcre2_match_data_free.3 \
+ doc/pcre2_next_match.3 \
+ doc/pcre2_pattern_convert.3 \
+ doc/pcre2_pattern_info.3 \
+ doc/pcre2_serialize_decode.3 \
+ doc/pcre2_serialize_encode.3 \
+ doc/pcre2_serialize_free.3 \
+ doc/pcre2_serialize_get_number_of_codes.3 \
+ doc/pcre2_set_bsr.3 \
+ doc/pcre2_set_callout.3 \
+ doc/pcre2_set_character_tables.3 \
+ doc/pcre2_set_compile_extra_options.3 \
+ doc/pcre2_set_compile_recursion_guard.3 \
+ doc/pcre2_set_depth_limit.3 \
+ doc/pcre2_set_glob_escape.3 \
+ doc/pcre2_set_glob_separator.3 \
+ doc/pcre2_set_heap_limit.3 \
+ doc/pcre2_set_match_limit.3 \
+ doc/pcre2_set_max_pattern_compiled_length.3 \
+ doc/pcre2_set_max_pattern_length.3 \
+ doc/pcre2_set_max_varlookbehind.3 \
+ doc/pcre2_set_offset_limit.3 \
+ doc/pcre2_set_optimize.3 \
+ doc/pcre2_set_newline.3 \
+ doc/pcre2_set_parens_nest_limit.3 \
+ doc/pcre2_set_recursion_limit.3 \
+ doc/pcre2_set_recursion_memory_management.3 \
+ doc/pcre2_set_substitute_callout.3 \
+ doc/pcre2_set_substitute_case_callout.3 \
+ doc/pcre2_substitute.3 \
+ doc/pcre2_substring_copy_byname.3 \
+ doc/pcre2_substring_copy_bynumber.3 \
+ doc/pcre2_substring_free.3 \
+ doc/pcre2_substring_get_byname.3 \
+ doc/pcre2_substring_get_bynumber.3 \
+ doc/pcre2_substring_length_byname.3 \
+ doc/pcre2_substring_length_bynumber.3 \
+ doc/pcre2_substring_list_free.3 \
+ doc/pcre2_substring_list_get.3 \
+ doc/pcre2_substring_nametable_scan.3 \
+ doc/pcre2_substring_number_from_name.3 \
+ doc/pcre2api.3 \
+ doc/pcre2build.3 \
+ doc/pcre2callout.3 \
+ doc/pcre2compat.3 \
+ doc/pcre2convert.3 \
+ doc/pcre2demo.3 \
+ doc/pcre2grep.1 \
+ doc/pcre2jit.3 \
+ doc/pcre2limits.3 \
+ doc/pcre2matching.3 \
+ doc/pcre2partial.3 \
+ doc/pcre2pattern.3 \
+ doc/pcre2perform.3 \
+ doc/pcre2posix.3 \
+ doc/pcre2sample.3 \
+ doc/pcre2serialize.3 \
+ doc/pcre2syntax.3 \
+ doc/pcre2test.1 \
+ doc/pcre2unicode.3
+
+
+# The Libtool libraries to install. We'll add to this later.
+lib_LTLIBRARIES = $(am__append_2) $(am__append_3) $(am__append_4) \
+ $(am__append_11)
+XFAIL_TESTS = $(am__append_46)
+check_SCRIPTS =
+dist_noinst_SCRIPTS = RunTest $(am__append_45)
+
+# Additional files to delete on 'make clean', 'make distclean',
+# and 'make maintainer-clean'. It turns out that the default is to delete only
+# those binaries that *this* configuration has created. If the configuration
+# has been changed, some binaries may not get automatically deleted. Therefore
+# we list them here.
+
+# RunTest and RunGrepTest should clean up after themselves, but just in case
+# they don't, add their working files to CLEANFILES.
+CLEANFILES = pcre2_dftables pcre2_jit_test pcre2fuzzcheck-8 \
+ pcre2fuzzcheck-16 pcre2fuzzcheck-32 pcre2demo \
+ src/pcre2_chartables.c testSinput testSoutput test3input \
+ test3output test3outputA test3outputB testtry teststdout \
+ teststderr teststderrgrep testtemp1grep testtemp2grep \
+ testtrygrep testNinputgrep
+DISTCLEANFILES = src/config.h.in~ $(am__append_53)
+MAINTAINERCLEANFILES = src/pcre2.h.generic src/config.h.generic
+
+# Additional files to bundle with the distribution, over and above what
+# the Autotools include by default.
+
+# These files contain additional m4 macros that are used by autoconf.
+
+# These files contain maintenance information
+
+# These are patches containing backports for older versions of PCRE2
+
+# These are support files for building with Bazel or Zig
+
+# These are support files for building under VMS
+
+# These files are usable versions of pcre2.h and config.h that are distributed
+# for the benefit of people who are building PCRE2 manually, without the
+# Autotools support.
+
+# The pcre2_chartables.c.dist file is the default version of
+# pcre2_chartables.c, used unless --enable-rebuild-chartables is specified.
+
+# The JIT compiler lives in a separate directory, but its files are #included
+# when pcre2_jit_compile.c is processed, so they must be distributed.
+
+# PCRE2 demonstration program. Not built automatically. The point is that the
+# users should build it themselves. So just distribute the source.
+
+# Symbol version template files for use with GNU and Sun ld.
+EXTRA_DIST = m4/ax_pthread.m4 m4/pcre2_check_vscript.m4 \
+ m4/pcre2_visibility.m4 m4/pcre2_zos.m4 NON-AUTOTOOLS-BUILD \
+ HACKING patches/pcre2-10.37-Remove-real-POSIX.patch \
+ patches/pcre2-10.39-Fix-incorrect-detection.patch \
+ patches/pcre2-10.40-A-Fixed-a-unicode.patch \
+ patches/pcre2-10.40-B-Fixed-an-issue-affecting.patch \
+ patches/pcre2-10.43-Avoid-LIMIT_HEAP-integer.patch \
+ patches/pcre2-10.43-Fix-heapframe-overflow.patch \
+ patches/pcre2-10.44-Fix-incorrect-compiling.patch \
+ patches/pcre2-10.44-Fix-locking-region.patch \
+ patches/pcre2-10.45-Memory-reports-only-compiled.patch \
+ patches/pcre2-10.47-Fix-for-callback.patch \
+ patches/pcre2-10.48-Check-JIT-mode-before-validation.patch \
+ patches/pcre2-10.48-Fix-DFA-workspace-overflows.patch \
+ patches/pcre2-10.48-Fix-JIT-STR_END.patch \
+ patches/pcre2-10.48-Fix-JIT-match-context-reuse.patch \
+ patches/pcre2-10.48-Fix-allocation-byte-sizing.patch \
+ patches/pcre2-10.48-Fix-character-list-generator.patch \
+ patches/pcre2-10.48-Fix-compiler-integer-overflows.patch \
+ patches/pcre2-10.48-Fix-invalid-UTF-backwards-scans.patch \
+ patches/pcre2-10.48-Fix-repeated-substitute-escapes.patch \
+ patches/pcre2-10.48-Fix-scan-prefix-repeat-reset.patch \
+ patches/pcre2-10.48-Keep-escape-error-offset-in-pattern.patch \
+ patches/pcre2-10.48-Write-serialization-padding.patch \
+ BUILD.bazel MODULE.bazel build.zig build.zig.zon \
+ vms/configure.com vms/openvms_readme.txt vms/pcre2.h_patch \
+ vms/stdint.h src/pcre2.h.generic src/config.h.generic \
+ src/pcre2_chartables.c.dist \
+ src/pcre2_chartables.c.ebcdic-1047-nl15 \
+ src/pcre2_chartables.c.ebcdic-1047-nl25 deps/sljit/LICENSE \
+ deps/sljit/README.md deps/sljit/sljit_src/sljitConfig.h \
+ deps/sljit/sljit_src/sljitConfigCPU.h \
+ deps/sljit/sljit_src/sljitConfigInternal.h \
+ deps/sljit/sljit_src/sljitLir.c \
+ deps/sljit/sljit_src/sljitLir.h \
+ deps/sljit/sljit_src/sljitNativeARM_32.c \
+ deps/sljit/sljit_src/sljitNativeARM_64.c \
+ deps/sljit/sljit_src/sljitNativeARM_T2_32.c \
+ deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c \
+ deps/sljit/sljit_src/sljitNativeMIPS_32.c \
+ deps/sljit/sljit_src/sljitNativeMIPS_64.c \
+ deps/sljit/sljit_src/sljitNativeMIPS_common.c \
+ deps/sljit/sljit_src/sljitNativePPC_32.c \
+ deps/sljit/sljit_src/sljitNativePPC_64.c \
+ deps/sljit/sljit_src/sljitNativePPC_common.c \
+ deps/sljit/sljit_src/sljitNativeRISCV_32.c \
+ deps/sljit/sljit_src/sljitNativeRISCV_64.c \
+ deps/sljit/sljit_src/sljitNativeRISCV_common.c \
+ deps/sljit/sljit_src/sljitNativeS390X.c \
+ deps/sljit/sljit_src/sljitNativeX86_32.c \
+ deps/sljit/sljit_src/sljitNativeX86_64.c \
+ deps/sljit/sljit_src/sljitNativeX86_common.c \
+ deps/sljit/sljit_src/sljitSerialize.c \
+ deps/sljit/sljit_src/sljitUtils.c \
+ deps/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c \
+ deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c \
+ deps/sljit/sljit_src/allocator_src/sljitExecAllocatorFreeBSD.c \
+ deps/sljit/sljit_src/allocator_src/sljitExecAllocatorPosix.c \
+ deps/sljit/sljit_src/allocator_src/sljitExecAllocatorWindows.c \
+ deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorNetBSD.c \
+ deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorPosix.c \
+ deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorPosix.c \
+ deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorWindows.c \
+ RunTest.bat $(am__append_44) testdata/grepbinary \
+ testdata/grepfilelist testdata/grepinput testdata/grepinput3 \
+ testdata/grepinput8 testdata/grepinputBad8 \
+ testdata/grepinputBad8_Trail testdata/grepinputC.bz2 \
+ testdata/grepinputC.gz testdata/grepinputM \
+ testdata/grepinputUN testdata/grepinputv testdata/grepinputx \
+ testdata/greplist testdata/grepnot.bz2 testdata/grepoutput \
+ testdata/grepoutput8 testdata/grepoutputC \
+ testdata/grepoutputCN testdata/grepoutputCNU \
+ testdata/grepoutputCU testdata/grepoutputCbz2 \
+ testdata/grepoutputCgz testdata/grepoutputN \
+ testdata/grepoutputUN testdata/greppatN4 testdata/testbtables \
+ testdata/testinput1 testdata/testinput2 testdata/testinput3 \
+ testdata/testinput4 testdata/testinput5 testdata/testinput6 \
+ testdata/testinput7 testdata/testinput8 testdata/testinput9 \
+ testdata/testinput10 testdata/testinput11 testdata/testinput12 \
+ testdata/testinput13 testdata/testinput14 testdata/testinput15 \
+ testdata/testinput16 testdata/testinput17 testdata/testinput18 \
+ testdata/testinput19 testdata/testinput20 testdata/testinput21 \
+ testdata/testinput22 testdata/testinput23 testdata/testinput24 \
+ testdata/testinput25 testdata/testinput26 testdata/testinput27 \
+ testdata/testinput28 testdata/testinput29 \
+ testdata/testinputheap testdata/testoutput1 \
+ testdata/testoutput2 testdata/testoutput3 \
+ testdata/testoutput3A testdata/testoutput3B \
+ testdata/testoutput4 testdata/testoutput5 testdata/testoutput6 \
+ testdata/testoutput7 testdata/testoutput8-16-2 \
+ testdata/testoutput8-16-4 testdata/testoutput8-32-4 \
+ testdata/testoutput8-8-2 testdata/testoutput8-8-3 \
+ testdata/testoutput8-8-4 testdata/testoutput9 \
+ testdata/testoutput10 testdata/testoutput11-16 \
+ testdata/testoutput11-32 testdata/testoutput12-16 \
+ testdata/testoutput12-32 testdata/testoutput13 \
+ testdata/testoutput14-16 testdata/testoutput14-32 \
+ testdata/testoutput14-8 testdata/testoutput15 \
+ testdata/testoutput16 testdata/testoutput17 \
+ testdata/testoutput18 testdata/testoutput19 \
+ testdata/testoutput20 testdata/testoutput21 \
+ testdata/testoutput22-16 testdata/testoutput22-32 \
+ testdata/testoutput22-8 testdata/testoutput23 \
+ testdata/testoutput24 testdata/testoutput25 \
+ testdata/testoutput26 testdata/testoutput27 \
+ testdata/testoutput28 testdata/testoutput29 \
+ testdata/testoutputheap-16 testdata/testoutputheap-32 \
+ testdata/testoutputheap-8 testdata/valgrind-jit.supp \
+ testdata/wintestinput3 testdata/wintestoutput3 perltest.sh \
+ src/pcre2demo.c src/libpcre2-8.sym.in src/libpcre2-16.sym.in \
+ src/libpcre2-32.sym.in src/libpcre2-posix.sym.in \
+ cmake/COPYING-CMAKE-SCRIPTS cmake/FindEditline.cmake \
+ cmake/FindReadline.cmake cmake/pcre2-config.cmake.in \
+ cmake/PCRE2CheckVscript.cmake \
+ cmake/PCRE2UseSystemExtensions.cmake \
+ cmake/PCRE2WarningAsError.cmake src/config-cmake.h.in \
+ CMakeLists.txt
+
+# These are the header files we'll install. We do not distribute pcre2.h
+# because it is generated from pcre2.h.in.
+nodist_include_HEADERS = src/pcre2.h
+include_HEADERS = src/pcre2posix.h
+
+# This is the "config" script.
+bin_SCRIPTS = pcre2-config
+@WITH_REBUILD_CHARTABLES_TRUE@pcre2_dftables_SOURCES = src/pcre2_dftables.c
+BUILT_SOURCES = src/pcre2_chartables.c
+NODIST_SOURCES = src/pcre2_chartables.c
+COMMON_SOURCES = \
+ src/pcre2_auto_possess.c \
+ src/pcre2_chkdint.c \
+ src/pcre2_compile.c \
+ src/pcre2_compile.h \
+ src/pcre2_compile_cgroup.c \
+ src/pcre2_compile_class.c \
+ src/pcre2_config.c \
+ src/pcre2_context.c \
+ src/pcre2_convert.c \
+ src/pcre2_dfa_match.c \
+ src/pcre2_error.c \
+ src/pcre2_extuni.c \
+ src/pcre2_find_bracket.c \
+ src/pcre2_internal.h \
+ src/pcre2_intmodedep.h \
+ src/pcre2_jit_char_inc.h \
+ src/pcre2_jit_compile.c \
+ src/pcre2_jit_match_inc.h \
+ src/pcre2_jit_misc_inc.h \
+ src/pcre2_jit_simd_inc.h \
+ src/pcre2_maketables.c \
+ src/pcre2_match.c \
+ src/pcre2_match_data.c \
+ src/pcre2_match_next.c \
+ src/pcre2_newline.c \
+ src/pcre2_ord2utf.c \
+ src/pcre2_pattern_info.c \
+ src/pcre2_printint_inc.h \
+ src/pcre2_script_run.c \
+ src/pcre2_serialize.c \
+ src/pcre2_string_utils.c \
+ src/pcre2_study.c \
+ src/pcre2_substitute.c \
+ src/pcre2_substring.c \
+ src/pcre2_tables.c \
+ src/pcre2_ucd.c \
+ src/pcre2_ucp.h \
+ src/pcre2_ucptables_inc.h \
+ src/pcre2_util.h \
+ src/pcre2_valid_utf.c \
+ src/pcre2_xclass.c
+
+@WITH_PCRE2_8_TRUE@libpcre2_8_la_SOURCES = \
+@WITH_PCRE2_8_TRUE@ $(COMMON_SOURCES)
+
+@WITH_PCRE2_8_TRUE@nodist_libpcre2_8_la_SOURCES = \
+@WITH_PCRE2_8_TRUE@ $(NODIST_SOURCES)
+
+@WITH_PCRE2_8_TRUE@libpcre2_8_la_CFLAGS = -DPCRE2_CODE_UNIT_WIDTH=8 \
+@WITH_PCRE2_8_TRUE@ $(VISIBILITY_CFLAGS) $(CET_CFLAGS) \
+@WITH_PCRE2_8_TRUE@ $(AM_CFLAGS) $(am__append_5) \
+@WITH_PCRE2_8_TRUE@ $(am__append_8)
+@WITH_PCRE2_8_TRUE@libpcre2_8_la_LIBADD =
+@WITH_PCRE2_16_TRUE@libpcre2_16_la_SOURCES = \
+@WITH_PCRE2_16_TRUE@ $(COMMON_SOURCES)
+
+@WITH_PCRE2_16_TRUE@nodist_libpcre2_16_la_SOURCES = \
+@WITH_PCRE2_16_TRUE@ $(NODIST_SOURCES)
+
+@WITH_PCRE2_16_TRUE@libpcre2_16_la_CFLAGS = \
+@WITH_PCRE2_16_TRUE@ -DPCRE2_CODE_UNIT_WIDTH=16 \
+@WITH_PCRE2_16_TRUE@ $(VISIBILITY_CFLAGS) $(CET_CFLAGS) \
+@WITH_PCRE2_16_TRUE@ $(AM_CFLAGS) $(am__append_6) \
+@WITH_PCRE2_16_TRUE@ $(am__append_9)
+@WITH_PCRE2_16_TRUE@libpcre2_16_la_LIBADD =
+@WITH_PCRE2_32_TRUE@libpcre2_32_la_SOURCES = \
+@WITH_PCRE2_32_TRUE@ $(COMMON_SOURCES)
+
+@WITH_PCRE2_32_TRUE@nodist_libpcre2_32_la_SOURCES = \
+@WITH_PCRE2_32_TRUE@ $(NODIST_SOURCES)
+
+@WITH_PCRE2_32_TRUE@libpcre2_32_la_CFLAGS = \
+@WITH_PCRE2_32_TRUE@ -DPCRE2_CODE_UNIT_WIDTH=32 \
+@WITH_PCRE2_32_TRUE@ $(VISIBILITY_CFLAGS) $(CET_CFLAGS) \
+@WITH_PCRE2_32_TRUE@ $(AM_CFLAGS) $(am__append_7) \
+@WITH_PCRE2_32_TRUE@ $(am__append_10)
+@WITH_PCRE2_32_TRUE@libpcre2_32_la_LIBADD =
+@WITH_PCRE2_8_TRUE@libpcre2_8_la_LDFLAGS = $(EXTRA_LIBPCRE2_8_LDFLAGS)
+@WITH_PCRE2_16_TRUE@libpcre2_16_la_LDFLAGS = $(EXTRA_LIBPCRE2_16_LDFLAGS)
+@WITH_PCRE2_32_TRUE@libpcre2_32_la_LDFLAGS = $(EXTRA_LIBPCRE2_32_LDFLAGS)
+@WITH_PCRE2_8_TRUE@libpcre2_posix_la_SOURCES = src/pcre2posix.c
+@WITH_PCRE2_8_TRUE@libpcre2_posix_la_CFLAGS = \
+@WITH_PCRE2_8_TRUE@ -DPCRE2_CODE_UNIT_WIDTH=8 \
+@WITH_PCRE2_8_TRUE@ @PCRE2POSIX_CFLAG@ $(VISIBILITY_CFLAGS) \
+@WITH_PCRE2_8_TRUE@ $(AM_CFLAGS) $(am__append_12)
+@WITH_PCRE2_8_TRUE@libpcre2_posix_la_LDFLAGS = $(EXTRA_LIBPCRE2_POSIX_LDFLAGS)
+@WITH_PCRE2_8_TRUE@libpcre2_posix_la_LIBADD = libpcre2-8.la
+@WITH_PCRE2_8_TRUE@pcre2grep_SOURCES = src/pcre2grep.c
+@WITH_PCRE2_8_TRUE@pcre2grep_CFLAGS = $(AM_CFLAGS) $(am__append_14)
+@WITH_PCRE2_8_TRUE@pcre2grep_LDADD = $(LIBZ) $(LIBBZ2) libpcre2-8.la \
+@WITH_PCRE2_8_TRUE@ $(am__append_15)
+@WITH_FUZZ_SUPPORT_TRUE@noinst_LIBRARIES = $(am__append_16) \
+@WITH_FUZZ_SUPPORT_TRUE@ $(am__append_20) $(am__append_24)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@_libs_libpcre2_fuzzsupport_a_SOURCES = src/pcre2_fuzzsupport.c
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@_libs_libpcre2_fuzzsupport_a_CFLAGS = $(AM_CFLAGS)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@_libs_libpcre2_fuzzsupport_a_LIBADD =
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@pcre2fuzzcheck_8_SOURCES = src/pcre2_fuzzsupport.c
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@pcre2fuzzcheck_8_CFLAGS = \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@ -DSTANDALONE \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@ $(AM_CFLAGS) \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@ $(am__append_18)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@pcre2fuzzcheck_8_LDADD = \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@ libpcre2-8.la \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_8_TRUE@ $(am__append_19)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@_libs_libpcre2_fuzzsupport_16_a_SOURCES = src/pcre2_fuzzsupport.c
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@_libs_libpcre2_fuzzsupport_16_a_CFLAGS = $(AM_CFLAGS) -DPCRE2_CODE_UNIT_WIDTH=16
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@_libs_libpcre2_fuzzsupport_16_a_LIBADD =
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@pcre2fuzzcheck_16_SOURCES = src/pcre2_fuzzsupport.c
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@pcre2fuzzcheck_16_CFLAGS = \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@ -DSTANDALONE \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@ $(AM_CFLAGS) \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@ -DPCRE2_CODE_UNIT_WIDTH=16 \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@ $(am__append_22)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@pcre2fuzzcheck_16_LDADD = \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@ libpcre2-16.la \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_16_TRUE@ $(am__append_23)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@_libs_libpcre2_fuzzsupport_32_a_SOURCES = src/pcre2_fuzzsupport.c
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@_libs_libpcre2_fuzzsupport_32_a_CFLAGS = $(AM_CFLAGS) -DPCRE2_CODE_UNIT_WIDTH=32
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@_libs_libpcre2_fuzzsupport_32_a_LIBADD =
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@pcre2fuzzcheck_32_SOURCES = src/pcre2_fuzzsupport.c
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@pcre2fuzzcheck_32_CFLAGS = \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@ -DSTANDALONE \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@ $(AM_CFLAGS) \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@ -DPCRE2_CODE_UNIT_WIDTH=32 \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@ $(am__append_26)
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@pcre2fuzzcheck_32_LDADD = \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@ libpcre2-32.la \
+@WITH_FUZZ_SUPPORT_TRUE@@WITH_PCRE2_32_TRUE@ $(am__append_27)
+@WITH_PCRE2_8_TRUE@pcre2posix_test_SOURCES = src/pcre2posix_test.c
+@WITH_PCRE2_8_TRUE@pcre2posix_test_CFLAGS = $(AM_CFLAGS) @PCRE2POSIX_CFLAG@
+@WITH_PCRE2_8_TRUE@pcre2posix_test_LDADD = libpcre2-posix.la libpcre2-8.la
+@WITH_JIT_TRUE@pcre2_jit_test_SOURCES = src/pcre2_jit_test.c
+@WITH_JIT_TRUE@pcre2_jit_test_CFLAGS = $(AM_CFLAGS) $(am__append_35)
+@WITH_JIT_TRUE@pcre2_jit_test_LDADD = $(am__append_32) \
+@WITH_JIT_TRUE@ $(am__append_33) $(am__append_34) \
+@WITH_JIT_TRUE@ $(am__append_36)
+pcre2test_SOURCES = src/pcre2test.c src/pcre2test_inc.h
+pcre2test_CFLAGS = $(AM_CFLAGS) $(am__append_40) $(am__append_41)
+pcre2test_LDADD = $(LIBREADLINE) $(am__append_37) $(am__append_38) \
+ $(am__append_39) $(am__append_42)
+
+# We have .pc files for pkg-config users.
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = $(am__append_47) $(am__append_48) $(am__append_49)
+
+# gcov/lcov code coverage reporting
+#
+# Coverage reporting targets:
+#
+# coverage: Create a coverage report from 'make check'
+# coverage-baseline: Capture baseline coverage information
+# coverage-reset: This zeros the coverage counters only
+# coverage-report: This creates the coverage report only
+# coverage-clean-report: This removes the generated coverage report
+# without cleaning the coverage data itself
+# coverage-clean-data: This removes the captured coverage data without
+# removing the coverage files created at compile time (*.gcno)
+# coverage-clean: This cleans all coverage data including the generated
+# coverage report.
+@WITH_GCOV_TRUE@COVERAGE_TEST_NAME = $(PACKAGE)
+@WITH_GCOV_TRUE@COVERAGE_NAME = $(PACKAGE)-$(VERSION)
+@WITH_GCOV_TRUE@COVERAGE_OUTPUT_FILE = $(COVERAGE_NAME)-coverage.info
+@WITH_GCOV_TRUE@COVERAGE_OUTPUT_DIR = $(COVERAGE_NAME)-coverage
+@WITH_GCOV_TRUE@COVERAGE_LCOV_EXTRA_FLAGS =
+@WITH_GCOV_TRUE@COVERAGE_GENHTML_EXTRA_FLAGS =
+@WITH_GCOV_TRUE@coverage_quiet = $(coverage_quiet_$(V))
+@WITH_GCOV_TRUE@coverage_quiet_ = $(coverage_quiet_$(AM_DEFAULT_VERBOSITY))
+@WITH_GCOV_TRUE@coverage_quiet_0 = --quiet
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
+am--refresh: Makefile
+ @:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ $(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+src/config.h: src/stamp-h1
+ @test -f $@ || rm -f src/stamp-h1
+ @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) src/stamp-h1
+
+src/stamp-h1: $(top_srcdir)/src/config.h.in $(top_builddir)/config.status
+ @rm -f src/stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status src/config.h
+$(top_srcdir)/src/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+ rm -f src/stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f src/config.h src/stamp-h1
+libpcre2-8.pc: $(top_builddir)/config.status $(srcdir)/libpcre2-8.pc.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+libpcre2-16.pc: $(top_builddir)/config.status $(srcdir)/libpcre2-16.pc.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+libpcre2-32.pc: $(top_builddir)/config.status $(srcdir)/libpcre2-32.pc.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+libpcre2-posix.pc: $(top_builddir)/config.status $(srcdir)/libpcre2-posix.pc.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+pcre2-config: $(top_builddir)/config.status $(srcdir)/pcre2-config.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+src/pcre2.h: $(top_builddir)/config.status $(top_srcdir)/src/pcre2.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+src/libpcre2-8.sym: $(top_builddir)/config.status $(top_srcdir)/src/libpcre2-8.sym.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+src/libpcre2-16.sym: $(top_builddir)/config.status $(top_srcdir)/src/libpcre2-16.sym.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+src/libpcre2-32.sym: $(top_builddir)/config.status $(top_srcdir)/src/libpcre2-32.sym.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+src/libpcre2-posix.sym: $(top_builddir)/config.status $(top_srcdir)/src/libpcre2-posix.sym.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+src/$(am__dirstamp):
+ @$(MKDIR_P) src
+ @: > src/$(am__dirstamp)
+src/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) src/$(DEPDIR)
+ @: > src/$(DEPDIR)/$(am__dirstamp)
+src/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.$(OBJEXT): \
+ src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+.libs/$(am__dirstamp):
+ @$(MKDIR_P) .libs
+ @: > .libs/$(am__dirstamp)
+
+.libs/libpcre2-fuzzsupport-16.a: $(_libs_libpcre2_fuzzsupport_16_a_OBJECTS) $(_libs_libpcre2_fuzzsupport_16_a_DEPENDENCIES) $(EXTRA__libs_libpcre2_fuzzsupport_16_a_DEPENDENCIES) .libs/$(am__dirstamp)
+ $(AM_V_at)-rm -f .libs/libpcre2-fuzzsupport-16.a
+ $(AM_V_AR)$(_libs_libpcre2_fuzzsupport_16_a_AR) .libs/libpcre2-fuzzsupport-16.a $(_libs_libpcre2_fuzzsupport_16_a_OBJECTS) $(_libs_libpcre2_fuzzsupport_16_a_LIBADD)
+ $(AM_V_at)$(RANLIB) .libs/libpcre2-fuzzsupport-16.a
+src/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.$(OBJEXT): \
+ src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+
+.libs/libpcre2-fuzzsupport-32.a: $(_libs_libpcre2_fuzzsupport_32_a_OBJECTS) $(_libs_libpcre2_fuzzsupport_32_a_DEPENDENCIES) $(EXTRA__libs_libpcre2_fuzzsupport_32_a_DEPENDENCIES) .libs/$(am__dirstamp)
+ $(AM_V_at)-rm -f .libs/libpcre2-fuzzsupport-32.a
+ $(AM_V_AR)$(_libs_libpcre2_fuzzsupport_32_a_AR) .libs/libpcre2-fuzzsupport-32.a $(_libs_libpcre2_fuzzsupport_32_a_OBJECTS) $(_libs_libpcre2_fuzzsupport_32_a_LIBADD)
+ $(AM_V_at)$(RANLIB) .libs/libpcre2-fuzzsupport-32.a
+src/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.$(OBJEXT): \
+ src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+
+.libs/libpcre2-fuzzsupport.a: $(_libs_libpcre2_fuzzsupport_a_OBJECTS) $(_libs_libpcre2_fuzzsupport_a_DEPENDENCIES) $(EXTRA__libs_libpcre2_fuzzsupport_a_DEPENDENCIES) .libs/$(am__dirstamp)
+ $(AM_V_at)-rm -f .libs/libpcre2-fuzzsupport.a
+ $(AM_V_AR)$(_libs_libpcre2_fuzzsupport_a_AR) .libs/libpcre2-fuzzsupport.a $(_libs_libpcre2_fuzzsupport_a_OBJECTS) $(_libs_libpcre2_fuzzsupport_a_LIBADD)
+ $(AM_V_at)$(RANLIB) .libs/libpcre2-fuzzsupport.a
+src/libpcre2_16_la-pcre2_auto_possess.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_chkdint.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_compile.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_compile_cgroup.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_compile_class.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_config.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_context.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_convert.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_dfa_match.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_error.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_extuni.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_find_bracket.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_jit_compile.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_maketables.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_match.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_match_data.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_match_next.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_newline.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_ord2utf.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_pattern_info.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_script_run.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_serialize.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_string_utils.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_study.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_substitute.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_substring.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_tables.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_ucd.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_valid_utf.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_xclass.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_16_la-pcre2_chartables.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+
+libpcre2-16.la: $(libpcre2_16_la_OBJECTS) $(libpcre2_16_la_DEPENDENCIES) $(EXTRA_libpcre2_16_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libpcre2_16_la_LINK) $(am_libpcre2_16_la_rpath) $(libpcre2_16_la_OBJECTS) $(libpcre2_16_la_LIBADD) $(LIBS)
+src/libpcre2_32_la-pcre2_auto_possess.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_chkdint.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_compile.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_compile_cgroup.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_compile_class.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_config.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_context.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_convert.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_dfa_match.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_error.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_extuni.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_find_bracket.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_jit_compile.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_maketables.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_match.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_match_data.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_match_next.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_newline.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_ord2utf.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_pattern_info.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_script_run.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_serialize.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_string_utils.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_study.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_substitute.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_substring.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_tables.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_ucd.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_valid_utf.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_xclass.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_32_la-pcre2_chartables.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+
+libpcre2-32.la: $(libpcre2_32_la_OBJECTS) $(libpcre2_32_la_DEPENDENCIES) $(EXTRA_libpcre2_32_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libpcre2_32_la_LINK) $(am_libpcre2_32_la_rpath) $(libpcre2_32_la_OBJECTS) $(libpcre2_32_la_LIBADD) $(LIBS)
+src/libpcre2_8_la-pcre2_auto_possess.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_chkdint.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_compile.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_compile_cgroup.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_compile_class.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_config.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_context.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_convert.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_dfa_match.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_error.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_extuni.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_find_bracket.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_jit_compile.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_maketables.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_match.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_match_data.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_match_next.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_newline.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_ord2utf.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_pattern_info.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_script_run.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_serialize.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_string_utils.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_study.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_substitute.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_substring.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_tables.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_ucd.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_valid_utf.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_xclass.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+src/libpcre2_8_la-pcre2_chartables.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+
+libpcre2-8.la: $(libpcre2_8_la_OBJECTS) $(libpcre2_8_la_DEPENDENCIES) $(EXTRA_libpcre2_8_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libpcre2_8_la_LINK) $(am_libpcre2_8_la_rpath) $(libpcre2_8_la_OBJECTS) $(libpcre2_8_la_LIBADD) $(LIBS)
+src/libpcre2_posix_la-pcre2posix.lo: src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+
+libpcre2-posix.la: $(libpcre2_posix_la_OBJECTS) $(libpcre2_posix_la_DEPENDENCIES) $(EXTRA_libpcre2_posix_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libpcre2_posix_la_LINK) $(am_libpcre2_posix_la_rpath) $(libpcre2_posix_la_OBJECTS) $(libpcre2_posix_la_LIBADD) $(LIBS)
+src/pcre2_dftables.$(OBJEXT): src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+
+pcre2_dftables$(EXEEXT): $(pcre2_dftables_OBJECTS) $(pcre2_dftables_DEPENDENCIES) $(EXTRA_pcre2_dftables_DEPENDENCIES)
+ @rm -f pcre2_dftables$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(pcre2_dftables_OBJECTS) $(pcre2_dftables_LDADD) $(LIBS)
+src/pcre2_jit_test-pcre2_jit_test.$(OBJEXT): src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+
+pcre2_jit_test$(EXEEXT): $(pcre2_jit_test_OBJECTS) $(pcre2_jit_test_DEPENDENCIES) $(EXTRA_pcre2_jit_test_DEPENDENCIES)
+ @rm -f pcre2_jit_test$(EXEEXT)
+ $(AM_V_CCLD)$(pcre2_jit_test_LINK) $(pcre2_jit_test_OBJECTS) $(pcre2_jit_test_LDADD) $(LIBS)
+src/pcre2fuzzcheck_16-pcre2_fuzzsupport.$(OBJEXT): \
+ src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+
+pcre2fuzzcheck-16$(EXEEXT): $(pcre2fuzzcheck_16_OBJECTS) $(pcre2fuzzcheck_16_DEPENDENCIES) $(EXTRA_pcre2fuzzcheck_16_DEPENDENCIES)
+ @rm -f pcre2fuzzcheck-16$(EXEEXT)
+ $(AM_V_CCLD)$(pcre2fuzzcheck_16_LINK) $(pcre2fuzzcheck_16_OBJECTS) $(pcre2fuzzcheck_16_LDADD) $(LIBS)
+src/pcre2fuzzcheck_32-pcre2_fuzzsupport.$(OBJEXT): \
+ src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
+
+pcre2fuzzcheck-32$(EXEEXT): $(pcre2fuzzcheck_32_OBJECTS) $(pcre2fuzzcheck_32_DEPENDENCIES) $(EXTRA_pcre2fuzzcheck_32_DEPENDENCIES)
+ @rm -f pcre2fuzzcheck-32$(EXEEXT)
+ $(AM_V_CCLD)$(pcre2fuzzcheck_32_LINK) $(pcre2fuzzcheck_32_OBJECTS) $(pcre2fuzzcheck_32_LDADD) $(LIBS)
+src/pcre2fuzzcheck_8-pcre2_fuzzsupport.$(OBJEXT): src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+
+pcre2fuzzcheck-8$(EXEEXT): $(pcre2fuzzcheck_8_OBJECTS) $(pcre2fuzzcheck_8_DEPENDENCIES) $(EXTRA_pcre2fuzzcheck_8_DEPENDENCIES)
+ @rm -f pcre2fuzzcheck-8$(EXEEXT)
+ $(AM_V_CCLD)$(pcre2fuzzcheck_8_LINK) $(pcre2fuzzcheck_8_OBJECTS) $(pcre2fuzzcheck_8_LDADD) $(LIBS)
+src/pcre2grep-pcre2grep.$(OBJEXT): src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+
+pcre2grep$(EXEEXT): $(pcre2grep_OBJECTS) $(pcre2grep_DEPENDENCIES) $(EXTRA_pcre2grep_DEPENDENCIES)
+ @rm -f pcre2grep$(EXEEXT)
+ $(AM_V_CCLD)$(pcre2grep_LINK) $(pcre2grep_OBJECTS) $(pcre2grep_LDADD) $(LIBS)
+src/pcre2posix_test-pcre2posix_test.$(OBJEXT): src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+
+pcre2posix_test$(EXEEXT): $(pcre2posix_test_OBJECTS) $(pcre2posix_test_DEPENDENCIES) $(EXTRA_pcre2posix_test_DEPENDENCIES)
+ @rm -f pcre2posix_test$(EXEEXT)
+ $(AM_V_CCLD)$(pcre2posix_test_LINK) $(pcre2posix_test_OBJECTS) $(pcre2posix_test_LDADD) $(LIBS)
+src/pcre2test-pcre2test.$(OBJEXT): src/$(am__dirstamp) \
+ src/$(DEPDIR)/$(am__dirstamp)
+
+pcre2test$(EXEEXT): $(pcre2test_OBJECTS) $(pcre2test_DEPENDENCIES) $(EXTRA_pcre2test_DEPENDENCIES)
+ @rm -f pcre2test$(EXEEXT)
+ $(AM_V_CCLD)$(pcre2test_LINK) $(pcre2test_OBJECTS) $(pcre2test_LDADD) $(LIBS)
+install-binSCRIPTS: $(bin_SCRIPTS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n' \
+ -e 'h;s|.*|.|' \
+ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) { files[d] = files[d] " " $$1; \
+ if (++n[d] == $(am__install_max)) { \
+ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
+ else { print "f", d "/" $$4, $$1 } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binSCRIPTS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 's,.*/,,;$(transform)'`; \
+ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+ -rm -f src/*.$(OBJEXT)
+ -rm -f src/*.lo
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_auto_possess.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_chartables.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_chkdint.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_compile.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_compile_cgroup.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_compile_class.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_config.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_convert.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_dfa_match.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_error.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_extuni.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_find_bracket.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_jit_compile.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_maketables.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_match.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_match_data.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_match_next.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_newline.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_ord2utf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_pattern_info.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_script_run.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_serialize.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_string_utils.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_study.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_substitute.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_substring.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_tables.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_ucd.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_valid_utf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_16_la-pcre2_xclass.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_auto_possess.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_chartables.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_chkdint.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_compile.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_compile_cgroup.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_compile_class.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_config.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_convert.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_dfa_match.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_error.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_extuni.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_find_bracket.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_jit_compile.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_maketables.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_match.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_match_data.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_match_next.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_newline.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_ord2utf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_pattern_info.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_script_run.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_serialize.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_string_utils.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_study.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_substitute.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_substring.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_tables.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_ucd.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_valid_utf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_32_la-pcre2_xclass.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_auto_possess.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_chartables.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_chkdint.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_compile.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_compile_cgroup.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_compile_class.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_config.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_context.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_convert.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_dfa_match.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_error.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_extuni.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_find_bracket.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_jit_compile.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_maketables.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_match.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_match_data.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_match_next.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_newline.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_ord2utf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_pattern_info.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_script_run.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_serialize.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_string_utils.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_study.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_substitute.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_substring.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_tables.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_ucd.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_valid_utf.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_8_la-pcre2_xclass.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/libpcre2_posix_la-pcre2posix.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pcre2_dftables.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pcre2_jit_test-pcre2_jit_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pcre2fuzzcheck_16-pcre2_fuzzsupport.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pcre2fuzzcheck_32-pcre2_fuzzsupport.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pcre2fuzzcheck_8-pcre2_fuzzsupport.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pcre2grep-pcre2grep.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pcre2posix_test-pcre2posix_test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pcre2test-pcre2test.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+src/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.o: src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_libs_libpcre2_fuzzsupport_16_a_CFLAGS) $(CFLAGS) -MT src/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.o -MD -MP -MF src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.Tpo -c -o src/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.o `test -f 'src/pcre2_fuzzsupport.c' || echo '$(srcdir)/'`src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.Tpo src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_fuzzsupport.c' object='src/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_libs_libpcre2_fuzzsupport_16_a_CFLAGS) $(CFLAGS) -c -o src/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.o `test -f 'src/pcre2_fuzzsupport.c' || echo '$(srcdir)/'`src/pcre2_fuzzsupport.c
+
+src/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.obj: src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_libs_libpcre2_fuzzsupport_16_a_CFLAGS) $(CFLAGS) -MT src/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.obj -MD -MP -MF src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.Tpo -c -o src/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.obj `if test -f 'src/pcre2_fuzzsupport.c'; then $(CYGPATH_W) 'src/pcre2_fuzzsupport.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2_fuzzsupport.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.Tpo src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_fuzzsupport.c' object='src/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_libs_libpcre2_fuzzsupport_16_a_CFLAGS) $(CFLAGS) -c -o src/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.obj `if test -f 'src/pcre2_fuzzsupport.c'; then $(CYGPATH_W) 'src/pcre2_fuzzsupport.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2_fuzzsupport.c'; fi`
+
+src/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.o: src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_libs_libpcre2_fuzzsupport_32_a_CFLAGS) $(CFLAGS) -MT src/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.o -MD -MP -MF src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.Tpo -c -o src/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.o `test -f 'src/pcre2_fuzzsupport.c' || echo '$(srcdir)/'`src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.Tpo src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_fuzzsupport.c' object='src/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_libs_libpcre2_fuzzsupport_32_a_CFLAGS) $(CFLAGS) -c -o src/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.o `test -f 'src/pcre2_fuzzsupport.c' || echo '$(srcdir)/'`src/pcre2_fuzzsupport.c
+
+src/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.obj: src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_libs_libpcre2_fuzzsupport_32_a_CFLAGS) $(CFLAGS) -MT src/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.obj -MD -MP -MF src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.Tpo -c -o src/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.obj `if test -f 'src/pcre2_fuzzsupport.c'; then $(CYGPATH_W) 'src/pcre2_fuzzsupport.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2_fuzzsupport.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.Tpo src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_fuzzsupport.c' object='src/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_libs_libpcre2_fuzzsupport_32_a_CFLAGS) $(CFLAGS) -c -o src/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.obj `if test -f 'src/pcre2_fuzzsupport.c'; then $(CYGPATH_W) 'src/pcre2_fuzzsupport.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2_fuzzsupport.c'; fi`
+
+src/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.o: src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_libs_libpcre2_fuzzsupport_a_CFLAGS) $(CFLAGS) -MT src/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.o -MD -MP -MF src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.Tpo -c -o src/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.o `test -f 'src/pcre2_fuzzsupport.c' || echo '$(srcdir)/'`src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.Tpo src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_fuzzsupport.c' object='src/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_libs_libpcre2_fuzzsupport_a_CFLAGS) $(CFLAGS) -c -o src/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.o `test -f 'src/pcre2_fuzzsupport.c' || echo '$(srcdir)/'`src/pcre2_fuzzsupport.c
+
+src/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.obj: src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_libs_libpcre2_fuzzsupport_a_CFLAGS) $(CFLAGS) -MT src/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.obj -MD -MP -MF src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.Tpo -c -o src/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.obj `if test -f 'src/pcre2_fuzzsupport.c'; then $(CYGPATH_W) 'src/pcre2_fuzzsupport.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2_fuzzsupport.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.Tpo src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_fuzzsupport.c' object='src/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(_libs_libpcre2_fuzzsupport_a_CFLAGS) $(CFLAGS) -c -o src/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.obj `if test -f 'src/pcre2_fuzzsupport.c'; then $(CYGPATH_W) 'src/pcre2_fuzzsupport.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2_fuzzsupport.c'; fi`
+
+src/libpcre2_16_la-pcre2_auto_possess.lo: src/pcre2_auto_possess.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_auto_possess.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_auto_possess.Tpo -c -o src/libpcre2_16_la-pcre2_auto_possess.lo `test -f 'src/pcre2_auto_possess.c' || echo '$(srcdir)/'`src/pcre2_auto_possess.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_auto_possess.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_auto_possess.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_auto_possess.c' object='src/libpcre2_16_la-pcre2_auto_possess.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_auto_possess.lo `test -f 'src/pcre2_auto_possess.c' || echo '$(srcdir)/'`src/pcre2_auto_possess.c
+
+src/libpcre2_16_la-pcre2_chkdint.lo: src/pcre2_chkdint.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_chkdint.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_chkdint.Tpo -c -o src/libpcre2_16_la-pcre2_chkdint.lo `test -f 'src/pcre2_chkdint.c' || echo '$(srcdir)/'`src/pcre2_chkdint.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_chkdint.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_chkdint.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_chkdint.c' object='src/libpcre2_16_la-pcre2_chkdint.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_chkdint.lo `test -f 'src/pcre2_chkdint.c' || echo '$(srcdir)/'`src/pcre2_chkdint.c
+
+src/libpcre2_16_la-pcre2_compile.lo: src/pcre2_compile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_compile.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_compile.Tpo -c -o src/libpcre2_16_la-pcre2_compile.lo `test -f 'src/pcre2_compile.c' || echo '$(srcdir)/'`src/pcre2_compile.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_compile.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_compile.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_compile.c' object='src/libpcre2_16_la-pcre2_compile.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_compile.lo `test -f 'src/pcre2_compile.c' || echo '$(srcdir)/'`src/pcre2_compile.c
+
+src/libpcre2_16_la-pcre2_compile_cgroup.lo: src/pcre2_compile_cgroup.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_compile_cgroup.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_compile_cgroup.Tpo -c -o src/libpcre2_16_la-pcre2_compile_cgroup.lo `test -f 'src/pcre2_compile_cgroup.c' || echo '$(srcdir)/'`src/pcre2_compile_cgroup.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_compile_cgroup.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_compile_cgroup.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_compile_cgroup.c' object='src/libpcre2_16_la-pcre2_compile_cgroup.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_compile_cgroup.lo `test -f 'src/pcre2_compile_cgroup.c' || echo '$(srcdir)/'`src/pcre2_compile_cgroup.c
+
+src/libpcre2_16_la-pcre2_compile_class.lo: src/pcre2_compile_class.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_compile_class.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_compile_class.Tpo -c -o src/libpcre2_16_la-pcre2_compile_class.lo `test -f 'src/pcre2_compile_class.c' || echo '$(srcdir)/'`src/pcre2_compile_class.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_compile_class.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_compile_class.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_compile_class.c' object='src/libpcre2_16_la-pcre2_compile_class.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_compile_class.lo `test -f 'src/pcre2_compile_class.c' || echo '$(srcdir)/'`src/pcre2_compile_class.c
+
+src/libpcre2_16_la-pcre2_config.lo: src/pcre2_config.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_config.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_config.Tpo -c -o src/libpcre2_16_la-pcre2_config.lo `test -f 'src/pcre2_config.c' || echo '$(srcdir)/'`src/pcre2_config.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_config.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_config.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_config.c' object='src/libpcre2_16_la-pcre2_config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_config.lo `test -f 'src/pcre2_config.c' || echo '$(srcdir)/'`src/pcre2_config.c
+
+src/libpcre2_16_la-pcre2_context.lo: src/pcre2_context.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_context.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_context.Tpo -c -o src/libpcre2_16_la-pcre2_context.lo `test -f 'src/pcre2_context.c' || echo '$(srcdir)/'`src/pcre2_context.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_context.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_context.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_context.c' object='src/libpcre2_16_la-pcre2_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_context.lo `test -f 'src/pcre2_context.c' || echo '$(srcdir)/'`src/pcre2_context.c
+
+src/libpcre2_16_la-pcre2_convert.lo: src/pcre2_convert.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_convert.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_convert.Tpo -c -o src/libpcre2_16_la-pcre2_convert.lo `test -f 'src/pcre2_convert.c' || echo '$(srcdir)/'`src/pcre2_convert.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_convert.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_convert.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_convert.c' object='src/libpcre2_16_la-pcre2_convert.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_convert.lo `test -f 'src/pcre2_convert.c' || echo '$(srcdir)/'`src/pcre2_convert.c
+
+src/libpcre2_16_la-pcre2_dfa_match.lo: src/pcre2_dfa_match.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_dfa_match.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_dfa_match.Tpo -c -o src/libpcre2_16_la-pcre2_dfa_match.lo `test -f 'src/pcre2_dfa_match.c' || echo '$(srcdir)/'`src/pcre2_dfa_match.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_dfa_match.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_dfa_match.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_dfa_match.c' object='src/libpcre2_16_la-pcre2_dfa_match.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_dfa_match.lo `test -f 'src/pcre2_dfa_match.c' || echo '$(srcdir)/'`src/pcre2_dfa_match.c
+
+src/libpcre2_16_la-pcre2_error.lo: src/pcre2_error.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_error.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_error.Tpo -c -o src/libpcre2_16_la-pcre2_error.lo `test -f 'src/pcre2_error.c' || echo '$(srcdir)/'`src/pcre2_error.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_error.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_error.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_error.c' object='src/libpcre2_16_la-pcre2_error.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_error.lo `test -f 'src/pcre2_error.c' || echo '$(srcdir)/'`src/pcre2_error.c
+
+src/libpcre2_16_la-pcre2_extuni.lo: src/pcre2_extuni.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_extuni.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_extuni.Tpo -c -o src/libpcre2_16_la-pcre2_extuni.lo `test -f 'src/pcre2_extuni.c' || echo '$(srcdir)/'`src/pcre2_extuni.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_extuni.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_extuni.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_extuni.c' object='src/libpcre2_16_la-pcre2_extuni.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_extuni.lo `test -f 'src/pcre2_extuni.c' || echo '$(srcdir)/'`src/pcre2_extuni.c
+
+src/libpcre2_16_la-pcre2_find_bracket.lo: src/pcre2_find_bracket.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_find_bracket.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_find_bracket.Tpo -c -o src/libpcre2_16_la-pcre2_find_bracket.lo `test -f 'src/pcre2_find_bracket.c' || echo '$(srcdir)/'`src/pcre2_find_bracket.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_find_bracket.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_find_bracket.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_find_bracket.c' object='src/libpcre2_16_la-pcre2_find_bracket.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_find_bracket.lo `test -f 'src/pcre2_find_bracket.c' || echo '$(srcdir)/'`src/pcre2_find_bracket.c
+
+src/libpcre2_16_la-pcre2_jit_compile.lo: src/pcre2_jit_compile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_jit_compile.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_jit_compile.Tpo -c -o src/libpcre2_16_la-pcre2_jit_compile.lo `test -f 'src/pcre2_jit_compile.c' || echo '$(srcdir)/'`src/pcre2_jit_compile.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_jit_compile.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_jit_compile.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_jit_compile.c' object='src/libpcre2_16_la-pcre2_jit_compile.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_jit_compile.lo `test -f 'src/pcre2_jit_compile.c' || echo '$(srcdir)/'`src/pcre2_jit_compile.c
+
+src/libpcre2_16_la-pcre2_maketables.lo: src/pcre2_maketables.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_maketables.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_maketables.Tpo -c -o src/libpcre2_16_la-pcre2_maketables.lo `test -f 'src/pcre2_maketables.c' || echo '$(srcdir)/'`src/pcre2_maketables.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_maketables.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_maketables.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_maketables.c' object='src/libpcre2_16_la-pcre2_maketables.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_maketables.lo `test -f 'src/pcre2_maketables.c' || echo '$(srcdir)/'`src/pcre2_maketables.c
+
+src/libpcre2_16_la-pcre2_match.lo: src/pcre2_match.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_match.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_match.Tpo -c -o src/libpcre2_16_la-pcre2_match.lo `test -f 'src/pcre2_match.c' || echo '$(srcdir)/'`src/pcre2_match.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_match.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_match.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_match.c' object='src/libpcre2_16_la-pcre2_match.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_match.lo `test -f 'src/pcre2_match.c' || echo '$(srcdir)/'`src/pcre2_match.c
+
+src/libpcre2_16_la-pcre2_match_data.lo: src/pcre2_match_data.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_match_data.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_match_data.Tpo -c -o src/libpcre2_16_la-pcre2_match_data.lo `test -f 'src/pcre2_match_data.c' || echo '$(srcdir)/'`src/pcre2_match_data.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_match_data.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_match_data.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_match_data.c' object='src/libpcre2_16_la-pcre2_match_data.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_match_data.lo `test -f 'src/pcre2_match_data.c' || echo '$(srcdir)/'`src/pcre2_match_data.c
+
+src/libpcre2_16_la-pcre2_match_next.lo: src/pcre2_match_next.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_match_next.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_match_next.Tpo -c -o src/libpcre2_16_la-pcre2_match_next.lo `test -f 'src/pcre2_match_next.c' || echo '$(srcdir)/'`src/pcre2_match_next.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_match_next.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_match_next.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_match_next.c' object='src/libpcre2_16_la-pcre2_match_next.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_match_next.lo `test -f 'src/pcre2_match_next.c' || echo '$(srcdir)/'`src/pcre2_match_next.c
+
+src/libpcre2_16_la-pcre2_newline.lo: src/pcre2_newline.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_newline.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_newline.Tpo -c -o src/libpcre2_16_la-pcre2_newline.lo `test -f 'src/pcre2_newline.c' || echo '$(srcdir)/'`src/pcre2_newline.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_newline.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_newline.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_newline.c' object='src/libpcre2_16_la-pcre2_newline.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_newline.lo `test -f 'src/pcre2_newline.c' || echo '$(srcdir)/'`src/pcre2_newline.c
+
+src/libpcre2_16_la-pcre2_ord2utf.lo: src/pcre2_ord2utf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_ord2utf.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_ord2utf.Tpo -c -o src/libpcre2_16_la-pcre2_ord2utf.lo `test -f 'src/pcre2_ord2utf.c' || echo '$(srcdir)/'`src/pcre2_ord2utf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_ord2utf.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_ord2utf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_ord2utf.c' object='src/libpcre2_16_la-pcre2_ord2utf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_ord2utf.lo `test -f 'src/pcre2_ord2utf.c' || echo '$(srcdir)/'`src/pcre2_ord2utf.c
+
+src/libpcre2_16_la-pcre2_pattern_info.lo: src/pcre2_pattern_info.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_pattern_info.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_pattern_info.Tpo -c -o src/libpcre2_16_la-pcre2_pattern_info.lo `test -f 'src/pcre2_pattern_info.c' || echo '$(srcdir)/'`src/pcre2_pattern_info.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_pattern_info.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_pattern_info.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_pattern_info.c' object='src/libpcre2_16_la-pcre2_pattern_info.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_pattern_info.lo `test -f 'src/pcre2_pattern_info.c' || echo '$(srcdir)/'`src/pcre2_pattern_info.c
+
+src/libpcre2_16_la-pcre2_script_run.lo: src/pcre2_script_run.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_script_run.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_script_run.Tpo -c -o src/libpcre2_16_la-pcre2_script_run.lo `test -f 'src/pcre2_script_run.c' || echo '$(srcdir)/'`src/pcre2_script_run.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_script_run.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_script_run.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_script_run.c' object='src/libpcre2_16_la-pcre2_script_run.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_script_run.lo `test -f 'src/pcre2_script_run.c' || echo '$(srcdir)/'`src/pcre2_script_run.c
+
+src/libpcre2_16_la-pcre2_serialize.lo: src/pcre2_serialize.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_serialize.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_serialize.Tpo -c -o src/libpcre2_16_la-pcre2_serialize.lo `test -f 'src/pcre2_serialize.c' || echo '$(srcdir)/'`src/pcre2_serialize.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_serialize.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_serialize.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_serialize.c' object='src/libpcre2_16_la-pcre2_serialize.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_serialize.lo `test -f 'src/pcre2_serialize.c' || echo '$(srcdir)/'`src/pcre2_serialize.c
+
+src/libpcre2_16_la-pcre2_string_utils.lo: src/pcre2_string_utils.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_string_utils.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_string_utils.Tpo -c -o src/libpcre2_16_la-pcre2_string_utils.lo `test -f 'src/pcre2_string_utils.c' || echo '$(srcdir)/'`src/pcre2_string_utils.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_string_utils.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_string_utils.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_string_utils.c' object='src/libpcre2_16_la-pcre2_string_utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_string_utils.lo `test -f 'src/pcre2_string_utils.c' || echo '$(srcdir)/'`src/pcre2_string_utils.c
+
+src/libpcre2_16_la-pcre2_study.lo: src/pcre2_study.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_study.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_study.Tpo -c -o src/libpcre2_16_la-pcre2_study.lo `test -f 'src/pcre2_study.c' || echo '$(srcdir)/'`src/pcre2_study.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_study.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_study.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_study.c' object='src/libpcre2_16_la-pcre2_study.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_study.lo `test -f 'src/pcre2_study.c' || echo '$(srcdir)/'`src/pcre2_study.c
+
+src/libpcre2_16_la-pcre2_substitute.lo: src/pcre2_substitute.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_substitute.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_substitute.Tpo -c -o src/libpcre2_16_la-pcre2_substitute.lo `test -f 'src/pcre2_substitute.c' || echo '$(srcdir)/'`src/pcre2_substitute.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_substitute.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_substitute.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_substitute.c' object='src/libpcre2_16_la-pcre2_substitute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_substitute.lo `test -f 'src/pcre2_substitute.c' || echo '$(srcdir)/'`src/pcre2_substitute.c
+
+src/libpcre2_16_la-pcre2_substring.lo: src/pcre2_substring.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_substring.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_substring.Tpo -c -o src/libpcre2_16_la-pcre2_substring.lo `test -f 'src/pcre2_substring.c' || echo '$(srcdir)/'`src/pcre2_substring.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_substring.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_substring.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_substring.c' object='src/libpcre2_16_la-pcre2_substring.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_substring.lo `test -f 'src/pcre2_substring.c' || echo '$(srcdir)/'`src/pcre2_substring.c
+
+src/libpcre2_16_la-pcre2_tables.lo: src/pcre2_tables.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_tables.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_tables.Tpo -c -o src/libpcre2_16_la-pcre2_tables.lo `test -f 'src/pcre2_tables.c' || echo '$(srcdir)/'`src/pcre2_tables.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_tables.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_tables.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_tables.c' object='src/libpcre2_16_la-pcre2_tables.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_tables.lo `test -f 'src/pcre2_tables.c' || echo '$(srcdir)/'`src/pcre2_tables.c
+
+src/libpcre2_16_la-pcre2_ucd.lo: src/pcre2_ucd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_ucd.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_ucd.Tpo -c -o src/libpcre2_16_la-pcre2_ucd.lo `test -f 'src/pcre2_ucd.c' || echo '$(srcdir)/'`src/pcre2_ucd.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_ucd.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_ucd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_ucd.c' object='src/libpcre2_16_la-pcre2_ucd.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_ucd.lo `test -f 'src/pcre2_ucd.c' || echo '$(srcdir)/'`src/pcre2_ucd.c
+
+src/libpcre2_16_la-pcre2_valid_utf.lo: src/pcre2_valid_utf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_valid_utf.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_valid_utf.Tpo -c -o src/libpcre2_16_la-pcre2_valid_utf.lo `test -f 'src/pcre2_valid_utf.c' || echo '$(srcdir)/'`src/pcre2_valid_utf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_valid_utf.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_valid_utf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_valid_utf.c' object='src/libpcre2_16_la-pcre2_valid_utf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_valid_utf.lo `test -f 'src/pcre2_valid_utf.c' || echo '$(srcdir)/'`src/pcre2_valid_utf.c
+
+src/libpcre2_16_la-pcre2_xclass.lo: src/pcre2_xclass.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_xclass.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_xclass.Tpo -c -o src/libpcre2_16_la-pcre2_xclass.lo `test -f 'src/pcre2_xclass.c' || echo '$(srcdir)/'`src/pcre2_xclass.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_xclass.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_xclass.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_xclass.c' object='src/libpcre2_16_la-pcre2_xclass.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_xclass.lo `test -f 'src/pcre2_xclass.c' || echo '$(srcdir)/'`src/pcre2_xclass.c
+
+src/libpcre2_16_la-pcre2_chartables.lo: src/pcre2_chartables.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_16_la-pcre2_chartables.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_16_la-pcre2_chartables.Tpo -c -o src/libpcre2_16_la-pcre2_chartables.lo `test -f 'src/pcre2_chartables.c' || echo '$(srcdir)/'`src/pcre2_chartables.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_16_la-pcre2_chartables.Tpo src/$(DEPDIR)/libpcre2_16_la-pcre2_chartables.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_chartables.c' object='src/libpcre2_16_la-pcre2_chartables.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_16_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_16_la-pcre2_chartables.lo `test -f 'src/pcre2_chartables.c' || echo '$(srcdir)/'`src/pcre2_chartables.c
+
+src/libpcre2_32_la-pcre2_auto_possess.lo: src/pcre2_auto_possess.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_auto_possess.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_auto_possess.Tpo -c -o src/libpcre2_32_la-pcre2_auto_possess.lo `test -f 'src/pcre2_auto_possess.c' || echo '$(srcdir)/'`src/pcre2_auto_possess.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_auto_possess.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_auto_possess.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_auto_possess.c' object='src/libpcre2_32_la-pcre2_auto_possess.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_auto_possess.lo `test -f 'src/pcre2_auto_possess.c' || echo '$(srcdir)/'`src/pcre2_auto_possess.c
+
+src/libpcre2_32_la-pcre2_chkdint.lo: src/pcre2_chkdint.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_chkdint.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_chkdint.Tpo -c -o src/libpcre2_32_la-pcre2_chkdint.lo `test -f 'src/pcre2_chkdint.c' || echo '$(srcdir)/'`src/pcre2_chkdint.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_chkdint.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_chkdint.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_chkdint.c' object='src/libpcre2_32_la-pcre2_chkdint.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_chkdint.lo `test -f 'src/pcre2_chkdint.c' || echo '$(srcdir)/'`src/pcre2_chkdint.c
+
+src/libpcre2_32_la-pcre2_compile.lo: src/pcre2_compile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_compile.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_compile.Tpo -c -o src/libpcre2_32_la-pcre2_compile.lo `test -f 'src/pcre2_compile.c' || echo '$(srcdir)/'`src/pcre2_compile.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_compile.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_compile.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_compile.c' object='src/libpcre2_32_la-pcre2_compile.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_compile.lo `test -f 'src/pcre2_compile.c' || echo '$(srcdir)/'`src/pcre2_compile.c
+
+src/libpcre2_32_la-pcre2_compile_cgroup.lo: src/pcre2_compile_cgroup.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_compile_cgroup.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_compile_cgroup.Tpo -c -o src/libpcre2_32_la-pcre2_compile_cgroup.lo `test -f 'src/pcre2_compile_cgroup.c' || echo '$(srcdir)/'`src/pcre2_compile_cgroup.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_compile_cgroup.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_compile_cgroup.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_compile_cgroup.c' object='src/libpcre2_32_la-pcre2_compile_cgroup.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_compile_cgroup.lo `test -f 'src/pcre2_compile_cgroup.c' || echo '$(srcdir)/'`src/pcre2_compile_cgroup.c
+
+src/libpcre2_32_la-pcre2_compile_class.lo: src/pcre2_compile_class.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_compile_class.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_compile_class.Tpo -c -o src/libpcre2_32_la-pcre2_compile_class.lo `test -f 'src/pcre2_compile_class.c' || echo '$(srcdir)/'`src/pcre2_compile_class.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_compile_class.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_compile_class.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_compile_class.c' object='src/libpcre2_32_la-pcre2_compile_class.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_compile_class.lo `test -f 'src/pcre2_compile_class.c' || echo '$(srcdir)/'`src/pcre2_compile_class.c
+
+src/libpcre2_32_la-pcre2_config.lo: src/pcre2_config.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_config.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_config.Tpo -c -o src/libpcre2_32_la-pcre2_config.lo `test -f 'src/pcre2_config.c' || echo '$(srcdir)/'`src/pcre2_config.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_config.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_config.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_config.c' object='src/libpcre2_32_la-pcre2_config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_config.lo `test -f 'src/pcre2_config.c' || echo '$(srcdir)/'`src/pcre2_config.c
+
+src/libpcre2_32_la-pcre2_context.lo: src/pcre2_context.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_context.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_context.Tpo -c -o src/libpcre2_32_la-pcre2_context.lo `test -f 'src/pcre2_context.c' || echo '$(srcdir)/'`src/pcre2_context.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_context.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_context.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_context.c' object='src/libpcre2_32_la-pcre2_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_context.lo `test -f 'src/pcre2_context.c' || echo '$(srcdir)/'`src/pcre2_context.c
+
+src/libpcre2_32_la-pcre2_convert.lo: src/pcre2_convert.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_convert.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_convert.Tpo -c -o src/libpcre2_32_la-pcre2_convert.lo `test -f 'src/pcre2_convert.c' || echo '$(srcdir)/'`src/pcre2_convert.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_convert.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_convert.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_convert.c' object='src/libpcre2_32_la-pcre2_convert.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_convert.lo `test -f 'src/pcre2_convert.c' || echo '$(srcdir)/'`src/pcre2_convert.c
+
+src/libpcre2_32_la-pcre2_dfa_match.lo: src/pcre2_dfa_match.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_dfa_match.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_dfa_match.Tpo -c -o src/libpcre2_32_la-pcre2_dfa_match.lo `test -f 'src/pcre2_dfa_match.c' || echo '$(srcdir)/'`src/pcre2_dfa_match.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_dfa_match.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_dfa_match.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_dfa_match.c' object='src/libpcre2_32_la-pcre2_dfa_match.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_dfa_match.lo `test -f 'src/pcre2_dfa_match.c' || echo '$(srcdir)/'`src/pcre2_dfa_match.c
+
+src/libpcre2_32_la-pcre2_error.lo: src/pcre2_error.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_error.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_error.Tpo -c -o src/libpcre2_32_la-pcre2_error.lo `test -f 'src/pcre2_error.c' || echo '$(srcdir)/'`src/pcre2_error.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_error.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_error.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_error.c' object='src/libpcre2_32_la-pcre2_error.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_error.lo `test -f 'src/pcre2_error.c' || echo '$(srcdir)/'`src/pcre2_error.c
+
+src/libpcre2_32_la-pcre2_extuni.lo: src/pcre2_extuni.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_extuni.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_extuni.Tpo -c -o src/libpcre2_32_la-pcre2_extuni.lo `test -f 'src/pcre2_extuni.c' || echo '$(srcdir)/'`src/pcre2_extuni.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_extuni.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_extuni.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_extuni.c' object='src/libpcre2_32_la-pcre2_extuni.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_extuni.lo `test -f 'src/pcre2_extuni.c' || echo '$(srcdir)/'`src/pcre2_extuni.c
+
+src/libpcre2_32_la-pcre2_find_bracket.lo: src/pcre2_find_bracket.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_find_bracket.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_find_bracket.Tpo -c -o src/libpcre2_32_la-pcre2_find_bracket.lo `test -f 'src/pcre2_find_bracket.c' || echo '$(srcdir)/'`src/pcre2_find_bracket.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_find_bracket.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_find_bracket.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_find_bracket.c' object='src/libpcre2_32_la-pcre2_find_bracket.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_find_bracket.lo `test -f 'src/pcre2_find_bracket.c' || echo '$(srcdir)/'`src/pcre2_find_bracket.c
+
+src/libpcre2_32_la-pcre2_jit_compile.lo: src/pcre2_jit_compile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_jit_compile.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_jit_compile.Tpo -c -o src/libpcre2_32_la-pcre2_jit_compile.lo `test -f 'src/pcre2_jit_compile.c' || echo '$(srcdir)/'`src/pcre2_jit_compile.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_jit_compile.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_jit_compile.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_jit_compile.c' object='src/libpcre2_32_la-pcre2_jit_compile.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_jit_compile.lo `test -f 'src/pcre2_jit_compile.c' || echo '$(srcdir)/'`src/pcre2_jit_compile.c
+
+src/libpcre2_32_la-pcre2_maketables.lo: src/pcre2_maketables.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_maketables.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_maketables.Tpo -c -o src/libpcre2_32_la-pcre2_maketables.lo `test -f 'src/pcre2_maketables.c' || echo '$(srcdir)/'`src/pcre2_maketables.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_maketables.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_maketables.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_maketables.c' object='src/libpcre2_32_la-pcre2_maketables.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_maketables.lo `test -f 'src/pcre2_maketables.c' || echo '$(srcdir)/'`src/pcre2_maketables.c
+
+src/libpcre2_32_la-pcre2_match.lo: src/pcre2_match.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_match.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_match.Tpo -c -o src/libpcre2_32_la-pcre2_match.lo `test -f 'src/pcre2_match.c' || echo '$(srcdir)/'`src/pcre2_match.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_match.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_match.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_match.c' object='src/libpcre2_32_la-pcre2_match.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_match.lo `test -f 'src/pcre2_match.c' || echo '$(srcdir)/'`src/pcre2_match.c
+
+src/libpcre2_32_la-pcre2_match_data.lo: src/pcre2_match_data.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_match_data.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_match_data.Tpo -c -o src/libpcre2_32_la-pcre2_match_data.lo `test -f 'src/pcre2_match_data.c' || echo '$(srcdir)/'`src/pcre2_match_data.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_match_data.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_match_data.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_match_data.c' object='src/libpcre2_32_la-pcre2_match_data.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_match_data.lo `test -f 'src/pcre2_match_data.c' || echo '$(srcdir)/'`src/pcre2_match_data.c
+
+src/libpcre2_32_la-pcre2_match_next.lo: src/pcre2_match_next.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_match_next.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_match_next.Tpo -c -o src/libpcre2_32_la-pcre2_match_next.lo `test -f 'src/pcre2_match_next.c' || echo '$(srcdir)/'`src/pcre2_match_next.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_match_next.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_match_next.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_match_next.c' object='src/libpcre2_32_la-pcre2_match_next.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_match_next.lo `test -f 'src/pcre2_match_next.c' || echo '$(srcdir)/'`src/pcre2_match_next.c
+
+src/libpcre2_32_la-pcre2_newline.lo: src/pcre2_newline.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_newline.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_newline.Tpo -c -o src/libpcre2_32_la-pcre2_newline.lo `test -f 'src/pcre2_newline.c' || echo '$(srcdir)/'`src/pcre2_newline.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_newline.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_newline.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_newline.c' object='src/libpcre2_32_la-pcre2_newline.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_newline.lo `test -f 'src/pcre2_newline.c' || echo '$(srcdir)/'`src/pcre2_newline.c
+
+src/libpcre2_32_la-pcre2_ord2utf.lo: src/pcre2_ord2utf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_ord2utf.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_ord2utf.Tpo -c -o src/libpcre2_32_la-pcre2_ord2utf.lo `test -f 'src/pcre2_ord2utf.c' || echo '$(srcdir)/'`src/pcre2_ord2utf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_ord2utf.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_ord2utf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_ord2utf.c' object='src/libpcre2_32_la-pcre2_ord2utf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_ord2utf.lo `test -f 'src/pcre2_ord2utf.c' || echo '$(srcdir)/'`src/pcre2_ord2utf.c
+
+src/libpcre2_32_la-pcre2_pattern_info.lo: src/pcre2_pattern_info.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_pattern_info.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_pattern_info.Tpo -c -o src/libpcre2_32_la-pcre2_pattern_info.lo `test -f 'src/pcre2_pattern_info.c' || echo '$(srcdir)/'`src/pcre2_pattern_info.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_pattern_info.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_pattern_info.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_pattern_info.c' object='src/libpcre2_32_la-pcre2_pattern_info.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_pattern_info.lo `test -f 'src/pcre2_pattern_info.c' || echo '$(srcdir)/'`src/pcre2_pattern_info.c
+
+src/libpcre2_32_la-pcre2_script_run.lo: src/pcre2_script_run.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_script_run.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_script_run.Tpo -c -o src/libpcre2_32_la-pcre2_script_run.lo `test -f 'src/pcre2_script_run.c' || echo '$(srcdir)/'`src/pcre2_script_run.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_script_run.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_script_run.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_script_run.c' object='src/libpcre2_32_la-pcre2_script_run.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_script_run.lo `test -f 'src/pcre2_script_run.c' || echo '$(srcdir)/'`src/pcre2_script_run.c
+
+src/libpcre2_32_la-pcre2_serialize.lo: src/pcre2_serialize.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_serialize.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_serialize.Tpo -c -o src/libpcre2_32_la-pcre2_serialize.lo `test -f 'src/pcre2_serialize.c' || echo '$(srcdir)/'`src/pcre2_serialize.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_serialize.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_serialize.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_serialize.c' object='src/libpcre2_32_la-pcre2_serialize.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_serialize.lo `test -f 'src/pcre2_serialize.c' || echo '$(srcdir)/'`src/pcre2_serialize.c
+
+src/libpcre2_32_la-pcre2_string_utils.lo: src/pcre2_string_utils.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_string_utils.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_string_utils.Tpo -c -o src/libpcre2_32_la-pcre2_string_utils.lo `test -f 'src/pcre2_string_utils.c' || echo '$(srcdir)/'`src/pcre2_string_utils.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_string_utils.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_string_utils.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_string_utils.c' object='src/libpcre2_32_la-pcre2_string_utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_string_utils.lo `test -f 'src/pcre2_string_utils.c' || echo '$(srcdir)/'`src/pcre2_string_utils.c
+
+src/libpcre2_32_la-pcre2_study.lo: src/pcre2_study.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_study.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_study.Tpo -c -o src/libpcre2_32_la-pcre2_study.lo `test -f 'src/pcre2_study.c' || echo '$(srcdir)/'`src/pcre2_study.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_study.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_study.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_study.c' object='src/libpcre2_32_la-pcre2_study.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_study.lo `test -f 'src/pcre2_study.c' || echo '$(srcdir)/'`src/pcre2_study.c
+
+src/libpcre2_32_la-pcre2_substitute.lo: src/pcre2_substitute.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_substitute.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_substitute.Tpo -c -o src/libpcre2_32_la-pcre2_substitute.lo `test -f 'src/pcre2_substitute.c' || echo '$(srcdir)/'`src/pcre2_substitute.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_substitute.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_substitute.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_substitute.c' object='src/libpcre2_32_la-pcre2_substitute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_substitute.lo `test -f 'src/pcre2_substitute.c' || echo '$(srcdir)/'`src/pcre2_substitute.c
+
+src/libpcre2_32_la-pcre2_substring.lo: src/pcre2_substring.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_substring.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_substring.Tpo -c -o src/libpcre2_32_la-pcre2_substring.lo `test -f 'src/pcre2_substring.c' || echo '$(srcdir)/'`src/pcre2_substring.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_substring.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_substring.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_substring.c' object='src/libpcre2_32_la-pcre2_substring.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_substring.lo `test -f 'src/pcre2_substring.c' || echo '$(srcdir)/'`src/pcre2_substring.c
+
+src/libpcre2_32_la-pcre2_tables.lo: src/pcre2_tables.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_tables.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_tables.Tpo -c -o src/libpcre2_32_la-pcre2_tables.lo `test -f 'src/pcre2_tables.c' || echo '$(srcdir)/'`src/pcre2_tables.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_tables.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_tables.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_tables.c' object='src/libpcre2_32_la-pcre2_tables.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_tables.lo `test -f 'src/pcre2_tables.c' || echo '$(srcdir)/'`src/pcre2_tables.c
+
+src/libpcre2_32_la-pcre2_ucd.lo: src/pcre2_ucd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_ucd.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_ucd.Tpo -c -o src/libpcre2_32_la-pcre2_ucd.lo `test -f 'src/pcre2_ucd.c' || echo '$(srcdir)/'`src/pcre2_ucd.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_ucd.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_ucd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_ucd.c' object='src/libpcre2_32_la-pcre2_ucd.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_ucd.lo `test -f 'src/pcre2_ucd.c' || echo '$(srcdir)/'`src/pcre2_ucd.c
+
+src/libpcre2_32_la-pcre2_valid_utf.lo: src/pcre2_valid_utf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_valid_utf.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_valid_utf.Tpo -c -o src/libpcre2_32_la-pcre2_valid_utf.lo `test -f 'src/pcre2_valid_utf.c' || echo '$(srcdir)/'`src/pcre2_valid_utf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_valid_utf.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_valid_utf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_valid_utf.c' object='src/libpcre2_32_la-pcre2_valid_utf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_valid_utf.lo `test -f 'src/pcre2_valid_utf.c' || echo '$(srcdir)/'`src/pcre2_valid_utf.c
+
+src/libpcre2_32_la-pcre2_xclass.lo: src/pcre2_xclass.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_xclass.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_xclass.Tpo -c -o src/libpcre2_32_la-pcre2_xclass.lo `test -f 'src/pcre2_xclass.c' || echo '$(srcdir)/'`src/pcre2_xclass.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_xclass.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_xclass.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_xclass.c' object='src/libpcre2_32_la-pcre2_xclass.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_xclass.lo `test -f 'src/pcre2_xclass.c' || echo '$(srcdir)/'`src/pcre2_xclass.c
+
+src/libpcre2_32_la-pcre2_chartables.lo: src/pcre2_chartables.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_32_la-pcre2_chartables.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_32_la-pcre2_chartables.Tpo -c -o src/libpcre2_32_la-pcre2_chartables.lo `test -f 'src/pcre2_chartables.c' || echo '$(srcdir)/'`src/pcre2_chartables.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_32_la-pcre2_chartables.Tpo src/$(DEPDIR)/libpcre2_32_la-pcre2_chartables.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_chartables.c' object='src/libpcre2_32_la-pcre2_chartables.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_32_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_32_la-pcre2_chartables.lo `test -f 'src/pcre2_chartables.c' || echo '$(srcdir)/'`src/pcre2_chartables.c
+
+src/libpcre2_8_la-pcre2_auto_possess.lo: src/pcre2_auto_possess.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_auto_possess.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_auto_possess.Tpo -c -o src/libpcre2_8_la-pcre2_auto_possess.lo `test -f 'src/pcre2_auto_possess.c' || echo '$(srcdir)/'`src/pcre2_auto_possess.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_auto_possess.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_auto_possess.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_auto_possess.c' object='src/libpcre2_8_la-pcre2_auto_possess.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_auto_possess.lo `test -f 'src/pcre2_auto_possess.c' || echo '$(srcdir)/'`src/pcre2_auto_possess.c
+
+src/libpcre2_8_la-pcre2_chkdint.lo: src/pcre2_chkdint.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_chkdint.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_chkdint.Tpo -c -o src/libpcre2_8_la-pcre2_chkdint.lo `test -f 'src/pcre2_chkdint.c' || echo '$(srcdir)/'`src/pcre2_chkdint.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_chkdint.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_chkdint.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_chkdint.c' object='src/libpcre2_8_la-pcre2_chkdint.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_chkdint.lo `test -f 'src/pcre2_chkdint.c' || echo '$(srcdir)/'`src/pcre2_chkdint.c
+
+src/libpcre2_8_la-pcre2_compile.lo: src/pcre2_compile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_compile.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_compile.Tpo -c -o src/libpcre2_8_la-pcre2_compile.lo `test -f 'src/pcre2_compile.c' || echo '$(srcdir)/'`src/pcre2_compile.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_compile.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_compile.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_compile.c' object='src/libpcre2_8_la-pcre2_compile.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_compile.lo `test -f 'src/pcre2_compile.c' || echo '$(srcdir)/'`src/pcre2_compile.c
+
+src/libpcre2_8_la-pcre2_compile_cgroup.lo: src/pcre2_compile_cgroup.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_compile_cgroup.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_compile_cgroup.Tpo -c -o src/libpcre2_8_la-pcre2_compile_cgroup.lo `test -f 'src/pcre2_compile_cgroup.c' || echo '$(srcdir)/'`src/pcre2_compile_cgroup.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_compile_cgroup.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_compile_cgroup.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_compile_cgroup.c' object='src/libpcre2_8_la-pcre2_compile_cgroup.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_compile_cgroup.lo `test -f 'src/pcre2_compile_cgroup.c' || echo '$(srcdir)/'`src/pcre2_compile_cgroup.c
+
+src/libpcre2_8_la-pcre2_compile_class.lo: src/pcre2_compile_class.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_compile_class.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_compile_class.Tpo -c -o src/libpcre2_8_la-pcre2_compile_class.lo `test -f 'src/pcre2_compile_class.c' || echo '$(srcdir)/'`src/pcre2_compile_class.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_compile_class.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_compile_class.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_compile_class.c' object='src/libpcre2_8_la-pcre2_compile_class.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_compile_class.lo `test -f 'src/pcre2_compile_class.c' || echo '$(srcdir)/'`src/pcre2_compile_class.c
+
+src/libpcre2_8_la-pcre2_config.lo: src/pcre2_config.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_config.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_config.Tpo -c -o src/libpcre2_8_la-pcre2_config.lo `test -f 'src/pcre2_config.c' || echo '$(srcdir)/'`src/pcre2_config.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_config.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_config.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_config.c' object='src/libpcre2_8_la-pcre2_config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_config.lo `test -f 'src/pcre2_config.c' || echo '$(srcdir)/'`src/pcre2_config.c
+
+src/libpcre2_8_la-pcre2_context.lo: src/pcre2_context.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_context.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_context.Tpo -c -o src/libpcre2_8_la-pcre2_context.lo `test -f 'src/pcre2_context.c' || echo '$(srcdir)/'`src/pcre2_context.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_context.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_context.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_context.c' object='src/libpcre2_8_la-pcre2_context.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_context.lo `test -f 'src/pcre2_context.c' || echo '$(srcdir)/'`src/pcre2_context.c
+
+src/libpcre2_8_la-pcre2_convert.lo: src/pcre2_convert.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_convert.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_convert.Tpo -c -o src/libpcre2_8_la-pcre2_convert.lo `test -f 'src/pcre2_convert.c' || echo '$(srcdir)/'`src/pcre2_convert.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_convert.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_convert.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_convert.c' object='src/libpcre2_8_la-pcre2_convert.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_convert.lo `test -f 'src/pcre2_convert.c' || echo '$(srcdir)/'`src/pcre2_convert.c
+
+src/libpcre2_8_la-pcre2_dfa_match.lo: src/pcre2_dfa_match.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_dfa_match.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_dfa_match.Tpo -c -o src/libpcre2_8_la-pcre2_dfa_match.lo `test -f 'src/pcre2_dfa_match.c' || echo '$(srcdir)/'`src/pcre2_dfa_match.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_dfa_match.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_dfa_match.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_dfa_match.c' object='src/libpcre2_8_la-pcre2_dfa_match.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_dfa_match.lo `test -f 'src/pcre2_dfa_match.c' || echo '$(srcdir)/'`src/pcre2_dfa_match.c
+
+src/libpcre2_8_la-pcre2_error.lo: src/pcre2_error.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_error.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_error.Tpo -c -o src/libpcre2_8_la-pcre2_error.lo `test -f 'src/pcre2_error.c' || echo '$(srcdir)/'`src/pcre2_error.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_error.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_error.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_error.c' object='src/libpcre2_8_la-pcre2_error.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_error.lo `test -f 'src/pcre2_error.c' || echo '$(srcdir)/'`src/pcre2_error.c
+
+src/libpcre2_8_la-pcre2_extuni.lo: src/pcre2_extuni.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_extuni.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_extuni.Tpo -c -o src/libpcre2_8_la-pcre2_extuni.lo `test -f 'src/pcre2_extuni.c' || echo '$(srcdir)/'`src/pcre2_extuni.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_extuni.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_extuni.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_extuni.c' object='src/libpcre2_8_la-pcre2_extuni.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_extuni.lo `test -f 'src/pcre2_extuni.c' || echo '$(srcdir)/'`src/pcre2_extuni.c
+
+src/libpcre2_8_la-pcre2_find_bracket.lo: src/pcre2_find_bracket.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_find_bracket.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_find_bracket.Tpo -c -o src/libpcre2_8_la-pcre2_find_bracket.lo `test -f 'src/pcre2_find_bracket.c' || echo '$(srcdir)/'`src/pcre2_find_bracket.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_find_bracket.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_find_bracket.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_find_bracket.c' object='src/libpcre2_8_la-pcre2_find_bracket.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_find_bracket.lo `test -f 'src/pcre2_find_bracket.c' || echo '$(srcdir)/'`src/pcre2_find_bracket.c
+
+src/libpcre2_8_la-pcre2_jit_compile.lo: src/pcre2_jit_compile.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_jit_compile.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_jit_compile.Tpo -c -o src/libpcre2_8_la-pcre2_jit_compile.lo `test -f 'src/pcre2_jit_compile.c' || echo '$(srcdir)/'`src/pcre2_jit_compile.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_jit_compile.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_jit_compile.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_jit_compile.c' object='src/libpcre2_8_la-pcre2_jit_compile.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_jit_compile.lo `test -f 'src/pcre2_jit_compile.c' || echo '$(srcdir)/'`src/pcre2_jit_compile.c
+
+src/libpcre2_8_la-pcre2_maketables.lo: src/pcre2_maketables.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_maketables.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_maketables.Tpo -c -o src/libpcre2_8_la-pcre2_maketables.lo `test -f 'src/pcre2_maketables.c' || echo '$(srcdir)/'`src/pcre2_maketables.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_maketables.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_maketables.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_maketables.c' object='src/libpcre2_8_la-pcre2_maketables.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_maketables.lo `test -f 'src/pcre2_maketables.c' || echo '$(srcdir)/'`src/pcre2_maketables.c
+
+src/libpcre2_8_la-pcre2_match.lo: src/pcre2_match.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_match.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_match.Tpo -c -o src/libpcre2_8_la-pcre2_match.lo `test -f 'src/pcre2_match.c' || echo '$(srcdir)/'`src/pcre2_match.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_match.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_match.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_match.c' object='src/libpcre2_8_la-pcre2_match.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_match.lo `test -f 'src/pcre2_match.c' || echo '$(srcdir)/'`src/pcre2_match.c
+
+src/libpcre2_8_la-pcre2_match_data.lo: src/pcre2_match_data.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_match_data.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_match_data.Tpo -c -o src/libpcre2_8_la-pcre2_match_data.lo `test -f 'src/pcre2_match_data.c' || echo '$(srcdir)/'`src/pcre2_match_data.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_match_data.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_match_data.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_match_data.c' object='src/libpcre2_8_la-pcre2_match_data.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_match_data.lo `test -f 'src/pcre2_match_data.c' || echo '$(srcdir)/'`src/pcre2_match_data.c
+
+src/libpcre2_8_la-pcre2_match_next.lo: src/pcre2_match_next.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_match_next.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_match_next.Tpo -c -o src/libpcre2_8_la-pcre2_match_next.lo `test -f 'src/pcre2_match_next.c' || echo '$(srcdir)/'`src/pcre2_match_next.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_match_next.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_match_next.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_match_next.c' object='src/libpcre2_8_la-pcre2_match_next.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_match_next.lo `test -f 'src/pcre2_match_next.c' || echo '$(srcdir)/'`src/pcre2_match_next.c
+
+src/libpcre2_8_la-pcre2_newline.lo: src/pcre2_newline.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_newline.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_newline.Tpo -c -o src/libpcre2_8_la-pcre2_newline.lo `test -f 'src/pcre2_newline.c' || echo '$(srcdir)/'`src/pcre2_newline.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_newline.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_newline.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_newline.c' object='src/libpcre2_8_la-pcre2_newline.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_newline.lo `test -f 'src/pcre2_newline.c' || echo '$(srcdir)/'`src/pcre2_newline.c
+
+src/libpcre2_8_la-pcre2_ord2utf.lo: src/pcre2_ord2utf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_ord2utf.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_ord2utf.Tpo -c -o src/libpcre2_8_la-pcre2_ord2utf.lo `test -f 'src/pcre2_ord2utf.c' || echo '$(srcdir)/'`src/pcre2_ord2utf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_ord2utf.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_ord2utf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_ord2utf.c' object='src/libpcre2_8_la-pcre2_ord2utf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_ord2utf.lo `test -f 'src/pcre2_ord2utf.c' || echo '$(srcdir)/'`src/pcre2_ord2utf.c
+
+src/libpcre2_8_la-pcre2_pattern_info.lo: src/pcre2_pattern_info.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_pattern_info.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_pattern_info.Tpo -c -o src/libpcre2_8_la-pcre2_pattern_info.lo `test -f 'src/pcre2_pattern_info.c' || echo '$(srcdir)/'`src/pcre2_pattern_info.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_pattern_info.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_pattern_info.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_pattern_info.c' object='src/libpcre2_8_la-pcre2_pattern_info.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_pattern_info.lo `test -f 'src/pcre2_pattern_info.c' || echo '$(srcdir)/'`src/pcre2_pattern_info.c
+
+src/libpcre2_8_la-pcre2_script_run.lo: src/pcre2_script_run.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_script_run.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_script_run.Tpo -c -o src/libpcre2_8_la-pcre2_script_run.lo `test -f 'src/pcre2_script_run.c' || echo '$(srcdir)/'`src/pcre2_script_run.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_script_run.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_script_run.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_script_run.c' object='src/libpcre2_8_la-pcre2_script_run.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_script_run.lo `test -f 'src/pcre2_script_run.c' || echo '$(srcdir)/'`src/pcre2_script_run.c
+
+src/libpcre2_8_la-pcre2_serialize.lo: src/pcre2_serialize.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_serialize.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_serialize.Tpo -c -o src/libpcre2_8_la-pcre2_serialize.lo `test -f 'src/pcre2_serialize.c' || echo '$(srcdir)/'`src/pcre2_serialize.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_serialize.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_serialize.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_serialize.c' object='src/libpcre2_8_la-pcre2_serialize.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_serialize.lo `test -f 'src/pcre2_serialize.c' || echo '$(srcdir)/'`src/pcre2_serialize.c
+
+src/libpcre2_8_la-pcre2_string_utils.lo: src/pcre2_string_utils.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_string_utils.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_string_utils.Tpo -c -o src/libpcre2_8_la-pcre2_string_utils.lo `test -f 'src/pcre2_string_utils.c' || echo '$(srcdir)/'`src/pcre2_string_utils.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_string_utils.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_string_utils.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_string_utils.c' object='src/libpcre2_8_la-pcre2_string_utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_string_utils.lo `test -f 'src/pcre2_string_utils.c' || echo '$(srcdir)/'`src/pcre2_string_utils.c
+
+src/libpcre2_8_la-pcre2_study.lo: src/pcre2_study.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_study.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_study.Tpo -c -o src/libpcre2_8_la-pcre2_study.lo `test -f 'src/pcre2_study.c' || echo '$(srcdir)/'`src/pcre2_study.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_study.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_study.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_study.c' object='src/libpcre2_8_la-pcre2_study.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_study.lo `test -f 'src/pcre2_study.c' || echo '$(srcdir)/'`src/pcre2_study.c
+
+src/libpcre2_8_la-pcre2_substitute.lo: src/pcre2_substitute.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_substitute.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_substitute.Tpo -c -o src/libpcre2_8_la-pcre2_substitute.lo `test -f 'src/pcre2_substitute.c' || echo '$(srcdir)/'`src/pcre2_substitute.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_substitute.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_substitute.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_substitute.c' object='src/libpcre2_8_la-pcre2_substitute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_substitute.lo `test -f 'src/pcre2_substitute.c' || echo '$(srcdir)/'`src/pcre2_substitute.c
+
+src/libpcre2_8_la-pcre2_substring.lo: src/pcre2_substring.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_substring.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_substring.Tpo -c -o src/libpcre2_8_la-pcre2_substring.lo `test -f 'src/pcre2_substring.c' || echo '$(srcdir)/'`src/pcre2_substring.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_substring.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_substring.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_substring.c' object='src/libpcre2_8_la-pcre2_substring.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_substring.lo `test -f 'src/pcre2_substring.c' || echo '$(srcdir)/'`src/pcre2_substring.c
+
+src/libpcre2_8_la-pcre2_tables.lo: src/pcre2_tables.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_tables.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_tables.Tpo -c -o src/libpcre2_8_la-pcre2_tables.lo `test -f 'src/pcre2_tables.c' || echo '$(srcdir)/'`src/pcre2_tables.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_tables.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_tables.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_tables.c' object='src/libpcre2_8_la-pcre2_tables.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_tables.lo `test -f 'src/pcre2_tables.c' || echo '$(srcdir)/'`src/pcre2_tables.c
+
+src/libpcre2_8_la-pcre2_ucd.lo: src/pcre2_ucd.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_ucd.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_ucd.Tpo -c -o src/libpcre2_8_la-pcre2_ucd.lo `test -f 'src/pcre2_ucd.c' || echo '$(srcdir)/'`src/pcre2_ucd.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_ucd.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_ucd.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_ucd.c' object='src/libpcre2_8_la-pcre2_ucd.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_ucd.lo `test -f 'src/pcre2_ucd.c' || echo '$(srcdir)/'`src/pcre2_ucd.c
+
+src/libpcre2_8_la-pcre2_valid_utf.lo: src/pcre2_valid_utf.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_valid_utf.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_valid_utf.Tpo -c -o src/libpcre2_8_la-pcre2_valid_utf.lo `test -f 'src/pcre2_valid_utf.c' || echo '$(srcdir)/'`src/pcre2_valid_utf.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_valid_utf.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_valid_utf.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_valid_utf.c' object='src/libpcre2_8_la-pcre2_valid_utf.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_valid_utf.lo `test -f 'src/pcre2_valid_utf.c' || echo '$(srcdir)/'`src/pcre2_valid_utf.c
+
+src/libpcre2_8_la-pcre2_xclass.lo: src/pcre2_xclass.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_xclass.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_xclass.Tpo -c -o src/libpcre2_8_la-pcre2_xclass.lo `test -f 'src/pcre2_xclass.c' || echo '$(srcdir)/'`src/pcre2_xclass.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_xclass.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_xclass.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_xclass.c' object='src/libpcre2_8_la-pcre2_xclass.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_xclass.lo `test -f 'src/pcre2_xclass.c' || echo '$(srcdir)/'`src/pcre2_xclass.c
+
+src/libpcre2_8_la-pcre2_chartables.lo: src/pcre2_chartables.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_8_la-pcre2_chartables.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_8_la-pcre2_chartables.Tpo -c -o src/libpcre2_8_la-pcre2_chartables.lo `test -f 'src/pcre2_chartables.c' || echo '$(srcdir)/'`src/pcre2_chartables.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_8_la-pcre2_chartables.Tpo src/$(DEPDIR)/libpcre2_8_la-pcre2_chartables.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_chartables.c' object='src/libpcre2_8_la-pcre2_chartables.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_8_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_8_la-pcre2_chartables.lo `test -f 'src/pcre2_chartables.c' || echo '$(srcdir)/'`src/pcre2_chartables.c
+
+src/libpcre2_posix_la-pcre2posix.lo: src/pcre2posix.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_posix_la_CFLAGS) $(CFLAGS) -MT src/libpcre2_posix_la-pcre2posix.lo -MD -MP -MF src/$(DEPDIR)/libpcre2_posix_la-pcre2posix.Tpo -c -o src/libpcre2_posix_la-pcre2posix.lo `test -f 'src/pcre2posix.c' || echo '$(srcdir)/'`src/pcre2posix.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/libpcre2_posix_la-pcre2posix.Tpo src/$(DEPDIR)/libpcre2_posix_la-pcre2posix.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2posix.c' object='src/libpcre2_posix_la-pcre2posix.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libpcre2_posix_la_CFLAGS) $(CFLAGS) -c -o src/libpcre2_posix_la-pcre2posix.lo `test -f 'src/pcre2posix.c' || echo '$(srcdir)/'`src/pcre2posix.c
+
+src/pcre2_jit_test-pcre2_jit_test.o: src/pcre2_jit_test.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2_jit_test_CFLAGS) $(CFLAGS) -MT src/pcre2_jit_test-pcre2_jit_test.o -MD -MP -MF src/$(DEPDIR)/pcre2_jit_test-pcre2_jit_test.Tpo -c -o src/pcre2_jit_test-pcre2_jit_test.o `test -f 'src/pcre2_jit_test.c' || echo '$(srcdir)/'`src/pcre2_jit_test.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/pcre2_jit_test-pcre2_jit_test.Tpo src/$(DEPDIR)/pcre2_jit_test-pcre2_jit_test.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_jit_test.c' object='src/pcre2_jit_test-pcre2_jit_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2_jit_test_CFLAGS) $(CFLAGS) -c -o src/pcre2_jit_test-pcre2_jit_test.o `test -f 'src/pcre2_jit_test.c' || echo '$(srcdir)/'`src/pcre2_jit_test.c
+
+src/pcre2_jit_test-pcre2_jit_test.obj: src/pcre2_jit_test.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2_jit_test_CFLAGS) $(CFLAGS) -MT src/pcre2_jit_test-pcre2_jit_test.obj -MD -MP -MF src/$(DEPDIR)/pcre2_jit_test-pcre2_jit_test.Tpo -c -o src/pcre2_jit_test-pcre2_jit_test.obj `if test -f 'src/pcre2_jit_test.c'; then $(CYGPATH_W) 'src/pcre2_jit_test.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2_jit_test.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/pcre2_jit_test-pcre2_jit_test.Tpo src/$(DEPDIR)/pcre2_jit_test-pcre2_jit_test.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_jit_test.c' object='src/pcre2_jit_test-pcre2_jit_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2_jit_test_CFLAGS) $(CFLAGS) -c -o src/pcre2_jit_test-pcre2_jit_test.obj `if test -f 'src/pcre2_jit_test.c'; then $(CYGPATH_W) 'src/pcre2_jit_test.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2_jit_test.c'; fi`
+
+src/pcre2fuzzcheck_16-pcre2_fuzzsupport.o: src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2fuzzcheck_16_CFLAGS) $(CFLAGS) -MT src/pcre2fuzzcheck_16-pcre2_fuzzsupport.o -MD -MP -MF src/$(DEPDIR)/pcre2fuzzcheck_16-pcre2_fuzzsupport.Tpo -c -o src/pcre2fuzzcheck_16-pcre2_fuzzsupport.o `test -f 'src/pcre2_fuzzsupport.c' || echo '$(srcdir)/'`src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/pcre2fuzzcheck_16-pcre2_fuzzsupport.Tpo src/$(DEPDIR)/pcre2fuzzcheck_16-pcre2_fuzzsupport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_fuzzsupport.c' object='src/pcre2fuzzcheck_16-pcre2_fuzzsupport.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2fuzzcheck_16_CFLAGS) $(CFLAGS) -c -o src/pcre2fuzzcheck_16-pcre2_fuzzsupport.o `test -f 'src/pcre2_fuzzsupport.c' || echo '$(srcdir)/'`src/pcre2_fuzzsupport.c
+
+src/pcre2fuzzcheck_16-pcre2_fuzzsupport.obj: src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2fuzzcheck_16_CFLAGS) $(CFLAGS) -MT src/pcre2fuzzcheck_16-pcre2_fuzzsupport.obj -MD -MP -MF src/$(DEPDIR)/pcre2fuzzcheck_16-pcre2_fuzzsupport.Tpo -c -o src/pcre2fuzzcheck_16-pcre2_fuzzsupport.obj `if test -f 'src/pcre2_fuzzsupport.c'; then $(CYGPATH_W) 'src/pcre2_fuzzsupport.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2_fuzzsupport.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/pcre2fuzzcheck_16-pcre2_fuzzsupport.Tpo src/$(DEPDIR)/pcre2fuzzcheck_16-pcre2_fuzzsupport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_fuzzsupport.c' object='src/pcre2fuzzcheck_16-pcre2_fuzzsupport.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2fuzzcheck_16_CFLAGS) $(CFLAGS) -c -o src/pcre2fuzzcheck_16-pcre2_fuzzsupport.obj `if test -f 'src/pcre2_fuzzsupport.c'; then $(CYGPATH_W) 'src/pcre2_fuzzsupport.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2_fuzzsupport.c'; fi`
+
+src/pcre2fuzzcheck_32-pcre2_fuzzsupport.o: src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2fuzzcheck_32_CFLAGS) $(CFLAGS) -MT src/pcre2fuzzcheck_32-pcre2_fuzzsupport.o -MD -MP -MF src/$(DEPDIR)/pcre2fuzzcheck_32-pcre2_fuzzsupport.Tpo -c -o src/pcre2fuzzcheck_32-pcre2_fuzzsupport.o `test -f 'src/pcre2_fuzzsupport.c' || echo '$(srcdir)/'`src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/pcre2fuzzcheck_32-pcre2_fuzzsupport.Tpo src/$(DEPDIR)/pcre2fuzzcheck_32-pcre2_fuzzsupport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_fuzzsupport.c' object='src/pcre2fuzzcheck_32-pcre2_fuzzsupport.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2fuzzcheck_32_CFLAGS) $(CFLAGS) -c -o src/pcre2fuzzcheck_32-pcre2_fuzzsupport.o `test -f 'src/pcre2_fuzzsupport.c' || echo '$(srcdir)/'`src/pcre2_fuzzsupport.c
+
+src/pcre2fuzzcheck_32-pcre2_fuzzsupport.obj: src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2fuzzcheck_32_CFLAGS) $(CFLAGS) -MT src/pcre2fuzzcheck_32-pcre2_fuzzsupport.obj -MD -MP -MF src/$(DEPDIR)/pcre2fuzzcheck_32-pcre2_fuzzsupport.Tpo -c -o src/pcre2fuzzcheck_32-pcre2_fuzzsupport.obj `if test -f 'src/pcre2_fuzzsupport.c'; then $(CYGPATH_W) 'src/pcre2_fuzzsupport.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2_fuzzsupport.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/pcre2fuzzcheck_32-pcre2_fuzzsupport.Tpo src/$(DEPDIR)/pcre2fuzzcheck_32-pcre2_fuzzsupport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_fuzzsupport.c' object='src/pcre2fuzzcheck_32-pcre2_fuzzsupport.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2fuzzcheck_32_CFLAGS) $(CFLAGS) -c -o src/pcre2fuzzcheck_32-pcre2_fuzzsupport.obj `if test -f 'src/pcre2_fuzzsupport.c'; then $(CYGPATH_W) 'src/pcre2_fuzzsupport.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2_fuzzsupport.c'; fi`
+
+src/pcre2fuzzcheck_8-pcre2_fuzzsupport.o: src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2fuzzcheck_8_CFLAGS) $(CFLAGS) -MT src/pcre2fuzzcheck_8-pcre2_fuzzsupport.o -MD -MP -MF src/$(DEPDIR)/pcre2fuzzcheck_8-pcre2_fuzzsupport.Tpo -c -o src/pcre2fuzzcheck_8-pcre2_fuzzsupport.o `test -f 'src/pcre2_fuzzsupport.c' || echo '$(srcdir)/'`src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/pcre2fuzzcheck_8-pcre2_fuzzsupport.Tpo src/$(DEPDIR)/pcre2fuzzcheck_8-pcre2_fuzzsupport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_fuzzsupport.c' object='src/pcre2fuzzcheck_8-pcre2_fuzzsupport.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2fuzzcheck_8_CFLAGS) $(CFLAGS) -c -o src/pcre2fuzzcheck_8-pcre2_fuzzsupport.o `test -f 'src/pcre2_fuzzsupport.c' || echo '$(srcdir)/'`src/pcre2_fuzzsupport.c
+
+src/pcre2fuzzcheck_8-pcre2_fuzzsupport.obj: src/pcre2_fuzzsupport.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2fuzzcheck_8_CFLAGS) $(CFLAGS) -MT src/pcre2fuzzcheck_8-pcre2_fuzzsupport.obj -MD -MP -MF src/$(DEPDIR)/pcre2fuzzcheck_8-pcre2_fuzzsupport.Tpo -c -o src/pcre2fuzzcheck_8-pcre2_fuzzsupport.obj `if test -f 'src/pcre2_fuzzsupport.c'; then $(CYGPATH_W) 'src/pcre2_fuzzsupport.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2_fuzzsupport.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/pcre2fuzzcheck_8-pcre2_fuzzsupport.Tpo src/$(DEPDIR)/pcre2fuzzcheck_8-pcre2_fuzzsupport.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2_fuzzsupport.c' object='src/pcre2fuzzcheck_8-pcre2_fuzzsupport.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2fuzzcheck_8_CFLAGS) $(CFLAGS) -c -o src/pcre2fuzzcheck_8-pcre2_fuzzsupport.obj `if test -f 'src/pcre2_fuzzsupport.c'; then $(CYGPATH_W) 'src/pcre2_fuzzsupport.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2_fuzzsupport.c'; fi`
+
+src/pcre2grep-pcre2grep.o: src/pcre2grep.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2grep_CFLAGS) $(CFLAGS) -MT src/pcre2grep-pcre2grep.o -MD -MP -MF src/$(DEPDIR)/pcre2grep-pcre2grep.Tpo -c -o src/pcre2grep-pcre2grep.o `test -f 'src/pcre2grep.c' || echo '$(srcdir)/'`src/pcre2grep.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/pcre2grep-pcre2grep.Tpo src/$(DEPDIR)/pcre2grep-pcre2grep.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2grep.c' object='src/pcre2grep-pcre2grep.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2grep_CFLAGS) $(CFLAGS) -c -o src/pcre2grep-pcre2grep.o `test -f 'src/pcre2grep.c' || echo '$(srcdir)/'`src/pcre2grep.c
+
+src/pcre2grep-pcre2grep.obj: src/pcre2grep.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2grep_CFLAGS) $(CFLAGS) -MT src/pcre2grep-pcre2grep.obj -MD -MP -MF src/$(DEPDIR)/pcre2grep-pcre2grep.Tpo -c -o src/pcre2grep-pcre2grep.obj `if test -f 'src/pcre2grep.c'; then $(CYGPATH_W) 'src/pcre2grep.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2grep.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/pcre2grep-pcre2grep.Tpo src/$(DEPDIR)/pcre2grep-pcre2grep.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2grep.c' object='src/pcre2grep-pcre2grep.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2grep_CFLAGS) $(CFLAGS) -c -o src/pcre2grep-pcre2grep.obj `if test -f 'src/pcre2grep.c'; then $(CYGPATH_W) 'src/pcre2grep.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2grep.c'; fi`
+
+src/pcre2posix_test-pcre2posix_test.o: src/pcre2posix_test.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2posix_test_CFLAGS) $(CFLAGS) -MT src/pcre2posix_test-pcre2posix_test.o -MD -MP -MF src/$(DEPDIR)/pcre2posix_test-pcre2posix_test.Tpo -c -o src/pcre2posix_test-pcre2posix_test.o `test -f 'src/pcre2posix_test.c' || echo '$(srcdir)/'`src/pcre2posix_test.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/pcre2posix_test-pcre2posix_test.Tpo src/$(DEPDIR)/pcre2posix_test-pcre2posix_test.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2posix_test.c' object='src/pcre2posix_test-pcre2posix_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2posix_test_CFLAGS) $(CFLAGS) -c -o src/pcre2posix_test-pcre2posix_test.o `test -f 'src/pcre2posix_test.c' || echo '$(srcdir)/'`src/pcre2posix_test.c
+
+src/pcre2posix_test-pcre2posix_test.obj: src/pcre2posix_test.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2posix_test_CFLAGS) $(CFLAGS) -MT src/pcre2posix_test-pcre2posix_test.obj -MD -MP -MF src/$(DEPDIR)/pcre2posix_test-pcre2posix_test.Tpo -c -o src/pcre2posix_test-pcre2posix_test.obj `if test -f 'src/pcre2posix_test.c'; then $(CYGPATH_W) 'src/pcre2posix_test.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2posix_test.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/pcre2posix_test-pcre2posix_test.Tpo src/$(DEPDIR)/pcre2posix_test-pcre2posix_test.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2posix_test.c' object='src/pcre2posix_test-pcre2posix_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2posix_test_CFLAGS) $(CFLAGS) -c -o src/pcre2posix_test-pcre2posix_test.obj `if test -f 'src/pcre2posix_test.c'; then $(CYGPATH_W) 'src/pcre2posix_test.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2posix_test.c'; fi`
+
+src/pcre2test-pcre2test.o: src/pcre2test.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2test_CFLAGS) $(CFLAGS) -MT src/pcre2test-pcre2test.o -MD -MP -MF src/$(DEPDIR)/pcre2test-pcre2test.Tpo -c -o src/pcre2test-pcre2test.o `test -f 'src/pcre2test.c' || echo '$(srcdir)/'`src/pcre2test.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/pcre2test-pcre2test.Tpo src/$(DEPDIR)/pcre2test-pcre2test.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2test.c' object='src/pcre2test-pcre2test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2test_CFLAGS) $(CFLAGS) -c -o src/pcre2test-pcre2test.o `test -f 'src/pcre2test.c' || echo '$(srcdir)/'`src/pcre2test.c
+
+src/pcre2test-pcre2test.obj: src/pcre2test.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2test_CFLAGS) $(CFLAGS) -MT src/pcre2test-pcre2test.obj -MD -MP -MF src/$(DEPDIR)/pcre2test-pcre2test.Tpo -c -o src/pcre2test-pcre2test.obj `if test -f 'src/pcre2test.c'; then $(CYGPATH_W) 'src/pcre2test.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2test.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) src/$(DEPDIR)/pcre2test-pcre2test.Tpo src/$(DEPDIR)/pcre2test-pcre2test.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='src/pcre2test.c' object='src/pcre2test-pcre2test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pcre2test_CFLAGS) $(CFLAGS) -c -o src/pcre2test-pcre2test.obj `if test -f 'src/pcre2test.c'; then $(CYGPATH_W) 'src/pcre2test.c'; else $(CYGPATH_W) '$(srcdir)/src/pcre2test.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf src/.libs src/_libs
+
+distclean-libtool:
+ -rm -f libtool config.lt
+install-man1: $(dist_man_MANS)
+ @$(NORMAL_INSTALL)
+ @list1=''; \
+ list2='$(dist_man_MANS)'; \
+ test -n "$(man1dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.1[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man1dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.1[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
+install-man3: $(dist_man_MANS)
+ @$(NORMAL_INSTALL)
+ @list1=''; \
+ list2='$(dist_man_MANS)'; \
+ test -n "$(man3dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man3dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man3dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.3[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man3:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man3dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.3[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man3dir)'; $(am__uninstall_files_from_dir)
+install-dist_docDATA: $(dist_doc_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \
+ done
+
+uninstall-dist_docDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir)
+install-dist_htmlDATA: $(dist_html_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(dist_html_DATA)'; test -n "$(htmldir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(htmldir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \
+ done
+
+uninstall-dist_htmlDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_html_DATA)'; test -n "$(htmldir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(htmldir)'; $(am__uninstall_files_from_dir)
+install-pkgconfigDATA: $(pkgconfig_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
+ done
+
+uninstall-pkgconfigDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
+install-includeHEADERS: $(include_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
+ done
+
+uninstall-includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
+install-nodist_includeHEADERS: $(nodist_include_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
+ done
+
+uninstall-nodist_includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscope: cscope.files
+ test ! -s cscope.files \
+ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
+clean-cscope:
+ -rm -f cscope.files
+cscope.files: clean-cscope cscopelist
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+ -rm -f cscope.out cscope.in.out cscope.po.out cscope.files
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+ rm -f $< $@
+ $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+ @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+ @$(am__set_TESTS_bases); \
+ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+ redo_bases=`for i in $$bases; do \
+ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+ done`; \
+ if test -n "$$redo_bases"; then \
+ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+ if $(am__make_dryrun); then :; else \
+ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+ fi; \
+ fi; \
+ if test -n "$$am__remaking_logs"; then \
+ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+ "recursion detected" >&2; \
+ elif test -n "$$redo_logs"; then \
+ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+ fi; \
+ if $(am__make_dryrun); then :; else \
+ st=0; \
+ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+ for i in $$redo_bases; do \
+ test -f $$i.trs && test -r $$i.trs \
+ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+ test -f $$i.log && test -r $$i.log \
+ || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+ done; \
+ test $$st -eq 0 || exit 1; \
+ fi
+ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+ ws='[ ]'; \
+ results=`for b in $$bases; do echo $$b.trs; done`; \
+ test -n "$$results" || results=/dev/null; \
+ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
+ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
+ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
+ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
+ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+ if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+ success=true; \
+ else \
+ success=false; \
+ fi; \
+ br='==================='; br=$$br$$br$$br$$br; \
+ result_count () \
+ { \
+ if test x"$$1" = x"--maybe-color"; then \
+ maybe_colorize=yes; \
+ elif test x"$$1" = x"--no-color"; then \
+ maybe_colorize=no; \
+ else \
+ echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+ fi; \
+ shift; \
+ desc=$$1 count=$$2; \
+ if test $$maybe_colorize = yes && test $$count -gt 0; then \
+ color_start=$$3 color_end=$$std; \
+ else \
+ color_start= color_end=; \
+ fi; \
+ echo "$${color_start}# $$desc $$count$${color_end}"; \
+ }; \
+ create_testsuite_report () \
+ { \
+ result_count $$1 "TOTAL:" $$all "$$brg"; \
+ result_count $$1 "PASS: " $$pass "$$grn"; \
+ result_count $$1 "SKIP: " $$skip "$$blu"; \
+ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+ result_count $$1 "FAIL: " $$fail "$$red"; \
+ result_count $$1 "XPASS:" $$xpass "$$red"; \
+ result_count $$1 "ERROR:" $$error "$$mgn"; \
+ }; \
+ { \
+ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
+ $(am__rst_title); \
+ create_testsuite_report --no-color; \
+ echo; \
+ echo ".. contents:: :depth: 2"; \
+ echo; \
+ for b in $$bases; do echo $$b; done \
+ | $(am__create_global_log); \
+ } >$(TEST_SUITE_LOG).tmp || exit 1; \
+ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
+ if $$success; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
+ fi; \
+ echo "$${col}$$br$${std}"; \
+ echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \
+ echo "$${col}$$br$${std}"; \
+ create_testsuite_report --maybe-color; \
+ echo "$$col$$br$$std"; \
+ if $$success; then :; else \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ if test -n "$(PACKAGE_BUGREPORT)"; then \
+ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ fi; \
+ echo "$$col$$br$$std"; \
+ fi; \
+ $$success || exit 1
+
+check-TESTS: $(check_SCRIPTS)
+ @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
+ @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+ exit $$?;
+recheck: all $(check_SCRIPTS)
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ bases=`for i in $$bases; do echo $$i; done \
+ | $(am__list_recheck_tests)` || exit 1; \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ log_list=`echo $$log_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+ am__force_recheck=am--force-recheck \
+ TEST_LOGS="$$log_list"; \
+ exit $$?
+pcre2posix_test.log: pcre2posix_test$(EXEEXT)
+ @p='pcre2posix_test$(EXEEXT)'; \
+ b='pcre2posix_test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+pcre2_jit_test.log: pcre2_jit_test$(EXEEXT)
+ @p='pcre2_jit_test$(EXEEXT)'; \
+ b='pcre2_jit_test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RunTest.log: RunTest
+ @p='RunTest'; \
+ b='RunTest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+RunGrepTest.log: RunGrepTest
+ @p='RunGrepTest'; \
+ b='RunGrepTest'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+ @p='$<'; \
+ $(am__set_b); \
+ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@ @p='$<'; \
+@am__EXEEXT_TRUE@ $(am__set_b); \
+@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ $(am__remove_distdir)
+ test -d "$(distdir)" || mkdir "$(distdir)"
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ -test -n "$(am__skip_mode_fix)" \
+ || find "$(distdir)" -type d ! -perm -755 \
+ -exec chmod u+rwx,go+rx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
+ $(am__post_remove_distdir)
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
+ $(am__post_remove_distdir)
+
+dist-lzip: distdir
+ tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
+ $(am__post_remove_distdir)
+
+dist-xz: distdir
+ tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
+ $(am__post_remove_distdir)
+
+dist-zstd: distdir
+ tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst
+ $(am__post_remove_distdir)
+
+dist-tarZ: distdir
+ @echo WARNING: "Support for distribution archives compressed with" \
+ "legacy program 'compress' is deprecated." >&2
+ @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__post_remove_distdir)
+
+dist-shar: distdir
+ @echo WARNING: "Support for shar distribution archives is" \
+ "deprecated." >&2
+ @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+ shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
+ $(am__post_remove_distdir)
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__post_remove_distdir)
+
+dist dist-all:
+ $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
+ $(am__post_remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lz*) \
+ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
+ *.tar.xz*) \
+ xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ *.tar.zst*) \
+ zstd -dc $(distdir).tar.zst | $(am__untar) ;;\
+ esac
+ chmod -R a-w $(distdir)
+ chmod u+w $(distdir)
+ mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
+ chmod a-w $(distdir)
+ test -d $(distdir)/_build || exit 0; \
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && am__cwd=`pwd` \
+ && $(am__cd) $(distdir)/_build/sub \
+ && ../../configure \
+ $(AM_DISTCHECK_CONFIGURE_FLAGS) \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ --srcdir=../.. --prefix="$$dc_install_base" \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+ && cd "$$am__cwd" \
+ || exit 1
+ $(am__post_remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @test -n '$(distuninstallcheck_dir)' || { \
+ echo 'ERROR: trying to run $@ with an empty' \
+ '$$(distuninstallcheck_dir)' >&2; \
+ exit 1; \
+ }; \
+ $(am__cd) '$(distuninstallcheck_dir)' || { \
+ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
+ exit 1; \
+ }; \
+ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(PROGRAMS) $(LIBRARIES) $(LTLIBRARIES) $(SCRIPTS) \
+ $(MANS) $(DATA) $(HEADERS)
+install-binPROGRAMS: install-libLTLIBRARIES
+
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(htmldir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(includedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f .libs/$(am__dirstamp)
+ -rm -f src/$(DEPDIR)/$(am__dirstamp)
+ -rm -f src/$(am__dirstamp)
+ -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
+ clean-libtool clean-local clean-noinstLIBRARIES \
+ clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -f src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.Po
+ -rm -f src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.Po
+ -rm -f src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.Po
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_auto_possess.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_chartables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_chkdint.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_compile.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_compile_cgroup.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_compile_class.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_config.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_context.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_convert.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_dfa_match.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_error.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_extuni.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_find_bracket.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_jit_compile.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_maketables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_match.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_match_data.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_match_next.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_newline.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_ord2utf.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_pattern_info.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_script_run.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_serialize.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_string_utils.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_study.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_substitute.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_substring.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_tables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_ucd.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_valid_utf.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_xclass.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_auto_possess.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_chartables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_chkdint.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_compile.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_compile_cgroup.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_compile_class.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_config.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_context.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_convert.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_dfa_match.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_error.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_extuni.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_find_bracket.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_jit_compile.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_maketables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_match.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_match_data.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_match_next.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_newline.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_ord2utf.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_pattern_info.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_script_run.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_serialize.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_string_utils.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_study.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_substitute.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_substring.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_tables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_ucd.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_valid_utf.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_xclass.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_auto_possess.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_chartables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_chkdint.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_compile.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_compile_cgroup.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_compile_class.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_config.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_context.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_convert.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_dfa_match.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_error.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_extuni.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_find_bracket.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_jit_compile.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_maketables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_match.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_match_data.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_match_next.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_newline.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_ord2utf.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_pattern_info.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_script_run.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_serialize.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_string_utils.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_study.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_substitute.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_substring.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_tables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_ucd.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_valid_utf.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_xclass.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_posix_la-pcre2posix.Plo
+ -rm -f src/$(DEPDIR)/pcre2_dftables.Po
+ -rm -f src/$(DEPDIR)/pcre2_jit_test-pcre2_jit_test.Po
+ -rm -f src/$(DEPDIR)/pcre2fuzzcheck_16-pcre2_fuzzsupport.Po
+ -rm -f src/$(DEPDIR)/pcre2fuzzcheck_32-pcre2_fuzzsupport.Po
+ -rm -f src/$(DEPDIR)/pcre2fuzzcheck_8-pcre2_fuzzsupport.Po
+ -rm -f src/$(DEPDIR)/pcre2grep-pcre2grep.Po
+ -rm -f src/$(DEPDIR)/pcre2posix_test-pcre2posix_test.Po
+ -rm -f src/$(DEPDIR)/pcre2test-pcre2test.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-hdr distclean-libtool distclean-local distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-dist_docDATA install-dist_htmlDATA \
+ install-includeHEADERS install-man \
+ install-nodist_includeHEADERS install-pkgconfigDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-binSCRIPTS \
+ install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man1 install-man3
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -f src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_16_a-pcre2_fuzzsupport.Po
+ -rm -f src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_32_a-pcre2_fuzzsupport.Po
+ -rm -f src/$(DEPDIR)/_libs_libpcre2_fuzzsupport_a-pcre2_fuzzsupport.Po
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_auto_possess.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_chartables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_chkdint.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_compile.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_compile_cgroup.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_compile_class.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_config.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_context.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_convert.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_dfa_match.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_error.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_extuni.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_find_bracket.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_jit_compile.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_maketables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_match.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_match_data.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_match_next.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_newline.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_ord2utf.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_pattern_info.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_script_run.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_serialize.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_string_utils.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_study.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_substitute.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_substring.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_tables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_ucd.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_valid_utf.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_16_la-pcre2_xclass.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_auto_possess.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_chartables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_chkdint.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_compile.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_compile_cgroup.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_compile_class.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_config.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_context.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_convert.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_dfa_match.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_error.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_extuni.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_find_bracket.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_jit_compile.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_maketables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_match.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_match_data.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_match_next.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_newline.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_ord2utf.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_pattern_info.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_script_run.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_serialize.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_string_utils.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_study.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_substitute.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_substring.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_tables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_ucd.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_valid_utf.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_32_la-pcre2_xclass.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_auto_possess.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_chartables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_chkdint.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_compile.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_compile_cgroup.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_compile_class.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_config.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_context.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_convert.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_dfa_match.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_error.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_extuni.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_find_bracket.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_jit_compile.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_maketables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_match.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_match_data.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_match_next.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_newline.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_ord2utf.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_pattern_info.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_script_run.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_serialize.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_string_utils.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_study.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_substitute.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_substring.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_tables.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_ucd.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_valid_utf.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_8_la-pcre2_xclass.Plo
+ -rm -f src/$(DEPDIR)/libpcre2_posix_la-pcre2posix.Plo
+ -rm -f src/$(DEPDIR)/pcre2_dftables.Po
+ -rm -f src/$(DEPDIR)/pcre2_jit_test-pcre2_jit_test.Po
+ -rm -f src/$(DEPDIR)/pcre2fuzzcheck_16-pcre2_fuzzsupport.Po
+ -rm -f src/$(DEPDIR)/pcre2fuzzcheck_32-pcre2_fuzzsupport.Po
+ -rm -f src/$(DEPDIR)/pcre2fuzzcheck_8-pcre2_fuzzsupport.Po
+ -rm -f src/$(DEPDIR)/pcre2grep-pcre2grep.Po
+ -rm -f src/$(DEPDIR)/pcre2posix_test-pcre2posix_test.Po
+ -rm -f src/$(DEPDIR)/pcre2test-pcre2test.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \
+ uninstall-dist_docDATA uninstall-dist_htmlDATA \
+ uninstall-includeHEADERS uninstall-libLTLIBRARIES \
+ uninstall-man uninstall-nodist_includeHEADERS \
+ uninstall-pkgconfigDATA
+
+uninstall-man: uninstall-man1 uninstall-man3
+
+.MAKE: all check check-am install install-am install-exec \
+ install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles am--refresh check \
+ check-TESTS check-am clean clean-binPROGRAMS clean-cscope \
+ clean-generic clean-libLTLIBRARIES clean-libtool clean-local \
+ clean-noinstLIBRARIES clean-noinstPROGRAMS cscope \
+ cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
+ dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \
+ dist-zstd distcheck distclean distclean-compile \
+ distclean-generic distclean-hdr distclean-libtool \
+ distclean-local distclean-tags distcleancheck distdir \
+ distuninstallcheck dvi dvi-am html html-am info info-am \
+ install install-am install-binPROGRAMS install-binSCRIPTS \
+ install-data install-data-am install-dist_docDATA \
+ install-dist_htmlDATA install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am \
+ install-includeHEADERS install-info install-info-am \
+ install-libLTLIBRARIES install-man install-man1 install-man3 \
+ install-nodist_includeHEADERS install-pdf install-pdf-am \
+ install-pkgconfigDATA install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ recheck tags tags-am uninstall uninstall-am \
+ uninstall-binPROGRAMS uninstall-binSCRIPTS \
+ uninstall-dist_docDATA uninstall-dist_htmlDATA \
+ uninstall-includeHEADERS uninstall-libLTLIBRARIES \
+ uninstall-man uninstall-man1 uninstall-man3 \
+ uninstall-nodist_includeHEADERS uninstall-pkgconfigDATA
+
+.PRECIOUS: Makefile
+
+
+# The only difference between pcre2.h.in and pcre2.h is the setting of the PCRE
+# version number. Therefore, we can create the generic version just by copying.
+
+src/pcre2.h.generic: src/pcre2.h.in configure.ac
+ rm -f $@
+ cp -p src/pcre2.h $@
+
+# It is more complicated for config.h.generic. We need the version that results
+# from a default configuration so as to get all the default values for PCRE
+# configuration macros such as MATCH_LIMIT and NEWLINE. We can get this by
+# doing a configure in a temporary directory. However, some trickery is needed,
+# because the source directory may already be configured. If you just try
+# running configure in a new directory, it complains. For this reason, we move
+# config.status out of the way while doing the default configuration. The
+# resulting config.h is munged by perl to put #ifdefs round any #defines for
+# macros with values, and to #undef all boolean macros such as HAVE_xxx,
+# SUPPORT_xxx, and PCRE2_STATIC/PCRE2POSIX_SHARED. We also get rid of any
+# GCC-specific visibility settings.
+
+src/config.h.generic: configure.ac
+ rm -rf $@ _generic
+ mkdir _generic
+ cs=$(srcdir)/config.status; test ! -f $$cs || mv -f $$cs $$cs.aside
+ cd _generic && $(abs_top_srcdir)/configure || :
+ cs=$(srcdir)/config.status; test ! -f $$cs.aside || mv -f $$cs.aside $$cs
+ test -f _generic/src/config.h
+ perl -n \
+ -e 'BEGIN{$$blank=0;}' \
+ -e 'if(/(.+?)\s*__attribute__ \(\(visibility/){print"$$1\n";$$blank=0;next;}' \
+ -e 'if(/LT_OBJDIR/){print"/* This is ignored unless you are using libtool. */\n";}' \
+ -e 'if(/^#define\s((?:HAVE|SUPPORT|STDC)_\w+|PCRE2_STATIC|PCRE2POSIX_SHARED)/){print"/* #undef $$1 */\n";$$blank=0;next;}' \
+ -e 'if(/^#define\s(?!PACKAGE|VERSION)(\w+)/){print"#ifndef $$1\n$$_#endif\n";$$blank=0;next;}' \
+ -e 'if(/^\s*$$/){print unless $$blank; $$blank=1;} else{print;$$blank=0;}' \
+ _generic/src/config.h >$@
+ rm -rf _generic
+@WITH_REBUILD_CHARTABLES_TRUE@src/pcre2_chartables.c: pcre2_dftables$(EXEEXT)
+@WITH_REBUILD_CHARTABLES_TRUE@ rm -f $@
+@WITH_REBUILD_CHARTABLES_TRUE@ ./pcre2_dftables$(EXEEXT) $@
+@WITH_EBCDIC_NL25_TRUE@@WITH_EBCDIC_TRUE@@WITH_REBUILD_CHARTABLES_FALSE@src/pcre2_chartables.c: $(srcdir)/src/pcre2_chartables.c.ebcdic-1047-nl25
+@WITH_EBCDIC_NL25_TRUE@@WITH_EBCDIC_TRUE@@WITH_REBUILD_CHARTABLES_FALSE@ rm -f $@
+@WITH_EBCDIC_NL25_TRUE@@WITH_EBCDIC_TRUE@@WITH_REBUILD_CHARTABLES_FALSE@ $(LN_S) $(abs_srcdir)/src/pcre2_chartables.c.ebcdic-1047-nl25 $(abs_builddir)/src/pcre2_chartables.c
+@WITH_EBCDIC_NL25_FALSE@@WITH_EBCDIC_TRUE@@WITH_REBUILD_CHARTABLES_FALSE@src/pcre2_chartables.c: $(srcdir)/src/pcre2_chartables.c.ebcdic-1047-nl15
+@WITH_EBCDIC_NL25_FALSE@@WITH_EBCDIC_TRUE@@WITH_REBUILD_CHARTABLES_FALSE@ rm -f $@
+@WITH_EBCDIC_NL25_FALSE@@WITH_EBCDIC_TRUE@@WITH_REBUILD_CHARTABLES_FALSE@ $(LN_S) $(abs_srcdir)/src/pcre2_chartables.c.ebcdic-1047-nl15 $(abs_builddir)/src/pcre2_chartables.c
+@WITH_EBCDIC_FALSE@@WITH_REBUILD_CHARTABLES_FALSE@src/pcre2_chartables.c: $(srcdir)/src/pcre2_chartables.c.dist
+@WITH_EBCDIC_FALSE@@WITH_REBUILD_CHARTABLES_FALSE@ rm -f $@
+@WITH_EBCDIC_FALSE@@WITH_REBUILD_CHARTABLES_FALSE@ $(LN_S) $(abs_srcdir)/src/pcre2_chartables.c.dist $(abs_builddir)/src/pcre2_chartables.c
+
+testoutput-clean:
+ -rm -rf testoutput8 testoutput8-jit testoutput8-dfa
+ -rm -rf testoutput16 testoutput16-jit testoutput16-dfa
+ -rm -rf testoutput32 testoutput32-jit testoutput32-dfa
+
+@WITH_GCOV_TRUE@coverage-check: all
+@WITH_GCOV_TRUE@ -$(MAKE) $(AM_MAKEFLAGS) -k check
+
+@WITH_GCOV_TRUE@coverage-baseline:
+@WITH_GCOV_TRUE@ $(LCOV) $(coverage_quiet) \
+@WITH_GCOV_TRUE@ --directory $(top_builddir) \
+@WITH_GCOV_TRUE@ --output-file "$(COVERAGE_OUTPUT_FILE)" \
+@WITH_GCOV_TRUE@ --capture \
+@WITH_GCOV_TRUE@ --initial
+
+@WITH_GCOV_TRUE@coverage-report:
+@WITH_GCOV_TRUE@ $(LCOV) $(coverage_quiet) \
+@WITH_GCOV_TRUE@ --directory $(top_builddir) \
+@WITH_GCOV_TRUE@ --capture \
+@WITH_GCOV_TRUE@ --output-file "$(COVERAGE_OUTPUT_FILE).tmp" \
+@WITH_GCOV_TRUE@ --test-name "$(COVERAGE_TEST_NAME)" \
+@WITH_GCOV_TRUE@ --no-checksum \
+@WITH_GCOV_TRUE@ --compat-libtool \
+@WITH_GCOV_TRUE@ $(COVERAGE_LCOV_EXTRA_FLAGS)
+@WITH_GCOV_TRUE@ $(LCOV) $(coverage_quiet) \
+@WITH_GCOV_TRUE@ --directory $(top_builddir) \
+@WITH_GCOV_TRUE@ --output-file "$(COVERAGE_OUTPUT_FILE)" \
+@WITH_GCOV_TRUE@ --remove "$(COVERAGE_OUTPUT_FILE).tmp" \
+@WITH_GCOV_TRUE@ "/tmp/*" \
+@WITH_GCOV_TRUE@ "/usr/include/*" \
+@WITH_GCOV_TRUE@ "$(includedir)/*"
+@WITH_GCOV_TRUE@ -@rm -f "$(COVERAGE_OUTPUT_FILE).tmp"
+@WITH_GCOV_TRUE@ LANG=C $(GENHTML) $(coverage_quiet) \
+@WITH_GCOV_TRUE@ --prefix $(top_builddir) \
+@WITH_GCOV_TRUE@ --output-directory "$(COVERAGE_OUTPUT_DIR)" \
+@WITH_GCOV_TRUE@ --title "$(PACKAGE) $(VERSION) Code Coverage Report" \
+@WITH_GCOV_TRUE@ --show-details "$(COVERAGE_OUTPUT_FILE)" \
+@WITH_GCOV_TRUE@ --legend \
+@WITH_GCOV_TRUE@ $(COVERAGE_GENHTML_EXTRA_FLAGS)
+@WITH_GCOV_TRUE@ @echo "Code coverage report written to file://$(abs_builddir)/$(COVERAGE_OUTPUT_DIR)/index.html"
+
+@WITH_GCOV_TRUE@coverage-reset:
+@WITH_GCOV_TRUE@ -$(LCOV) $(coverage_quiet) --zerocounters --directory $(top_builddir)
+
+@WITH_GCOV_TRUE@coverage-clean-report:
+@WITH_GCOV_TRUE@ -rm -f "$(COVERAGE_OUTPUT_FILE)" "$(COVERAGE_OUTPUT_FILE).tmp"
+@WITH_GCOV_TRUE@ -rm -rf "$(COVERAGE_OUTPUT_DIR)"
+
+@WITH_GCOV_TRUE@coverage-clean-data:
+@WITH_GCOV_TRUE@ -find $(top_builddir) -name "*.gcda" -delete
+
+@WITH_GCOV_TRUE@coverage-clean: coverage-reset coverage-clean-report coverage-clean-data
+@WITH_GCOV_TRUE@ -find $(top_builddir) -name "*.gcno" -delete
+
+@WITH_GCOV_TRUE@coverage-distclean: coverage-clean
+
+@WITH_GCOV_TRUE@coverage: coverage-reset coverage-baseline coverage-check coverage-report
+
+@WITH_GCOV_FALSE@coverage:
+@WITH_GCOV_FALSE@ @echo "Configuring with --enable-coverage is required to generate code coverage report."
+
+@WITH_GCOV_FALSE@coverage-distclean:
+@WITH_GCOV_FALSE@ rm -rf $(PACKAGE)-$(VERSION)-coverage*
+
+clean-local: $(CLEAN_LOCAL_TARGETS)
+distclean-local: $(DISTCLEAN_LOCAL_TARGETS)
+.PHONY: $(PHONY_TARGETS)
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..13cc4c6
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,703 @@
+News about PCRE2 releases
+-------------------------
+
+Version 10.48 31-August-2026
+----------------------------
+
+This is a regular release, incorporating security fixes along with small
+improvements and fixes to library behaviour.
+
+Only changes to behaviour, changes to the API, and other significant changes
+are described here. Please see the ChangeLog and Git log for further details.
+
+As well as the tarball and Git tag for this release, there are detailed
+instructions for backporting security and correctness fixes, for the last
+five years of releases.
+
+* (Git change) Renamed the default development branch from master to main.
+
+* (Maintenance change) Added a five-year support lifecycle policy and
+publication of backport patches for security and high-severity fixes in older
+releases.
+
+* (Security fix for very specific API usage, GHSA-2p8c-ff85-vh9x) If
+pcre2_jit_compile() is called with options for some match modes, and then
+pcre2_match() is used to perform a match for a different match mode, an
+out-of-bounds read can occur if the match is attempted against invalid UTF input.
+
+* (Security fix for pattern conversion, GHSA-q8g2-wprr-34m9) If pcre2_convert()
+is called on untrusted input on platforms with 32-bit size_t, an out-of-bounds
+heap write can occur.
+
+* (Security fix, GHSA-3r4p-g7gg-ppmf) Fixed an out-of-bounds write in DFA
+matching when using a heap limit; also fixed possible integer overflows which
+could cause under-allocation of the workspace.
+
+* (Security fix, GHSA-fmgr-6ggq-9859) Added bounds checks for several integer
+overflows while compiling patterns on 32-bit CPUs, which could cause
+under-allocation followed by out-of-bounds writes.
+
+* (Security fix, GHSA-9qww-pwc4-77qq) Applied lower buffer bound to prevent
+two out-of-bounds reads while scanning backwards through invalid UTF data with
+PCRE2_MATCH_INVALID_UTF.
+
+* (Matching correctness) Fixed several matching issues:
+ - A JIT-specific matching bug affecting prefix scanning on patterns with
+ repeats (#875).
+ - A JIT-specific matching bug in variable-length lookbehinds (#912).
+ - Miscompiled Unicode character classes combining characters at or below
+ U+00FF with characters at U+0100 and U+8000 or above (#841).
+ - Incorrect JIT character advancement with PCRE2_MATCH_INVALID_UTF in UTF-8
+ and UTF-16 modes, which could skip adjacent characters (#945).
+
+* (Behaviour change) Updated Unicode support to Unicode 17.0.
+
+* (Small behaviour changes) Many small fixes, including pcre2_substitute()
+improvements, optimisation of possessive backreference matching, and
+pcre2_compile() fixes.
+
+* (Small build changes) Many small adjustments to the CMake and Zig builds.
+
+* (Security fix for very specific API usage, #937) Fixed a leak and later
+invalid free when calling the fast-path pcre2_jit_match() function with a match
+data object previously used with pcre2_match() and
+PCRE2_COPY_MATCHED_SUBJECT.
+
+* (Low-severity security fix, GHSA-q7rw-r7qq-2hx6) Fixed exposure of two
+uninitialised bytes from malloc() via pcre2_serialize_encode().
+
+
+Version 10.47 21-October-2025
+-----------------------------
+
+This is a regular semi-annual release, incorporating a few new features and
+several maintenance and build improvements.
+
+Only changes to behaviour, changes to the API, and other significant changes
+are described here. Please see the ChangeLog and Git log for further details.
+
+* (Powerful new feature) Pattern recursion of the form
+"(?1(GROUP_NAME_OR_NUM,...))" acts as a subroutine call which additionally
+returns the listed capturing groups to the calling context.
+
+* (Significant bugfix) Fixed a crash in pcre2_callout_enumerate() which is
+easily reachable on any pattern that contains a Unicode character class. If your
+application uses this function, please read the details for this change and
+evaluate its severity for your application.
+
+* (Build change) There are now linker scripts to enable symbol versioning for
+the PCRE2 dynamic libraries. Downstream Linux distributions may make use of
+this, or disable it with the new Autoconf `--disable-symvers` and CMake
+`-DPCRE2_SYMVERS` options. Linux, Solaris, and FreeBSD (GNU ld, LLVM lld, and
+Solaris ld) are tested and supported.
+
+* (New API function) Added pcre2_next_match(). This function makes it both
+simpler and safer for clients to iterate over all matches in a subject. The
+documentation in `pcre2api` also provides improved guidance in the section
+"Iterating over all matches".
+
+* (Minor API addition) Added the PCRE2_CONFIG_EFFECTIVE_LINKSIZE option to
+pcre2_config().
+
+* (Minor replacement syntax extension) Added support for $+ replacement to
+pcre2_substitute().
+
+* (Build change) Modernize the CMake build files, to use the
+"$", "$" and "install(EXPORT...)"
+expressions to export the PCRE2 targets.
+
+
+Version 10.46 27-August-2025
+----------------------------
+
+This is a security-only release, to address CVE-2025-58050.
+
+Compared to 10.45, this release has only a minimal code change to prevent a
+read-past-the-end memory error, of arbitrary length. An attacker-controlled
+regex pattern is required, and it cannot be triggered by providing crafted
+subject (match) text. The (*ACCEPT) and (*scs:) pattern features must be used
+together.
+
+Release 10.44 and earlier are not affected.
+
+This could have implications of denial-of-service or information disclosure,
+and could potentially be used to escalate other vulnerabilities in a system
+(such as information disclosure being used to escalate the severity of an
+unrelated bug in another system).
+
+
+Version 10.45 05-February-2025
+------------------------------
+
+This is a comparatively large release, incorporating new features, some
+bugfixes, and a few changes with slight backwards compatibility implications.
+Please see the ChangeLog and Git log for further details.
+
+Only changes to behaviour, changes to the API, and major changes to the pattern
+syntax are described here.
+
+This release is the first to be available as a (signed) Git tag, or
+alternatively as a (signed) tarball of the Git tag.
+
+This is also the first release to be made by the new maintainers of PCRE2, and
+we would like to thank Philip Hazel, creator and maintainer of PCRE and PCRE2.
+
+* (Git change) The sljit project has been split out into a separate Git
+ repository. Git users must now run `git submodule init; git submodule update`
+ after a Git checkout.
+
+* (Behaviour change) Update Unicode support to UCD 16.
+
+* (Match behaviour change) Case-insensitive matching of Unicode properties
+ Ll, Lt, and Lu has been changed to match Perl. Previously, /\p{Ll}/i would
+ match only lower-case characters (even though case-insensitive matching was
+ specified). This also affects case-insensitive matching of POSIX classes such
+ as [:lower:].
+
+* (Minor match behaviour change) Case-insensitive matching of backreferences now
+ respects the PCRE2_EXTRA_CASELESS_RESTRICT option.
+
+* (Minor pattern syntax change) Parsing of the \x escape is stricter, and is
+ no longer parsed as an escape for the NUL character if not followed by '{' or
+ a hexadecimal digit. Use \x00 instead.
+
+* (Major new feature) Add a new feature called scan substring. This is a new
+ type of assertion which matches the content of a capturing block to a
+ sub-pattern.
+
+ Example: to find a word that contains the rare (in English) sequence of
+ letters "rh" not at the start:
+
+ \b(\w++)(*scan_substring:(1).+rh)
+
+ The first group captures a word which is then scanned by the
+ (*scan_substring:(1) ... ) assertion, which tests whether the pattern ".+rh"
+ matches the capture group "(1)".
+
+* (Major new feature) Add support for UTS#18 compatible character classes,
+ using the new option PCRE2_ALT_EXTENDED_CLASS. This adds '[' as a
+ metacharacter within character classes and the operators '&&', '--' and '~~',
+ allowing subtractions and intersections of character classes to be easily
+ expressed.
+
+ Example: to match Thai or Greek letters (but not letters or other characters
+ in those scripts), use [\p{L}&&[\p{Thai}||\p{Greek}]].
+
+* (Major new feature) Add support for Perl-style extended character classes,
+ using the syntax (?[...]). This also allows expressing subtractions and
+ intersections of character classes, but using a different syntax to UTS#18.
+
+ Example: to match Thai or Greek letters (but not letters or other characters
+ in those scripts), use (?[\p{L} & (\p{Thai} + \p{Greek})]).
+
+* (Minor feature) Significant improvements to the character class match engine.
+ Compiled character classes are now more compact, and have faster matching
+ for large or complex character sets, using binary search through the set.
+
+* JIT compilation now fails with the new error code PCRE2_ERROR_JIT_UNSUPPORTED
+ for patterns which use features not supported by the JIT compiler.
+
+* (Minor feature) New options PCRE2_EXTRA_NO_BS0 (disallow \0 as an escape for
+ the NUL character); PCRE2_EXTRA_PYTHON_OCTAL (use Python disambiguation rules
+ for deciding whether \12 is a backreference or an octal escape);
+ PCRE2_EXTRA_NEVER_CALLOUT (disable callout syntax entirely);
+ PCRE2_EXTRA_TURKISH_CASING (use Turkish rules for case-insensitive matching).
+
+* (Minor feature) Add new API function pcre2_set_optimize() for controlling
+ which optimizations are enabled.
+
+* (Minor new features) A variety of extensions have been made to
+ pcre2_substitute() and its syntax for replacement strings. These now support:
+ \123 octal escapes; titlecasing \u\L; \1 backreferences; \g<1> and $
+ backreferences; $& $` $' and $_; new function
+ pcre2_set_substitute_case_callout() to allow locale-aware case transformation.
+
+
+Version 10.44 07-June-2024
+--------------------------
+
+This is mostly a bug-fix and tidying release. There is one new function, to set
+a maximum size for a compiled pattern. The maximum name length for groups is
+increased to 128. Some auxiliary files for building under VMS are added.
+
+
+Version 10.43 16-February-2024
+------------------------------
+
+There are quite a lot of changes in this release (see ChangeLog and Git log for
+a list). Those that are not bugfixes or code tidies are:
+
+* The JIT code no longer supports ARMv5 architecture.
+
+* A new function pcre2_get_match_data_heapframes_size() for finer heap control.
+
+* New option flags to restrict the interaction between ASCII and non-ASCII
+ characters for caseless matching and \d and friends. There are also new
+ pattern constructs to control these flags from within a pattern.
+
+* Upgrade to Unicode 15.0.0.
+
+* Treat a NULL pattern with zero length as an empty string.
+
+* Added support for limited-length variable-length lookbehind assertions, with
+ a default maximum length of 255 characters (same as Perl) but with a function
+ to adjust the limit.
+
+* Support for LoongArch in JIT.
+
+* Perl changed the meaning of (for example) {,3} which did not used to be
+ recognized as a quantifier. Now it means {0,3} and PCRE2 has also changed.
+ Note that {,} is still not a quantifier.
+
+* Following Perl, allow spaces and tabs after { and before } in all Perl-
+ compatible items that use braces, and also around commas in quantifiers. The
+ one exception in PCRE2 is \u{...}, which is from ECMAScript, not Perl, and
+ PCRE2 follows ECMAScript usage.
+
+* Changed the meaning of \w and its synonyms and derivatives (\b and \B) in UCP
+ mode to follow Perl. It now matches characters whose general categories are L
+ or N or whose particular categories are Mn (non-spacing mark) or Pc
+ (combining punctuation).
+
+* Changed the default meaning of [:xdigit:] in UCP mode to follow Perl. It now
+ matches the "fullwidth" versions of hex digits. PCRE2_EXTRA_ASCII_DIGIT can
+ be used to keep it ASCII only.
+
+* Make PCRE2_UCP the default in UTF mode in pcre2grep and add --no-ucp,
+ --case-restrict and --posix-digit.
+
+* Add --group-separator and --no-group-separator to pcre2grep.
+
+
+Version 10.42 11-December-2022
+------------------------------
+
+This is an unexpectedly early release to fix a problem that was introduced in
+10.41. ChangeLog number 19 (GitHub #139) added the default definition of
+PCRE2_CALL_CONVENTION to pcre2posix.c instead of pcre2posix.h, which meant that
+programs including pcre2posix.h but not pcre2.h couldn't compile. A new test
+that checks this case has been added.
+
+A couple of other minor issues are also fixed, and a patch for an intermittent
+JIT fault is also included. See ChangeLog and the Git log.
+
+
+Version 10.41 06-December-2022
+------------------------------
+
+This is another mainly bug-fixing and code-tidying release. There is one
+significant upgrade to pcre2grep: it now behaves like GNU grep when matching
+more than one pattern and a later pattern matches at an earlier point in the
+subject when the matched substrings are being identified by colour or by
+offsets.
+
+
+Version 10.40 15-April-2022
+---------------------------
+
+This is mostly a bug-fixing and code-tidying release. However, there are some
+extensions to Unicode property handling:
+
+* Added support for Bidi_Class and a number of binary Unicode properties,
+including Bidi_Control.
+
+* A number of changes to script matching for \p and \P:
+
+ (a) Script extensions for a character are now coded as a bitmap instead of
+ a list of script numbers, which should be faster and does not need a
+ loop.
+
+ (b) Added the syntax \p{script:xxx} and \p{script_extensions:xxx} (synonyms
+ sc and scx).
+
+ (c) Changed \p{scriptname} from being the same as \p{sc:scriptname} to being
+ the same as \p{scx:scriptname} because this change happened in Perl at
+ release 5.26.
+
+ (d) The standard Unicode 4-letter abbreviations for script names are now
+ recognized.
+
+ (e) In accordance with Unicode and Perl's "loose matching" rules, spaces,
+ hyphens, and underscores are ignored in property names, which are then
+ matched independent of case.
+
+As always, see ChangeLog for a list of all changes (also the Git log).
+
+
+Version 10.39 29-October-2021
+-----------------------------
+
+This release is happening soon after 10.38 because the bug fix is important.
+
+1. Fix incorrect detection of alternatives in first character search in JIT.
+
+2. Update to Unicode 14.0.0.
+
+3. Some code cleanups (see ChangeLog).
+
+
+Version 10.38 01-October-2021
+-----------------------------
+
+As well as some bug fixes and tidies (as always, see ChangeLog for details),
+the documentation is updated to list the new URLs, following the move of the
+source repository to GitHub and the mailing list to Google Groups.
+
+* The CMake build system can now build both static and shared libraries in one
+go.
+
+* Following Perl's lead, \K is now locked out in lookaround assertions by
+default, but an option is provided to re-enable the previous behaviour.
+
+
+Version 10.37 26-May-2021
+-------------------------
+
+A few more bug fixes and tidies. The only change of real note is the removal of
+the actual POSIX names regcomp etc. from the POSIX wrapper library because
+these have caused issues for some applications (see 10.33 #2 below).
+
+
+Version 10.36 04-December-2020
+------------------------------
+
+Again, mainly bug fixes and tidies. The only enhancements are the addition of
+GNU grep's -m (aka --max-count) option to pcre2grep, and also unifying the
+handling of substitution strings for both -O and callouts in pcre2grep, with
+the addition of $x{...} and $o{...} to allow for characters whose code points
+are greater than 255 in Unicode mode.
+
+NOTE: there is an outstanding issue with JIT support for MacOS on arm64
+hardware. For details, please see Bugzilla issue #2618.
+
+
+Version 10.35 15-April-2020
+---------------------------
+
+Bugfixes, tidies, and a few new enhancements.
+
+1. Capturing groups that contain recursive backreferences to themselves are no
+longer automatically atomic, because the restriction is no longer necessary
+as a result of the 10.30 restructuring.
+
+2. Several new options for pcre2_substitute().
+
+3. When Unicode is supported and PCRE2_UCP is set without PCRE2_UTF, Unicode
+character properties are used for upper/lower case computations on characters
+whose code points are greater than 127.
+
+4. The character tables (for low-valued characters) can now more easily be
+saved and restored in binary.
+
+5. Updated to Unicode 13.0.0.
+
+
+Version 10.34 21-November-2019
+------------------------------
+
+Another release with a few enhancements as well as bugfixes and tidies. The
+main new features are:
+
+1. There is now some support for matching in invalid UTF strings.
+
+2. Non-atomic positive lookarounds are implemented in the pcre2_match()
+interpreter, but not in JIT.
+
+3. Added two new functions: pcre2_get_match_data_size() and
+pcre2_maketables_free().
+
+4. Upgraded to Unicode 12.1.0.
+
+
+Version 10.33 16-April-2019
+---------------------------
+
+Yet more bugfixes, tidies, and a few enhancements, summarized here (see
+ChangeLog for the full list):
+
+1. Callouts from pcre2_substitute() are now available.
+
+2. The POSIX functions are now all called pcre2_regcomp() etc., with wrapper
+functions that use the standard POSIX names. However, in pcre2posix.h the POSIX
+names are defined as macros. This should help avoid linking with the wrong
+library in some environments, while still exporting the POSIX names for
+pre-existing programs that use them.
+
+3. Some new options:
+
+ (a) PCRE2_EXTRA_ESCAPED_CR_IS_LF makes \r behave as \n.
+
+ (b) PCRE2_EXTRA_ALT_BSUX enables support for ECMAScript 6's \u{hh...}
+ construct.
+
+ (c) PCRE2_COPY_MATCHED_SUBJECT causes a copy of a matched subject to be
+ made, instead of just remembering a pointer.
+
+4. Some new Perl features:
+
+ (a) Perl 5.28's experimental alphabetic names for atomic groups and
+ lookaround assertions, for example, (*pla:...) and (*atomic:...).
+
+ (b) The new Perl "script run" features (*script_run:...) and
+ (*atomic_script_run:...) aka (*sr:...) and (*asr:...).
+
+ (c) When PCRE2_UTF is set, allow non-ASCII letters and decimal digits in
+ capture group names.
+
+5. --disable-percent-zt disables the use of %zu and %td in formatting strings
+in pcre2test. They were already automatically disabled for VC and older C
+compilers.
+
+6. Some changes related to callouts in pcre2grep:
+
+ (a) Support for running an external program under VMS has been added, in
+ addition to Windows and fork() support.
+
+ (b) --disable-pcre2grep-callout-fork restricts the callout support in
+ to the inbuilt echo facility.
+
+
+Version 10.32 10-September-2018
+-------------------------------
+
+This is another mainly bugfix and tidying release with a few minor
+enhancements. These are the main ones:
+
+1. pcre2grep now supports the inclusion of binary zeros in patterns that are
+read from files via the -f option.
+
+2. ./configure now supports --enable-jit=auto, which automatically enables JIT
+if the hardware supports it.
+
+3. In pcre2_dfa_match(), internal recursive calls no longer use the stack for
+local workspace and local ovectors. Instead, an initial block of stack is
+reserved, but if this is insufficient, heap memory is used. The heap limit
+parameter now applies to pcre2_dfa_match().
+
+4. Updated to Unicode version 11.0.0.
+
+5. (*ACCEPT:ARG), (*FAIL:ARG), and (*COMMIT:ARG) are now supported.
+
+6. Added support for \N{U+dddd}, but only in Unicode mode.
+
+7. Added support for (?^) to unset all imnsx options.
+
+
+Version 10.31 12-February-2018
+------------------------------
+
+This is mainly a bugfix and tidying release (see ChangeLog for full details).
+However, there are some minor enhancements.
+
+1. New pcre2_config() options: PCRE2_CONFIG_NEVER_BACKSLASH_C and
+PCRE2_CONFIG_COMPILED_WIDTHS.
+
+2. New pcre2_pattern_info() option PCRE2_INFO_EXTRAOPTIONS to retrieve the
+extra compile time options.
+
+3. There are now public names for all the pcre2_compile() error numbers.
+
+4. Added PCRE2_CALLOUT_STARTMATCH and PCRE2_CALLOUT_BACKTRACK bits to a new
+field callout_flags in callout blocks.
+
+
+Version 10.30 14-August-2017
+----------------------------
+
+The full list of changes that includes bugfixes and tidies is, as always, in
+ChangeLog. These are the most important new features:
+
+1. The main interpreter, pcre2_match(), has been refactored into a new version
+that does not use recursive function calls (and therefore the system stack) for
+remembering backtracking positions. This makes --disable-stack-for-recursion a
+NOOP. The new implementation allows backtracking into recursive group calls in
+patterns, making it more compatible with Perl, and also fixes some other
+previously hard-to-do issues. For patterns that have a lot of backtracking, the
+heap is now used, and there is an explicit limit on the amount, settable by
+pcre2_set_heap_limit() or (*LIMIT_HEAP=xxx). The "recursion limit" is retained,
+but is renamed as "depth limit" (though the old names remain for
+compatibility).
+
+There is also a change in the way callouts from pcre2_match() are handled. The
+offset_vector field in the callout block is no longer a pointer to the
+actual ovector that was passed to the matching function in the match data
+block. Instead it points to an internal ovector of a size large enough to hold
+all possible captured substrings in the pattern.
+
+2. The new option PCRE2_ENDANCHORED insists that a pattern match must end at
+the end of the subject.
+
+3. The new option PCRE2_EXTENDED_MORE implements Perl's /xx feature, and
+pcre2test is upgraded to support it. Setting within the pattern by (?xx) is
+also supported.
+
+4. (?n) can be used to set PCRE2_NO_AUTO_CAPTURE, because Perl now has this.
+
+5. Additional compile options in the compile context are now available, and the
+first two are: PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES and
+PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL.
+
+6. The newline type PCRE2_NEWLINE_NUL is now available.
+
+7. The match limit value now also applies to pcre2_dfa_match() as there are
+patterns that can use up a lot of resources without necessarily recursing very
+deeply.
+
+8. The option REG_PEND (a GNU extension) is now available for the POSIX
+wrapper. Also there is a new option PCRE2_LITERAL which is used to support
+REG_NOSPEC.
+
+9. PCRE2_EXTRA_MATCH_LINE and PCRE2_EXTRA_MATCH_WORD are implemented for the
+benefit of pcre2grep, and pcre2grep's -F, -w, and -x options are re-implemented
+using PCRE2_LITERAL, PCRE2_EXTRA_MATCH_WORD, and PCRE2_EXTRA_MATCH_LINE. This
+is tidier and also fixes some bugs.
+
+10. The Unicode tables are upgraded from Unicode 8.0.0 to Unicode 10.0.0.
+
+11. There are some experimental functions for converting foreign patterns
+(globs and POSIX patterns) into PCRE2 patterns.
+
+
+Version 10.23 14-February-2017
+------------------------------
+
+1. ChangeLog has the details of a lot of bug fixes and tidies.
+
+2. There has been a major re-factoring of the pcre2_compile.c file. Most syntax
+checking is now done in the pre-pass that identifies capturing groups. This has
+reduced the amount of duplication and made the code tidier. While doing this,
+some minor bugs and Perl incompatibilities were fixed (see ChangeLog for
+details.)
+
+3. Back references are now permitted in lookbehind assertions when there are
+no duplicated group numbers (that is, (?| has not been used), and, if the
+reference is by name, there is only one group of that name. The referenced
+group must, of course be of fixed length.
+
+4. \g{+} (e.g. \g{+2} ) is now supported. It is a "forward back
+reference" and can be useful in repetitions (compare \g{-} ). Perl does
+not recognize this syntax.
+
+5. pcre2grep now automatically expands its buffer up to a maximum set by
+--max-buffer-size.
+
+6. The -t option (grand total) has been added to pcre2grep.
+
+7. A new function called pcre2_code_copy_with_tables() exists to copy a
+compiled pattern along with a private copy of the character tables that is
+uses.
+
+8. A user supplied a number of patches to upgrade pcre2grep under Windows and
+tidy the code.
+
+9. Several updates have been made to pcre2test and test scripts (see
+ChangeLog).
+
+
+Version 10.22 29-July-2016
+--------------------------
+
+1. ChangeLog has the details of a number of bug fixes.
+
+2. The POSIX wrapper function regcomp() did not used to support back references
+and subroutine calls if called with the REG_NOSUB option. It now does.
+
+3. A new function, pcre2_code_copy(), is added, to make a copy of a compiled
+pattern.
+
+4. Support for string callouts is added to pcre2grep.
+
+5. Added the PCRE2_NO_JIT option to pcre2_match().
+
+6. The pcre2_get_error_message() function now returns with a negative error
+code if the error number it is given is unknown.
+
+7. Several updates have been made to pcre2test and test scripts (see
+ChangeLog).
+
+
+Version 10.21 12-January-2016
+-----------------------------
+
+1. Many bugs have been fixed. A large number of them were provoked only by very
+strange pattern input, and were discovered by fuzzers. Some others were
+discovered by code auditing. See ChangeLog for details.
+
+2. The Unicode tables have been updated to Unicode version 8.0.0.
+
+3. For Perl compatibility in EBCDIC environments, ranges such as a-z in a
+class, where both values are literal letters in the same case, omit the
+non-letter EBCDIC code points within the range.
+
+4. There have been a number of enhancements to the pcre2_substitute() function,
+giving more flexibility to replacement facilities. It is now also possible to
+cause the function to return the needed buffer size if the one given is too
+small.
+
+5. The PCRE2_ALT_VERBNAMES option causes the "name" parts of special verbs such
+as (*THEN:name) to be processed for backslashes and to take note of
+PCRE2_EXTENDED.
+
+6. PCRE2_INFO_HASBACKSLASHC makes it possible for a client to find out if a
+pattern uses \C, and --never-backslash-C makes it possible to compile a version
+PCRE2 in which the use of \C is always forbidden.
+
+7. A limit to the length of pattern that can be handled can now be set by
+calling pcre2_set_max_pattern_length().
+
+8. When matching an unanchored pattern, a match can be required to begin within
+a given number of code units after the start of the subject by calling
+pcre2_set_offset_limit().
+
+9. The pcre2test program has been extended to test new facilities, and it can
+now run the tests when LF on its own is not a valid newline sequence.
+
+10. The RunTest script has also been updated to enable more tests to be run.
+
+11. There have been some minor performance enhancements.
+
+
+Version 10.20 30-June-2015
+--------------------------
+
+1. Callouts with string arguments and the pcre2_callout_enumerate() function
+have been implemented.
+
+2. The PCRE2_NEVER_BACKSLASH_C option, which locks out the use of \C, is added.
+
+3. The PCRE2_ALT_CIRCUMFLEX option lets ^ match after a newline at the end of a
+subject in multiline mode.
+
+4. The way named subpatterns are handled has been refactored. The previous
+approach had several bugs.
+
+5. The handling of \c in EBCDIC environments has been changed to conform to the
+perlebcdic document. This is an incompatible change.
+
+6. Bugs have been mended, many of them discovered by fuzzers.
+
+
+Version 10.10 06-March-2015
+---------------------------
+
+1. Serialization and de-serialization functions have been added to the API,
+making it possible to save and restore sets of compiled patterns, though
+restoration must be done in the same environment that was used for compilation.
+
+2. The (*NO_JIT) feature has been added; this makes it possible for a pattern
+creator to specify that JIT is not to be used.
+
+3. A number of bugs have been fixed. In particular, bugs that caused building
+on Windows using CMake to fail have been mended.
+
+
+Version 10.00 05-January-2015
+-----------------------------
+
+Version 10.00 is the first release of PCRE2, a revised API for the PCRE
+library. Changes prior to 10.00 are logged in the ChangeLog file for the old
+API, up to item 20 for release 8.36. New programs are recommended to use the
+new library. Programs that use the original (PCRE1) API will need changing
+before linking with the new library.
+
+****
diff --git a/NON-AUTOTOOLS-BUILD b/NON-AUTOTOOLS-BUILD
new file mode 100644
index 0000000..45c8bad
--- /dev/null
+++ b/NON-AUTOTOOLS-BUILD
@@ -0,0 +1,487 @@
+Building PCRE2 without using autotools
+======================================
+
+This document contains the following sections:
+
+ General
+ Generic instructions for the PCRE2 C libraries
+ Stack size in Windows environments
+ Linking programs in Windows environments
+ Calling conventions in Windows environments
+ Comments about Win32 builds
+ Building PCRE2 on Windows with CMake
+ Building PCRE2 on Windows with Visual Studio
+ Testing with RunTest.bat
+ Building PCRE2 on z/OS and z/VM
+ Building PCRE2 under VMS
+
+
+General
+-------
+
+The source of the PCRE2 libraries consists entirely of code written in Standard
+C, and so should compile successfully on any system that has a Standard C
+compiler and library.
+
+The PCRE2 distribution includes a "configure" file for use by the
+configure/make (autotools) build system, as found in many Unix-like
+environments. The README file contains information about the options for
+"configure".
+
+There is also support for CMake, which some users prefer, especially in Windows
+environments, though it can also be run in Unix-like environments. See the
+section entitled "Building PCRE2 on Windows with CMake" below.
+
+Versions of src/config.h and src/pcre2.h are distributed in the PCRE2 tarballs
+under the names src/config.h.generic and src/pcre2.h.generic. These are
+provided for those who build PCRE2 without using "configure" or CMake. If you
+use "configure" or CMake, the .generic versions are not used.
+
+
+Generic instructions for the PCRE2 C libraries
+----------------------------------------------
+
+There are three possible PCRE2 libraries, each handling data with a specific
+code unit width: 8, 16, or 32 bits. You can build any combination of them. The
+following are generic instructions for building a PCRE2 C library "by hand". If
+you are going to use CMake, this section does not apply to you; you can skip
+ahead to the CMake section. Note that the settings concerned with 8-bit,
+16-bit, and 32-bit code units relate to the type of data string that PCRE2
+processes. They are NOT referring to the underlying operating system bit width.
+You do not have to do anything special to compile in a 64-bit environment, for
+example.
+
+ (1) Copy or rename the file src/config.h.generic as src/config.h, and edit the
+ macro settings that it contains to whatever is appropriate for your
+ environment. In particular, you can alter the definition of the NEWLINE
+ macro to specify what character(s) you want to be interpreted as line
+ terminators by default. You need to #define at least one of
+ SUPPORT_PCRE2_8, SUPPORT_PCRE2_16, or SUPPORT_PCRE2_32, depending on which
+ libraries you are going to build. You must set all that apply.
+
+ When you subsequently compile any of the PCRE2 modules, you must specify
+ -DHAVE_CONFIG_H to your compiler so that src/config.h is included in the
+ sources.
+
+ An alternative approach is not to edit src/config.h, but to use -D on the
+ compiler command line to make any changes that you need to the
+ configuration options. In this case -DHAVE_CONFIG_H must not be set.
+
+ NOTE: There have been occasions when the way in which certain parameters
+ in src/config.h are used has changed between releases. (In the
+ configure/make world, this is handled automatically.) When upgrading to a
+ new release, you are strongly advised to review src/config.h.generic
+ before re-using what you had previously.
+
+ Note also that the src/config.h.generic file is created from a config.h
+ that was generated by Autotools, which automatically includes settings of
+ a number of macros that are not actually used by PCRE2 (for example,
+ HAVE_DLFCN_H).
+
+ (2) Copy or rename the file src/pcre2.h.generic as src/pcre2.h.
+
+ (3) EITHER:
+ Copy or rename file src/pcre2_chartables.c.dist as
+ src/pcre2_chartables.c.
+
+ OR:
+ Compile src/pcre2_dftables.c as a stand-alone program (using
+ -DHAVE_CONFIG_H if you have set up src/config.h), and then run it with
+ the single argument "src/pcre2_chartables.c". This generates a set of
+ standard character tables and writes them to that file. The tables are
+ generated using the default C locale for your system. If you want to use
+ a locale that is specified by LC_xxx environment variables, add the -L
+ option to the pcre2_dftables command. You must use this method if you
+ are building on a system that uses EBCDIC code.
+
+ The tables in src/pcre2_chartables.c are defaults. The caller of PCRE2 can
+ specify alternative tables at run time.
+
+ (4) For a library that supports 8-bit code units in the character strings that
+ it processes, compile the following source files from the src directory,
+ setting -DPCRE2_CODE_UNIT_WIDTH=8 as a compiler option. Also set
+ -DHAVE_CONFIG_H if you have set up src/config.h with your configuration,
+ or else use other -D settings to change the configuration as required.
+
+ pcre2_auto_possess.c
+ pcre2_chkdint.c
+ pcre2_chartables.c
+ pcre2_compile.c
+ pcre2_compile_cgroup.c
+ pcre2_compile_class.c
+ pcre2_config.c
+ pcre2_context.c
+ pcre2_convert.c
+ pcre2_dfa_match.c
+ pcre2_error.c
+ pcre2_extuni.c
+ pcre2_find_bracket.c
+ pcre2_jit_compile.c
+ pcre2_maketables.c
+ pcre2_match.c
+ pcre2_match_data.c
+ pcre2_match_next.c
+ pcre2_newline.c
+ pcre2_ord2utf.c
+ pcre2_pattern_info.c
+ pcre2_script_run.c
+ pcre2_serialize.c
+ pcre2_string_utils.c
+ pcre2_study.c
+ pcre2_substitute.c
+ pcre2_substring.c
+ pcre2_tables.c
+ pcre2_ucd.c
+ pcre2_valid_utf.c
+ pcre2_xclass.c
+
+ Make sure that you include -I. in the compiler command (or equivalent for
+ an unusual compiler) so that all included PCRE2 header files are first
+ sought in the src directory under the current directory. Otherwise you run
+ the risk of picking up a previously-installed file from somewhere else.
+
+ Note that you must compile pcre2_jit_compile.c, even if you have not
+ defined SUPPORT_JIT in src/config.h, because when JIT support is not
+ configured, dummy functions are compiled. When JIT support IS configured,
+ pcre2_jit_compile.c #includes other files from the sljit dependency,
+ all of whose names begin with "sljit".
+
+ Note also that the pcre2_fuzzsupport.c file contains special code that is
+ useful to those who want to run fuzzing tests on the PCRE2 library. Unless
+ you are doing that, you can ignore it.
+
+ (5) Now link all the compiled code into an object library in whichever form
+ your system keeps such libraries. This is the PCRE2 C 8-bit library,
+ typically called something like libpcre2-8. If your system has static and
+ shared libraries, you may have to do this once for each type.
+
+ (6) If you want to build a library that supports 16-bit or 32-bit code units,
+ set 16 or 32 as the value of -DPCRE2_CODE_UNIT_WIDTH when obeying step 4
+ above. If you want to build more than one PCRE2 library, repeat steps 4
+ and 5 as necessary.
+
+ (7) If you want to build the POSIX wrapper functions (which apply only to the
+ 8-bit library), ensure that you have the src/pcre2posix.h file and then
+ compile src/pcre2posix.c. Link the result (on its own) as the pcre2posix
+ library. If targeting a DLL in Windows, make sure to include
+ -DPCRE2POSIX_SHARED with your compiler flags.
+
+ (8) The pcre2test program can be linked with any combination of the 8-bit,
+ 16-bit and 32-bit libraries (depending on what you specfied in
+ src/config.h) . Compile src/pcre2test.c; don't forget -DHAVE_CONFIG_H if
+ necessary, but do NOT define PCRE2_CODE_UNIT_WIDTH. Then link with the
+ appropriate library/ies. If you compiled an 8-bit library, pcre2test also
+ needs the pcre2posix wrapper library when linking.
+
+ (9) Run pcre2test on the testinput files in the testdata directory, and check
+ that the output matches the corresponding testoutput files. There are
+ comments about what each test does in the section entitled "Testing PCRE2"
+ in the README file. If you compiled more than one of the 8-bit, 16-bit and
+ 32-bit libraries, you need to run pcre2test with the -16 option to do
+ 16-bit tests and with the -32 option to do 32-bit tests.
+
+ Some tests are relevant only when certain build-time options are selected.
+ For example, test 4 is for Unicode support, and will not run if you have
+ built PCRE2 without it. See the comments at the start of each testinput
+ file. If you have a suitable Unix-like shell, the RunTest script will run
+ the appropriate tests for you. The command "RunTest list" will output a
+ list of all the tests.
+
+ Note that the supplied files are in Unix format, with just LF characters
+ as line terminators. You may need to edit them to change this if your
+ system uses a different convention.
+
+(10) If you have built PCRE2 with SUPPORT_JIT, the JIT features can be tested
+ by running pcre2test with the -jit option. This is done automatically by
+ the RunTest script. You might also like to build and run the freestanding
+ JIT test program, src/pcre2_jit_test.c.
+
+(11) The pcre2test program tests the POSIX wrapper library, but there is also a
+ freestanding test program in src/pcre2posix_test.c. It must be linked with
+ both the pcre2posix library and the 8-bit PCRE2 library.
+
+(12) If you want to use the pcre2grep command, compile and link
+ src/pcre2grep.c; it uses only the 8-bit PCRE2 library (it does not need
+ the pcre2posix library). If you have built the PCRE2 library with JIT
+ support by defining SUPPORT_JIT in src/config.h, you can also define
+ SUPPORT_PCRE2GREP_JIT, which causes pcre2grep to make use of JIT (unless
+ it is run with --no-jit). If you define SUPPORT_PCRE2GREP_JIT without
+ defining SUPPORT_JIT, pcre2grep does not try to make use of JIT.
+
+
+Stack size in Windows environments
+----------------------------------
+
+Prior to release 10.30 the default system stack size of 1MiB in some Windows
+environments caused issues with some tests. This should no longer be the case
+for 10.30 and later releases.
+
+
+Linking programs in Windows environments
+----------------------------------------
+
+If you want to statically link a program against a PCRE2 library in the form of
+a non-dll .a file, you must define PCRE2_STATIC before including src/pcre2.h.
+
+
+Calling conventions in Windows environments
+-------------------------------------------
+
+It is possible to compile programs to use different calling conventions using
+MSVC. Search the web for "calling conventions" for more information. To make it
+easier to change the calling convention for the exported functions in a
+PCRE2 library, the macro PCRE2_CALL_CONVENTION is present in all the external
+definitions. It can be set externally when compiling (e.g. in CFLAGS). If it is
+not set, it defaults to empty; the default calling convention is then used
+(which is what is wanted most of the time).
+
+
+Comments about Win32 builds (see also "Building PCRE2 on Windows with CMake")
+---------------------------
+
+There are two ways of building PCRE2 using the "configure, make, make install"
+paradigm on Windows systems: using MinGW or using Cygwin. These are not at all
+the same thing; they are completely different from each other. There is also
+support for building using CMake, which some users find a more straightforward
+way of building PCRE2 under Windows.
+
+The MinGW home page (http://www.mingw.org/) says this:
+
+ MinGW: A collection of freely available and freely distributable Windows
+ specific header files and import libraries combined with GNU toolsets that
+ allow one to produce native Windows programs that do not rely on any
+ 3rd-party C runtime DLLs.
+
+The Cygwin home page (http://www.cygwin.com/) says this:
+
+ Cygwin is a Linux-like environment for Windows. It consists of two parts:
+
+ . A DLL (cygwin1.dll) which acts as a Linux API emulation layer providing
+ substantial Linux API functionality
+
+ . A collection of tools which provide Linux look and feel.
+
+On both MinGW and Cygwin, PCRE2 should build correctly using:
+
+ ./configure && make && make install
+
+This should create two libraries called libpcre2-8 and libpcre2-posix. These
+are independent libraries: when you link with libpcre2-posix you must also link
+with libpcre2-8, which contains the basic functions.
+
+Using Cygwin's compiler generates libraries and executables that depend on
+cygwin1.dll. If a library that is generated this way is distributed,
+cygwin1.dll has to be distributed as well. Since cygwin1.dll is under the GPL
+licence, this forces not only PCRE2 to be under the GPL, but also the entire
+application. A distributor who wants to keep their own code proprietary must
+purchase an appropriate Cygwin licence.
+
+MinGW has no such restrictions. The MinGW compiler generates a library or
+executable that can run standalone on Windows without any third party dll or
+licensing issues.
+
+But there is more complication:
+
+If a Cygwin user uses the -mno-cygwin Cygwin gcc flag, what that really does is
+to tell Cygwin's gcc to use the MinGW gcc. Cygwin's gcc is only acting as a
+front end to MinGW's gcc (if you install Cygwin's gcc, you get both Cygwin's
+gcc and MinGW's gcc). So, a user can:
+
+. Build native binaries by using MinGW or by getting Cygwin and using
+ -mno-cygwin.
+
+. Build binaries that depend on cygwin1.dll by using Cygwin with the normal
+ compiler flags.
+
+The test files that are supplied with PCRE2 are in UNIX format, with LF
+characters as line terminators. Unless your PCRE2 library uses a default
+newline option that includes LF as a valid newline, it may be necessary to
+change the line terminators in the test files to get some of the tests to work.
+
+
+Building PCRE2 on Windows with CMake
+------------------------------------
+
+CMake is an alternative configuration facility that can be used instead of
+"configure". CMake creates project files (make files, solution files, etc.)
+tailored to numerous development environments, including Visual Studio,
+Borland, Msys, MinGW, NMake, and Unix. If possible, use short paths with no
+spaces in the names for your CMake installation and your PCRE2 source and build
+directories.
+
+If you are using CMake and encounter errors, deleting the CMake cache and
+restarting from a fresh build may fix the error. In the CMake GUI, the cache can
+be deleted by selecting "File > Delete Cache"; or the folder "CMakeCache" can
+be deleted.
+
+1. Install the latest CMake version available from http://www.cmake.org/, and
+ ensure that cmake\bin is on your path.
+
+2. Unzip (retaining folder structure) the PCRE2 source tree into a source
+ directory such as C:\pcre2. You should ensure your local date and time
+ is not earlier than the file dates in your source dir if the release is
+ very new.
+
+3. Create a new, empty build directory, preferably a subdirectory of the
+ source dir. For example, C:\pcre2\pcre2-xx\build.
+
+4. Run CMake.
+
+ - Using the CLI, simply run `cmake ..` inside the `build/` directory. You can
+ use the `ccmake` ncurses GUI to select and configure PCRE2 features.
+
+ - Using the CMake GUI:
+
+ a) Run cmake-gui from the Shell environment of your build tool, for
+ example, Msys for Msys/MinGW or Visual Studio Command Prompt for
+ VC/VC++.
+
+ b) Enter C:\pcre2\pcre2-xx and C:\pcre2\pcre2-xx\build for the source and
+ build directories, respectively.
+
+ c) Press the "Configure" button.
+
+ d) Select the particular IDE / build tool that you are using (Visual
+ Studio, MSYS makefiles, MinGW makefiles, etc.)
+
+ e) The GUI will then list several configuration options. This is where
+ you can disable Unicode support or select other PCRE2 optional features.
+
+ f) Press "Configure" again. The adjacent "Generate" button should now be
+ active.
+
+ g) Press "Generate".
+
+5. The build directory should now contain a usable build system, be it a
+ solution file for Visual Studio, makefiles for MinGW, etc. Exit from
+ cmake-gui and use the generated build system with your compiler or IDE.
+ E.g., for MinGW you can run "make", or for Visual Studio, open the PCRE2
+ solution, select the desired configuration (Debug, or Release, etc.) and
+ build the ALL_BUILD project.
+
+ Regardless of build system used, `cmake --build .` will build it.
+
+6. If during configuration with cmake-gui you've elected to build the test
+ programs, you can execute them by building the test project. E.g., for
+ MinGW: "make test"; for Visual Studio build the RUN_TESTS project. The
+ most recent build configuration is targeted by the tests. A summary of
+ test results is presented. Complete test output is subsequently
+ available for review in Testing\Temporary under your build dir.
+
+ Regardless of build system used, `ctest` will run the tests.
+
+
+Building PCRE2 on Windows with Visual Studio
+--------------------------------------------
+
+The code currently cannot be compiled without an inttypes.h header, which is
+available only with Visual Studio 2013 or newer. However, this portable and
+permissively-licensed implementation of the stdint.h header could be used as an
+alternative:
+
+ http://www.azillionmonkeys.com/qed/pstdint.h
+
+Just rename it and drop it into the top level of the build tree.
+
+
+Testing with RunTest.bat
+------------------------
+
+If configured with CMake, building the test project ("make test" or building
+ALL_TESTS in Visual Studio) creates (and runs) pcre2_test.bat (and depending
+on your configuration options, possibly other test programs) in the build
+directory. The pcre2_test.bat script runs RunTest.bat with correct source and
+exe paths.
+
+For manual testing with RunTest.bat, provided the build dir is a subdirectory
+of the source directory: Open command shell window. Chdir to the location
+of your pcre2test.exe and pcre2grep.exe programs. Call RunTest.bat with
+"..\RunTest.Bat" or "..\..\RunTest.bat" as appropriate.
+
+To run only a particular test with RunTest.Bat provide a test number argument.
+
+Otherwise:
+
+1. Copy RunTest.bat into the directory where pcre2test.exe and pcre2grep.exe
+ have been created.
+
+2. Edit RunTest.bat to identify the full or relative location of
+ the pcre2 source (wherein which the testdata folder resides), e.g.:
+
+ set srcdir=C:\pcre2\pcre2-10.00
+
+3. In a Windows command environment, chdir to the location of your bat and
+ exe programs.
+
+4. Run RunTest.bat. Test outputs will automatically be compared to expected
+ results, and discrepancies will be identified in the console output.
+
+To independently test the just-in-time compiler, run pcre2_jit_test.exe.
+
+
+Building PCRE2 on z/OS and z/VM
+-------------------------------
+
+z/OS and z/VM are operating systems for mainframe computers, produced by IBM.
+The character code used is EBCDIC, not ASCII or Unicode. In z/OS, UNIX APIs and
+applications can be supported through UNIX System Services.
+
+The PCRE2 codebase compiles and runs with native EBCDIC support on modern z/OS
+systems, using the pre-installed tools (/bin/sh, ./configure, and the XLC or
+IBM-Clang compilers). PCRE2 supports z/OS using both Autoconf (./configure) and
+CMake (which IBM distributes via "zopen install cmake").
+
+Note that as of the time of writing, IBM's port of CMake to z/OS has only
+partial support for EBCDIC. It is recommended to build PCRE2 using the
+./configure script, if you require an EBCDIC build.
+
+Any EBCDIC codepage should work (PCRE2 does not assume or require IBM-1047), or
+PCRE2 can compiled for ASCII/Latin-1/Unicode.
+
+After unpacking the PCRE2 tarball, you must subsequently tag the files as ASCII
+in order for the z/OS shell and compiler to interpret them correctly:
+ chtag -R -tc ISO8859-1
+
+Some unusual features on the IBM platform are:
+ - The _ALL_SOURCE macro must be provided. Unlike on Linux or macOS, even quite
+ standard POSIX APIs are not made visible by default. PCRE2's Autoconf and
+ CMake system both provide this for you.
+ - The `cc`, `c89`, and even `c99` compilers provided by IBM do not default to
+ the same argument ordering as other Unix platforms.
+ - The XLC compiler requires `-qhaltonmsg=CCN3296`, otherwise it will treat any
+ preprocessor #include errors as a warning rather than an error. Needless to
+ say this default wrecks Autoconf and CMake's feature-detection tests.
+ PCRE2's build system is aware of this.
+ - The test suite (in the testdata/ directory) is entirely in ASCII/UTF-8.
+ When running the tests, you must ensure that the EBCDIC-native build of
+ pcre2test receives an EBCDIC version of these files. The easiest way to
+ achieve this is via filesystem tagging (chtag). Alternatively, you could
+ manually re-encode the testdata files as EBCDIC, and tag them as EBCDIC.
+ (Latin-1 and EBCDIC are one-to-one convertible encodings, a simple
+ byte-by-byte permutation of the 256 values.)
+
+In native z/OS (without UNIX System Services) and in z/VM, a user has provided a
+special port of PCRE2. For details, please see file 939 on this web site:
+
+ http://www.cbttape.org
+
+The user-provided port also provides an API for LE languages such as COBOL and
+for the z/OS and z/VM versions of the Rexx languages.
+
+
+Building PCRE2 under VMS
+------------------------
+
+Alexey Chuphin has contributed some auxiliary files for building PCRE2 under
+OpenVMS. They are in the "vms" directory in the distribution tarball. Please
+read the file called vms/openvms_readme.txt. The pcre2test and pcre2grep
+programs contain some VMS-specific code.
+
+This has not been tested for some time. The PCRE2 maintainers would be grateful
+to learn whether it still works (or if anyone still uses it).
+
+
+=============================
+Last updated: 17 October 2025
+=============================
+
diff --git a/README b/README
new file mode 100644
index 0000000..3adf495
--- /dev/null
+++ b/README
@@ -0,0 +1,1008 @@
+README file for PCRE2 (Perl-compatible regular expression library)
+==================================================================
+
+PCRE2 is a re-working of the original PCRE1 library to provide an entirely new
+API. Since its initial release in 2015, there has been further development of
+the code and it now differs from PCRE1 in more than just the API. There are new
+features, and the internals have been improved. The original PCRE1 library is
+now obsolete and no longer maintained. The latest release of PCRE2 is available
+in .tar.gz, tar.bz2, or .zip form from this GitHub repository:
+
+https://github.com/PCRE2Project/pcre2/releases
+
+There is a mailing list for discussion about the development of PCRE2 at
+pcre2-dev@googlegroups.com. You can subscribe by sending an email to
+pcre2-dev+subscribe@googlegroups.com.
+
+You can access the archives and also subscribe or manage your subscription
+here:
+
+https://groups.google.com/g/pcre2-dev
+
+Please read the NEWS file if you are upgrading from a previous release. The
+contents of this README file are:
+
+ The PCRE2 APIs
+ Documentation for PCRE2
+ Building PCRE2 on non-Unix-like systems
+ Building PCRE2 without using autotools
+ Building PCRE2 using autotools
+ Retrieving configuration information
+ Shared libraries
+ Cross-compiling using autotools
+ Making new tarballs
+ Testing PCRE2
+ Character tables
+ File manifest
+
+
+The PCRE2 APIs
+--------------
+
+PCRE2 is written in C, and it has its own API. There are three sets of
+functions, one for the 8-bit library, which processes strings of bytes, one for
+the 16-bit library, which processes strings of 16-bit values, and one for the
+32-bit library, which processes strings of 32-bit values. Unlike PCRE1, there
+are no C++ wrappers.
+
+The distribution does contain a set of C wrapper functions for the 8-bit
+library that are based on the POSIX regular expression API (see the pcre2posix
+man page). These are built into a library called libpcre2-posix. Note that this
+just provides a POSIX calling interface to PCRE2; the regular expressions
+themselves still follow Perl syntax and semantics. The POSIX API is restricted,
+and does not give full access to all of PCRE2's facilities.
+
+The header file for the POSIX-style functions is called pcre2posix.h. The
+official POSIX name is regex.h, but I did not want to risk possible problems
+with existing files of that name by distributing it that way. To use PCRE2 with
+an existing program that uses the POSIX API, pcre2posix.h will have to be
+renamed or pointed at by a link (or the program modified, of course). See the
+pcre2posix documentation for more details.
+
+
+Documentation for PCRE2
+-----------------------
+
+If you install PCRE2 in the normal way on a Unix-like system, you will end up
+with a set of man pages whose names all start with "pcre2". The one that is
+just called "pcre2" lists all the others. In addition to these man pages, the
+PCRE2 documentation is supplied in two other forms:
+
+ 1. There are files called doc/pcre2.txt, doc/pcre2grep.txt, and
+ doc/pcre2test.txt in the source distribution. The first of these is a
+ concatenation of the text forms of all the section 3 man pages except the
+ listing of pcre2demo.c and those that summarize individual functions. The
+ other two are the text forms of the section 1 man pages for the pcre2grep
+ and pcre2test commands. These text forms are provided for ease of scanning
+ with text editors or similar tools. They are installed in
+ /share/doc/pcre2, where is the installation prefix
+ (defaulting to /usr/local).
+
+ 2. A set of files containing all the documentation in HTML form, hyperlinked
+ in various ways, and rooted in a file called index.html, is distributed in
+ doc/html and installed in /share/doc/pcre2/html.
+
+
+Building PCRE2 on non-Unix-like systems
+---------------------------------------
+
+For a non-Unix-like system, please read the file NON-AUTOTOOLS-BUILD, though if
+your system supports the use of "configure" and "make" you may be able to build
+PCRE2 using autotools in the same way as for many Unix-like systems. This file
+also contains useful information on building for some unusual Unix environments
+(such as EBCDIC mainframes).
+
+PCRE2 can also be configured using CMake, which can be run in various ways
+(command line, GUI, etc). This creates Makefiles, solution files, etc. The file
+NON-AUTOTOOLS-BUILD has information about CMake.
+
+PCRE2 has been compiled on many different operating systems. It should be
+straightforward to build PCRE2 on any system that has a C99 or later compiler
+and library.
+
+
+Building PCRE2 without using autotools
+--------------------------------------
+
+The use of autotools (in particular, libtool) is problematic in some
+environments, even some that are Unix or Unix-like. See the NON-AUTOTOOLS-BUILD
+file for ways of building PCRE2 without using autotools.
+
+
+Building PCRE2 using autotools
+------------------------------
+
+The following instructions assume the use of the widely used "configure; make;
+make install" (autotools) process.
+
+If you have downloaded and unpacked a PCRE2 release tarball, run the
+"configure" command from the PCRE2 directory, with your current directory set
+to the directory where you want the files to be created. This command is a
+standard GNU "autoconf" configuration script, for which generic instructions
+are supplied in the file INSTALL.
+
+The files in the GitHub repository do not contain "configure". If you have
+downloaded the PCRE2 source files from GitHub, before you can run "configure"
+you must run the shell script called autogen.sh. This runs a number of
+autotools to create a "configure" script (you must of course have the autotools
+commands installed in order to do this).
+
+Most commonly, people build PCRE2 within its own distribution directory, and in
+this case, on many systems, just running "./configure" is sufficient. However,
+the usual methods of changing standard defaults are available. For example:
+
+CFLAGS='-O2 -Wall' ./configure --prefix=/opt/local
+
+This command specifies that the C compiler should be run with the flags '-O2
+-Wall' instead of the default, and that "make install" should install PCRE2
+under /opt/local instead of the default /usr/local.
+
+If you want to build in a different directory, just run "configure" with that
+directory as current. For example, suppose you have unpacked the PCRE2 source
+into /source/pcre2/pcre2-xxx, but you want to build it in
+/build/pcre2/pcre2-xxx:
+
+cd /build/pcre2/pcre2-xxx
+/source/pcre2/pcre2-xxx/configure
+
+PCRE2 is written in C and is normally compiled as a C library. However, it is
+possible to build it as a C++ library, though the provided building apparatus
+does not have any features to support this.
+
+There are some optional features that can be included or omitted from the PCRE2
+library. They are also documented in the pcre2build man page.
+
+. By default, both shared and static libraries are built. You can change this
+ by adding one of these options to the "configure" command:
+
+ --disable-shared
+ --disable-static
+
+ Setting --disable-shared ensures that PCRE2 libraries are built as static
+ libraries. The binaries that are then created as part of the build process
+ (for example, pcre2test and pcre2grep) are linked statically with one or more
+ PCRE2 libraries, but may also be dynamically linked with other libraries such
+ as libc. If you want these binaries to be fully statically linked, you can
+ set LDFLAGS like this:
+
+ LDFLAGS=--static ./configure --disable-shared
+
+ Note the two hyphens in --static. Of course, this works only if static
+ versions of all the relevant libraries are available for linking. See also
+ "Shared libraries" below.
+
+ Shared libraries are compiled with symbol versioning enabled on platforms that
+ support this, but this can be disabled by adding --disable-symvers.
+
+. By default, only the 8-bit library is built. If you add --enable-pcre2-16 to
+ the "configure" command, the 16-bit library is also built. If you add
+ --enable-pcre2-32 to the "configure" command, the 32-bit library is also
+ built. If you want only the 16-bit or 32-bit library, use --disable-pcre2-8
+ to disable building the 8-bit library.
+
+. If you want to include support for just-in-time (JIT) compiling, which can
+ give large performance improvements on certain platforms, add --enable-jit to
+ the "configure" command. This support is available only for certain hardware
+ architectures. If you try to enable it on an unsupported architecture, there
+ will be a compile time error. If in doubt, use --enable-jit=auto, which
+ enables JIT only if the current hardware is supported.
+
+. If you are enabling JIT under SELinux environment you may also want to add
+ --enable-jit-sealloc, which enables the use of an executable memory allocator
+ that is compatible with SELinux. Warning: this allocator is experimental!
+ It does not support fork() operation and may crash when no disk space is
+ available. This option has no effect if JIT is disabled.
+
+. If you do not want to make use of the default support for UTF-8 Unicode
+ character strings in the 8-bit library, UTF-16 Unicode character strings in
+ the 16-bit library, or UTF-32 Unicode character strings in the 32-bit
+ library, you can add --disable-unicode to the "configure" command. This
+ reduces the size of the libraries. It is not possible to configure one
+ library with Unicode support, and another without, in the same configuration.
+ It is also not possible to use --enable-ebcdic (see below) with Unicode
+ support, so if this option is set, you must also use --disable-unicode.
+
+ When Unicode support is available, the use of a UTF encoding still has to be
+ enabled by setting the PCRE2_UTF option at run time or starting a pattern
+ with (*UTF). When PCRE2 is compiled with Unicode support, its input can only
+ either be ASCII or UTF-8/16/32, even when running on EBCDIC platforms.
+
+ As well as supporting UTF strings, Unicode support includes support for the
+ \P, \p, and \X sequences that recognize Unicode character properties.
+ However, only a subset of Unicode properties are supported; see the
+ pcre2pattern man page for details. Escape sequences such as \d and \w in
+ patterns do not by default make use of Unicode properties, but can be made to
+ do so by setting the PCRE2_UCP option or starting a pattern with (*UCP).
+
+. You can build PCRE2 to recognize either CR or LF or the sequence CRLF, or any
+ of the preceding, or any of the Unicode newline sequences, or the NUL (zero)
+ character as indicating the end of a line. Whatever you specify at build time
+ is the default; the caller of PCRE2 can change the selection at run time. The
+ default newline indicator is a single LF character (the Unix standard). You
+ can specify the default newline indicator by adding --enable-newline-is-cr,
+ --enable-newline-is-lf, --enable-newline-is-crlf,
+ --enable-newline-is-anycrlf, --enable-newline-is-any, or
+ --enable-newline-is-nul to the "configure" command, respectively.
+
+. By default, the sequence \R in a pattern matches any Unicode line ending
+ sequence. This is independent of the option specifying what PCRE2 considers
+ to be the end of a line (see above). However, the caller of PCRE2 can
+ restrict \R to match only CR, LF, or CRLF. You can make this the default by
+ adding --enable-bsr-anycrlf to the "configure" command (bsr = "backslash R").
+
+. In a pattern, the escape sequence \C matches a single code unit, even in a
+ UTF mode. This can be dangerous because it breaks up multi-code-unit
+ characters. You can build PCRE2 with the use of \C permanently locked out by
+ adding --enable-never-backslash-C (note the upper case C) to the "configure"
+ command. When \C is allowed by the library, individual applications can lock
+ it out by calling pcre2_compile() with the PCRE2_NEVER_BACKSLASH_C option.
+
+. PCRE2 has a counter that limits the depth of nesting of parentheses in a
+ pattern. This limits the amount of system stack that a pattern uses when it
+ is compiled. The default is 250, but you can change it by setting, for
+ example,
+
+ --with-parens-nest-limit=500
+
+. PCRE2 has a counter that can be set to limit the amount of computing resource
+ it uses when matching a pattern. If the limit is exceeded during a match, the
+ match fails. The default is ten million. You can change the default by
+ setting, for example,
+
+ --with-match-limit=500000
+
+ on the "configure" command. This is just the default; individual calls to
+ pcre2_match() or pcre2_dfa_match() can supply their own value. There is more
+ discussion in the pcre2api man page (search for pcre2_set_match_limit).
+
+. There is a separate counter that limits the depth of nested backtracking
+ (pcre2_match()) or nested function calls (pcre2_dfa_match()) during a
+ matching process, which indirectly limits the amount of heap memory that is
+ used, and in the case of pcre2_dfa_match() the amount of stack as well. This
+ counter also has a default of ten million, which is essentially "unlimited".
+ You can change the default by setting, for example,
+
+ --with-match-limit-depth=5000
+
+ There is more discussion in the pcre2api man page (search for
+ pcre2_set_depth_limit).
+
+. You can also set an explicit limit on the amount of heap memory used by
+ the pcre2_match() and pcre2_dfa_match() interpreters:
+
+ --with-heap-limit=500
+
+ The units are kibibytes (units of 1024 bytes). This limit does not apply when
+ the JIT optimization (which has its own memory control features) is used.
+ There is more discussion on the pcre2api man page (search for
+ pcre2_set_heap_limit).
+
+. In the 8-bit library, the default maximum compiled pattern size is around
+ 64 kibibytes. You can increase this by adding --with-link-size=3 to the
+ "configure" command. PCRE2 then uses three bytes instead of two for offsets
+ to different parts of the compiled pattern. In the 16-bit library,
+ --with-link-size=3 is the same as --with-link-size=4, which (in both
+ libraries) uses four-byte offsets. Increasing the internal link size reduces
+ performance in the 8-bit and 16-bit libraries. In the 32-bit library, the
+ link size setting is ignored, as 4-byte offsets are always used.
+
+. Lookbehind assertions in which one or more branches can match a variable
+ number of characters are supported only if there is a maximum matching length
+ for each top-level branch. There is a limit to this maximum that defaults to
+ 255 characters. You can alter this default by a setting such as
+
+ --with-max-varlookbehind=100
+
+ The limit can be changed at runtime by calling pcre2_set_max_varlookbehind().
+ Lookbehind assertions in which every branch matches a fixed number of
+ characters (not necessarily all the same) are not constrained by this limit.
+
+. For speed, PCRE2 uses four tables for manipulating and identifying characters
+ whose code point values are less than 256. By default, it uses a set of
+ tables for ASCII encoding that is part of the distribution. If you specify
+
+ --enable-rebuild-chartables
+
+ a program called pcre2_dftables is compiled and run in the default C locale
+ when you obey "make". It builds a source file called pcre2_chartables.c. If
+ you do not specify this option, pcre2_chartables.c is created as a copy of
+ pcre2_chartables.c.dist. See "Character tables" below for further
+ information.
+
+. It is possible to compile PCRE2 for use on systems that use EBCDIC as their
+ character code (as opposed to ASCII/Unicode) by specifying
+
+ --enable-ebcdic --disable-unicode
+
+ This automatically implies --enable-rebuild-chartables (see above), in order
+ to ensure that you have the correct default character tables for your system's
+ codepage. There is an exception when you set --enable-ebcdic-ignoring-compiler
+ (see below), which allows using a default set of EBCDIC 1047 character tables
+ rather than forcing use of --enable-rebuild-chartables.
+
+ When PCRE2 is built with EBCDIC support, it always operates in EBCDIC. It
+ cannot support both EBCDIC and ASCII or UTF-8/16/32.
+
+ There is a second option, --enable-ebcdic-nl25, which specifies that the code
+ value for the EBCDIC NL character is 0x25 instead of the default 0x15.
+
+ There is a third option, --enable-ebcdic-ignoring-compiler, which disregards
+ the compiler's codepage for determining the numeric value of C character
+ constants such as 'z', and instead forces PCRE2 to use numeric constants for
+ the EBCDIC 1047 codepage instead.
+
+. If you specify --enable-debug, additional debugging code is included in the
+ build. This option is intended for use by the PCRE2 maintainers.
+
+. In environments where valgrind is installed, if you specify
+
+ --enable-valgrind
+
+ PCRE2 will use valgrind annotations to mark certain memory regions as
+ unaddressable. This allows it to detect invalid memory accesses, and is
+ mostly useful for debugging PCRE2 itself.
+
+. In environments where the gcc compiler is used and lcov is installed, if you
+ specify
+
+ --enable-coverage
+
+ the build process implements a code coverage report for the test suite. The
+ report is generated by running "make coverage". If ccache is installed on
+ your system, it must be disabled when building PCRE2 for coverage reporting.
+ You can do this by setting the environment variable CCACHE_DISABLE=1 before
+ running "make" to build PCRE2. There is more information about coverage
+ reporting in the "pcre2build" documentation.
+
+. When JIT support is enabled, pcre2grep automatically makes use of it, unless
+ you add --disable-pcre2grep-jit to the "configure" command.
+
+. There is support for calling external programs during matching in the
+ pcre2grep command, using PCRE2's callout facility with string arguments. This
+ support can be disabled by adding --disable-pcre2grep-callout to the
+ "configure" command. There are two kinds of callout: one that generates
+ output from inbuilt code, and another that calls an external program. The
+ latter has special support for Windows and VMS; otherwise it assumes the
+ existence of the fork() function. This facility can be disabled by adding
+ --disable-pcre2grep-callout-fork to the "configure" command.
+
+. The pcre2grep program currently supports only 8-bit data files, and so
+ requires the 8-bit PCRE2 library. It is possible to compile pcre2grep to use
+ libz and/or libbz2, in order to read .gz and .bz2 files (respectively), by
+ specifying one or both of
+
+ --enable-pcre2grep-libz
+ --enable-pcre2grep-libbz2
+
+ Of course, the relevant libraries must be installed on your system.
+
+. The default starting size (in bytes) of the internal buffer used by pcre2grep
+ can be set by, for example:
+
+ --with-pcre2grep-bufsize=51200
+
+ The value must be a plain integer. The default is 20480. The amount of memory
+ used by pcre2grep is actually three times this number, to allow for "before"
+ and "after" lines. If very long lines are encountered, the buffer is
+ automatically enlarged, up to a fixed maximum size.
+
+. The default maximum size of pcre2grep's internal buffer can be set by, for
+ example:
+
+ --with-pcre2grep-max-bufsize=2097152
+
+ The default is either 1048576 or the value of --with-pcre2grep-bufsize,
+ whichever is the larger.
+
+. It is possible to compile pcre2test so that it links with the libreadline
+ or libedit libraries, by specifying, respectively,
+
+ --enable-pcre2test-libreadline or --enable-pcre2test-libedit
+
+ If this is done, when pcre2test's input is from a terminal, it reads it using
+ the readline() function. This provides line-editing and history facilities.
+ Note that libreadline is GPL-licensed, so if you distribute a binary of
+ pcre2test linked in this way, there may be licensing issues. These can be
+ avoided by linking with libedit (which has a BSD licence) instead.
+
+ Enabling libreadline causes the -lreadline option to be added to the
+ pcre2test build. In many operating environments with a system-installed
+ readline library this is sufficient. However, in some environments (e.g. if
+ an unmodified distribution version of readline is in use), it may be
+ necessary to specify something like LIBS="-lncurses" as well. This is
+ because, to quote the readline INSTALL, "Readline uses the termcap functions,
+ but does not link with the termcap or curses library itself, allowing
+ applications which link with readline the option to choose an appropriate
+ library." If you get error messages about missing functions tgetstr, tgetent,
+ tputs, tgetflag, or tgoto, this is the problem, and linking with the ncurses
+ library should fix it.
+
+. The C99 standard defines formatting modifiers z and t for size_t and
+ ptrdiff_t values, respectively. By default, PCRE2 uses these modifiers in
+ environments other than Microsoft Visual Studio versions earlier than 2013
+ when __STDC_VERSION__ is defined and has a value greater than or equal to
+ 199901L (indicating C99). However, there is at least one environment that
+ claims to be C99 but does not support these modifiers. If
+ --disable-percent-zt is specified, no use is made of the z or t modifiers.
+ Instead of %td or %zu, %lu is used, with a cast for size_t values.
+
+. There is a special option called --enable-fuzz-support for use by people who
+ want to run fuzzing tests on PCRE2. If set, it causes an extra library
+ called libpcre2-fuzzsupport.a to be built, but not installed. This contains
+ a single function called LLVMFuzzerTestOneInput() whose arguments are a
+ pointer to a string and the length of the string. When called, this function
+ tries to compile the string as a pattern, and if that succeeds, to match
+ it. This is done both with no options and with some random options bits that
+ are generated from the string. Setting --enable-fuzz-support also causes an
+ executable called pcre2fuzzcheck-{8,16,32} to be created. This is normally
+ run under valgrind or used when PCRE2 is compiled with address sanitizing
+ enabled. It calls the fuzzing function and outputs information about what it
+ is doing. The input strings are specified by arguments: if an argument
+ starts with "=" the rest of it is a literal input string. Otherwise, it is
+ assumed to be a file name, and the contents of the file are the test string.
+
+. Releases before 10.30 could be compiled with --disable-stack-for-recursion,
+ which caused pcre2_match() to use individual blocks on the heap for
+ backtracking instead of recursive function calls (which use the stack). This
+ is now obsolete because pcre2_match() was refactored always to use the heap
+ (in a much more efficient way than before). This option is retained for
+ backwards compatibility, but has no effect other than to output a warning.
+
+The "configure" script builds the following files for the basic C library:
+
+. Makefile the makefile that builds the library
+. src/config.h build-time configuration options for the library
+. src/pcre2.h the public PCRE2 header file
+. pcre2-config script that shows the building settings such as CFLAGS
+ that were set for "configure"
+. libpcre2-8.pc )
+. libpcre2-16.pc ) data for the pkg-config command
+. libpcre2-32.pc )
+. libpcre2-posix.pc )
+. libtool script that builds shared and/or static libraries
+
+Versions of config.h and pcre2.h are distributed in the src directory of PCRE2
+tarballs under the names config.h.generic and pcre2.h.generic. These are
+provided for those who have to build PCRE2 without using "configure" or CMake.
+If you use "configure" or CMake, the .generic versions are not used.
+
+The "configure" script also creates config.status, which is an executable
+script that can be run to recreate the configuration, and config.log, which
+contains compiler output from tests that "configure" runs.
+
+Once "configure" has run, you can run "make". This builds whichever of the
+libraries libpcre2-8, libpcre2-16 and libpcre2-32 are configured, and a test
+program called pcre2test. If you enabled JIT support with --enable-jit, another
+test program called pcre2_jit_test is built as well. If the 8-bit library is
+built, libpcre2-posix, pcre2posix_test, and the pcre2grep command are also
+built. Running "make" with the -j option may speed up compilation on
+multiprocessor systems.
+
+The command "make check" runs all the appropriate tests. Details of the PCRE2
+tests are given below in a separate section of this document. The -j option of
+"make" can also be used when running the tests.
+
+You can use "make install" to install PCRE2 into live directories on your
+system. The following are installed (file names are all relative to the
+ that is set when "configure" is run):
+
+ Commands (bin):
+ pcre2test
+ pcre2grep (if 8-bit support is enabled)
+ pcre2-config
+
+ Libraries (lib):
+ libpcre2-8 (if 8-bit support is enabled)
+ libpcre2-16 (if 16-bit support is enabled)
+ libpcre2-32 (if 32-bit support is enabled)
+ libpcre2-posix (if 8-bit support is enabled)
+
+ Configuration information (lib/pkgconfig):
+ libpcre2-8.pc
+ libpcre2-16.pc
+ libpcre2-32.pc
+ libpcre2-posix.pc
+
+ Header files (include):
+ pcre2.h
+ pcre2posix.h
+
+ Man pages (share/man/man{1,3}):
+ pcre2grep.1
+ pcre2test.1
+ pcre2-config.1
+ pcre2.3
+ pcre2*.3 (lots more pages, all starting "pcre2")
+
+ HTML documentation (share/doc/pcre2/html):
+ index.html
+ *.html (lots more pages, hyperlinked from index.html)
+
+ Text file documentation (share/doc/pcre2):
+ AUTHORS.md
+ COPYING
+ ChangeLog
+ LICENCE.md
+ NEWS
+ README
+ SECURITY.md
+ SUPPORT-LIFECYCLE.md
+ pcre2.txt (a concatenation of the man(3) pages)
+ pcre2test.txt the pcre2test man page
+ pcre2grep.txt the pcre2grep man page
+ pcre2-config.txt the pcre2-config man page
+
+If you want to remove PCRE2 from your system, you can run "make uninstall".
+This removes all the files that "make install" installed. However, it does not
+remove any directories, because these are often shared with other programs.
+
+
+Retrieving configuration information
+------------------------------------
+
+Running "make install" installs the command pcre2-config, which can be used to
+recall information about the PCRE2 configuration and installation. For example:
+
+ pcre2-config --version
+
+prints the version number, and
+
+ pcre2-config --libs8
+
+outputs information about where the 8-bit library is installed. This command
+can be included in makefiles for programs that use PCRE2, saving the programmer
+from having to remember too many details. Run pcre2-config with no arguments to
+obtain a list of possible arguments.
+
+The pkg-config command is another system for saving and retrieving information
+about installed libraries. Instead of separate commands for each library, a
+single command is used. For example:
+
+ pkg-config --libs libpcre2-16
+
+The data is held in *.pc files that are installed in a directory called
+/lib/pkgconfig.
+
+
+Shared libraries
+----------------
+
+The default distribution builds PCRE2 as shared libraries and static libraries,
+as long as the operating system supports shared libraries. Shared library
+support relies on the "libtool" script which is built as part of the
+"configure" process.
+
+The libtool script is used to compile and link both shared and static
+libraries. They are placed in a subdirectory called .libs when they are newly
+built. The programs pcre2test and pcre2grep are built to use these uninstalled
+libraries (by means of wrapper scripts in the case of shared libraries). When
+you use "make install" to install shared libraries, pcre2grep and pcre2test are
+automatically re-built to use the newly installed shared libraries before being
+installed themselves. However, the versions left in the build directory still
+use the uninstalled libraries.
+
+To build PCRE2 using static libraries only you must use --disable-shared when
+configuring it. For example:
+
+./configure --prefix=/usr/gnu --disable-shared
+
+Then run "make" in the usual way. Similarly, you can use --disable-static to
+build only shared libraries. Note, however, that when you build only static
+libraries, binary programs such as pcre2test and pcre2grep may still be
+dynamically linked with other libraries (for example, libc) unless you set
+LDFLAGS to --static when running "configure".
+
+
+Cross-compiling using autotools
+-------------------------------
+
+You can specify CC and CFLAGS in the normal way to the "configure" command, in
+order to cross-compile PCRE2 for some other host. However, you should NOT
+specify --enable-rebuild-chartables, because if you do, the pcre2_dftables.c
+source file is compiled and run on the local host, in order to generate the
+inbuilt character tables (the pcre2_chartables.c file). This will probably not
+work, because pcre2_dftables.c needs to be compiled with the local compiler,
+not the cross compiler.
+
+When --enable-rebuild-chartables is not specified, pcre2_chartables.c is
+created by making a copy of pcre2_chartables.c.dist, which is a default set of
+tables that assumes ASCII code. Cross-compiling with the default tables should
+not be a problem.
+
+If you need to modify the character tables when cross-compiling, you should
+move pcre2_chartables.c.dist out of the way, then compile pcre2_dftables.c by
+hand and run it on the local host to make a new version of
+pcre2_chartables.c.dist. See the pcre2build section "Creating character tables
+at build time" for more details.
+
+
+Making new tarballs
+-------------------
+
+The command "make dist" creates three PCRE2 tarballs, in tar.gz, tar.bz2, and
+zip formats. The command "make distcheck" does the same, but then does a trial
+build of the new distribution to ensure that it works.
+
+If you have modified any of the man page sources in the doc directory, you
+should first run the maint/UpdateAlways script before making a distribution.
+This script creates the .txt and HTML forms of the documentation from the man
+pages.
+
+
+Testing PCRE2
+-------------
+
+To test the basic PCRE2 library on a Unix-like system, run the RunTest script.
+There is another script called RunGrepTest that tests the pcre2grep command.
+When the 8-bit library is built, a test program for the POSIX wrapper, called
+pcre2posix_test, is compiled, and when JIT support is enabled, a test program
+called pcre2_jit_test is built. The scripts and the program tests are all run
+when you obey "make check". For other environments, see the instructions in
+NON-AUTOTOOLS-BUILD.
+
+The RunTest script runs the pcre2test test program (which is documented in its
+own man page) on each of the relevant testinput files in the testdata
+directory, and compares the output with the contents of the corresponding
+testoutput files. RunTest places its output in directories
+testoutput{8,16,32}{,-jit,-dfa}. Other files whose names begin with "test" are
+used as working files in some tests.
+
+Some tests are relevant only when certain build-time options were selected. For
+example, the tests for UTF-8/16/32 features are run only when Unicode support
+is available. RunTest outputs a comment when it skips a test.
+
+Many (but not all) of the tests that are not skipped are run twice if JIT
+support is available. On the second run, JIT compilation is forced. This
+testing can be suppressed by putting "-nojit" on the RunTest command line.
+
+The entire set of tests is run once for each of the 8-bit, 16-bit and 32-bit
+libraries that are enabled. If you want to run just one set of tests, call
+RunTest with either the -8, -16 or -32 option.
+
+If valgrind is installed, you can run the tests under it by putting "-valgrind"
+on the RunTest command line. To run pcre2test on just one or more specific test
+files, give their numbers as arguments to RunTest, for example:
+
+ RunTest 2 7 11
+
+You can also specify ranges of tests such as 3-6 or 3- (meaning 3 to the
+end), or a number preceded by ~ to exclude a test. For example:
+
+ Runtest 3-15 ~10
+
+This runs tests 3 to 15, excluding test 10, and just ~13 runs all the tests
+except test 13. Whatever order the arguments are in, the tests are always run
+in numerical order.
+
+You can also call RunTest with the single argument "list" to cause it to output
+a list of tests.
+
+The test sequence starts with "test 0", which is a special test that has no
+input file, and whose output is not checked. This is because it will be
+different on different hardware and with different configurations. The test
+exists in order to exercise some of pcre2test's code that would not otherwise
+be run.
+
+Tests 1 and 2 can always be run, as they expect only plain text strings (not
+UTF) and make no use of Unicode properties. The first test file can be fed
+directly into the perltest.sh script to check that Perl gives the same results.
+The only difference you should see is in the first few lines, where the Perl
+version is given instead of the PCRE2 version. The second set of tests check
+auxiliary functions, error detection, and run-time flags that are specific to
+PCRE2. It also uses the debugging flags to check some of the internals of
+pcre2_compile().
+
+If you build PCRE2 with a locale setting that is not the standard C locale, the
+character tables may be different (see next paragraph). In some cases, this may
+cause failures in the second set of tests. For example, in a locale where the
+isprint() function yields TRUE for characters in the range 128-255, the use of
+[:isascii:] inside a character class defines a different set of characters, and
+this shows up in this test as a difference in the compiled code, which is being
+listed for checking. For example, where the comparison test output contains
+[\x00-\x7f] the test might contain [\x00-\xff], and similarly in some other
+cases. This is not a bug in PCRE2.
+
+Test 3 checks pcre2_maketables(), the facility for building a set of character
+tables for a specific locale and using them instead of the default tables. The
+script uses the "locale" command to check for the availability of the "fr_FR",
+"french", or "fr" locale, and uses the first one that it finds. If the "locale"
+command fails, or if its output doesn't include "fr_FR", "french", or "fr" in
+the list of available locales, the third test cannot be run, and a comment is
+output to say why. If running this test produces an error like this:
+
+ ** Failed to set locale "fr_FR"
+
+it means that the given locale is not available on your system, despite being
+listed by "locale". This does not mean that PCRE2 is broken. There are three
+alternative output files for the third test, because three different versions
+of the French locale have been encountered. The test passes if its output
+matches any one of them.
+
+Tests 4 and 5 check UTF and Unicode property support, test 4 being compatible
+with the perltest.sh script, and test 5 checking PCRE2-specific things.
+
+Tests 6 and 7 check the pcre2_dfa_match() alternative matching function, in
+non-UTF mode and UTF-mode with Unicode property support, respectively.
+
+Test 8 checks some internal offsets and code size features, but it is run only
+when Unicode support is enabled. The output is different in 8-bit, 16-bit, and
+32-bit modes and for different link sizes, so there are different output files
+for each mode and link size.
+
+Tests 9 and 10 are run only in 8-bit mode, and tests 11 and 12 are run only in
+16-bit and 32-bit modes. These are tests that generate different output in
+8-bit mode. Each pair are for general cases and Unicode support, respectively.
+
+Test 13 checks the handling of non-UTF characters greater than 255 by
+pcre2_dfa_match() in 16-bit and 32-bit modes.
+
+Test 14 contains some special UTF and UCP tests that give different output for
+different code unit widths.
+
+Test 15 contains a number of tests that must not be run with JIT. They check,
+among other non-JIT things, the match-limiting features of the interpretive
+matcher.
+
+Test 16 is run only when JIT support is not available. It checks that an
+attempt to use JIT has the expected behaviour.
+
+Test 17 is run only when JIT support is available. It checks JIT complete and
+partial modes, match-limiting under JIT, and other JIT-specific features.
+
+Tests 18 and 19 are run only in 8-bit mode. They check the POSIX interface to
+the 8-bit library, without and with Unicode support, respectively.
+
+Test 20 checks the serialization functions by writing a set of compiled
+patterns to a file, and then reloading and checking them.
+
+Tests 21 and 22 test \C support when the use of \C is not locked out, without
+and with UTF support, respectively. Test 23 tests \C when it is locked out.
+
+Tests 24 and 25 test the experimental pattern conversion functions, without and
+with UTF support, respectively.
+
+Test 26 checks Unicode property support using tests that were generated
+automatically from the Unicode data tables. These are the archived version of
+the tests from Unicode 15.
+
+Test 27 checks Unicode property support using tests that are generated
+automatically from the currently-used Unicode data tables.
+
+Test 28 tests EBCDIC support, and is only run when PCRE2 is specifically
+compiled for EBCDIC. Test 29 tests EBCDIC when NL has been configured to be
+0x25.
+
+
+Character tables
+----------------
+
+For speed, PCRE2 uses four tables for manipulating and identifying characters
+whose code point values are less than 256. By default, a set of tables that is
+built into the library is used. The pcre2_maketables() function can be called
+by an application to create a new set of tables in the current locale. This are
+passed to PCRE2 by calling pcre2_set_character_tables() to put a pointer into a
+compile context.
+
+The source file called pcre2_chartables.c contains the default set of tables.
+By default, this is created as a copy of pcre2_chartables.c.dist, which
+contains tables for ASCII coding. However, if --enable-rebuild-chartables is
+specified for ./configure, a new version of pcre2_chartables.c is built by the
+program pcre2_dftables (compiled from pcre2_dftables.c), which uses the ANSI C
+character handling functions such as isalnum(), isalpha(), isupper(),
+islower(), etc. to build the table sources. This means that the default C
+locale that is set for your system will control the contents of these default
+tables. You can change the default tables by editing pcre2_chartables.c and
+then re-building PCRE2. If you do this, you should take care to ensure that the
+file does not get automatically re-generated. The best way to do this is to
+move pcre2_chartables.c.dist out of the way and replace it with your customized
+tables.
+
+When the pcre2_dftables program is run as a result of specifying
+--enable-rebuild-chartables, it uses the default C locale that is set on your
+system. It does not pay attention to the LC_xxx environment variables. In other
+words, it uses the system's default locale rather than whatever the compiling
+user happens to have set. If you really do want to build a source set of
+character tables in a locale that is specified by the LC_xxx variables, you can
+run the pcre2_dftables program by hand with the -L option. For example:
+
+ ./pcre2_dftables -L pcre2_chartables.c.special
+
+The second argument names the file where the source code for the tables is
+written. The first two 256-byte tables provide lower casing and case flipping
+functions, respectively. The next table consists of a number of 32-byte bit
+maps which identify certain character classes such as digits, "word"
+characters, white space, etc. These are used when building 32-byte bit maps
+that represent character classes for code points less than 256. The final
+256-byte table has bits indicating various character types, as follows:
+
+ 1 white space character
+ 2 letter
+ 4 lower case letter
+ 8 decimal digit
+ 16 alphanumeric or '_'
+
+You can also specify -b (with or without -L) when running pcre2_dftables. This
+causes the tables to be written in binary instead of as source code. A set of
+binary tables can be loaded into memory by an application and passed to
+pcre2_compile() in the same way as tables created dynamically by calling
+pcre2_maketables(). The tables are just a string of bytes, independent of
+hardware characteristics such as endianness. This means they can be bundled
+with an application that runs in different environments, to ensure consistent
+behaviour.
+
+See also the pcre2build section "Creating character tables at build time".
+
+
+File manifest
+-------------
+
+The distribution should contain the files listed below.
+
+(A) Source files for the PCRE2 library functions and their headers are found in
+ the src directory:
+
+ src/pcre2_dftables.c auxiliary program for building pcre2_chartables.c
+ when --enable-rebuild-chartables is specified
+
+ src/pcre2_chartables.c.dist a default set of character tables that assume
+ ASCII coding; unless --enable-rebuild-chartables is
+ specified, used by copying to pcre2_chartables.c
+ src/pcre2_chartables.c.ebcdic-1047-{nl15,nl25} a default set of character
+ tables for EBCDIC 1047; used if
+ --enable-ebcdic-ignoring-compiler is specified
+ without --enable-rebuild-chartables
+
+ src/pcre2posix.c )
+ src/pcre2_auto_possess.c )
+ src/pcre2_chkdint.c )
+ src/pcre2_compile.c )
+ src/pcre2_compile_cgroup.c )
+ src/pcre2_compile_class.c )
+ src/pcre2_config.c )
+ src/pcre2_context.c )
+ src/pcre2_convert.c )
+ src/pcre2_dfa_match.c )
+ src/pcre2_error.c )
+ src/pcre2_extuni.c )
+ src/pcre2_find_bracket.c )
+ src/pcre2_jit_compile.c )
+ src/pcre2_maketables.c ) sources for the functions in the library,
+ src/pcre2_match.c ) and some internal functions that they use
+ src/pcre2_match_data.c )
+ src/pcre2_match_next.c )
+ src/pcre2_newline.c )
+ src/pcre2_ord2utf.c )
+ src/pcre2_pattern_info.c )
+ src/pcre2_script_run.c )
+ src/pcre2_serialize.c )
+ src/pcre2_string_utils.c )
+ src/pcre2_study.c )
+ src/pcre2_substitute.c )
+ src/pcre2_substring.c )
+ src/pcre2_tables.c )
+ src/pcre2_ucd.c )
+ src/pcre2_valid_utf.c )
+ src/pcre2_xclass.c )
+
+ src/pcre2_fuzzsupport.c function for (optional) fuzzing support
+
+ src/config.h.in template for config.h, when built by "configure"
+ src/pcre2.h.in template for pcre2.h when built by "configure"
+ src/pcre2posix.h header for the external POSIX wrapper API
+ src/pcre2_compile.h header for internal use
+ src/pcre2_internal.h header for internal use
+ src/pcre2_intmodedep.h a mode-specific internal header
+ src/pcre2_jit_char_inc.h header used by JIT
+ src/pcre2_jit_match_inc.h header used by JIT
+ src/pcre2_jit_misc_inc.h header used by JIT
+ src/pcre2_jit_simd_inc.h header used by JIT
+ src/pcre2_printint_inc.h debugging function that is used by pcre2test
+ src/pcre2_ucp.h header for Unicode property handling
+ src/pcre2_ucptables_inc.h header with Unicode data tables
+ src/pcre2_util.h header for internal utils
+
+ deps/sljit/sljit_src/* source files for the JIT compiler
+
+(B) Source files for programs that use PCRE2:
+
+ src/pcre2demo.c simple demonstration of coding calls to PCRE2
+ src/pcre2grep.c source of a grep utility that uses PCRE2
+ src/pcre2test.c comprehensive test program
+ src/pcre2test_inc.h header used by pcre2test
+ src/pcre2_jit_test.c JIT test program
+ src/pcre2posix_test.c POSIX wrapper API test program
+
+(C) Auxiliary files:
+
+ AUTHORS.md information about the authors of PCRE2
+ ChangeLog log of changes to the code
+ HACKING some notes about the internals of PCRE2
+ INSTALL generic installation instructions
+ LICENCE.md conditions for the use of PCRE2
+ COPYING the same, using GNU's standard name
+ SECURITY.md information on reporting vulnerabilities
+ SUPPORT-LIFECYCLE.md information on the support policy
+ Makefile.in ) template for Unix Makefile, which is built by
+ ) "configure"
+ Makefile.am ) the automake input that was used to create
+ ) Makefile.in
+ NEWS important changes in this release
+ NON-AUTOTOOLS-BUILD notes on building PCRE2 without using autotools
+ README this file
+ RunTest a Unix shell script for running tests
+ RunGrepTest a Unix shell script for pcre2grep tests
+ RunTest.bat a Windows batch file for running tests
+ RunGrepTest.bat a Windows batch file for pcre2grep tests
+ aclocal.m4 m4 macros (generated by "aclocal")
+ m4/* m4 macros (used by autoconf)
+ configure a configuring shell script (built by autoconf)
+ configure.ac ) the autoconf input that was used to build
+ ) "configure" and config.h
+ doc/*.3 man page sources for PCRE2
+ doc/*.1 man page sources for pcre2grep and pcre2test
+ doc/html/* HTML documentation
+ doc/pcre2.txt plain text version of the man pages
+ doc/pcre2-config.txt plain text documentation of pcre2-config script
+ doc/pcre2grep.txt plain text documentation of grep utility program
+ doc/pcre2test.txt plain text documentation of test program
+ libpcre2-8.pc.in template for libpcre2-8.pc for pkg-config
+ libpcre2-16.pc.in template for libpcre2-16.pc for pkg-config
+ libpcre2-32.pc.in template for libpcre2-32.pc for pkg-config
+ libpcre2-posix.pc.in template for libpcre2-posix.pc for pkg-config
+ ar-lib )
+ config.guess )
+ config.sub )
+ depcomp ) helper tools generated by libtool and
+ compile ) automake, used internally by ./configure
+ install-sh )
+ ltmain.sh )
+ missing )
+ test-driver )
+ perltest.sh Script for running a Perl test program
+ pcre2-config.in source of script which retains PCRE2 information
+ testdata/testinput* test data for main library tests
+ testdata/testoutput* expected test results
+ testdata/grep* input and output for pcre2grep tests
+ testdata/* other supporting test files
+ src/libpcre2-8.sym.in )
+ src/libpcre2-16.sym.in ) symbol version script templates for the
+ src/libpcre2-32.sym.in ) GNU, BSD and Sun linkers
+ src/libpcre2-posix.sym.in )
+
+(D) Auxiliary files for CMake support
+
+ cmake/COPYING-CMAKE-SCRIPTS
+ cmake/FindEditline.cmake
+ cmake/FindReadline.cmake
+ cmake/pcre2-config.cmake.in
+ cmake/PCRE2CheckVscript.cmake
+ cmake/PCRE2UseSystemExtensions.cmake
+ cmake/PCRE2WarningAsError.cmake
+ src/config-cmake.h.in
+ CMakeLists.txt
+
+(E) Auxiliary files for building PCRE2 "by hand"
+
+ src/pcre2.h.generic ) a version of the public PCRE2 header file
+ ) for use in non-"configure" environments
+ src/config.h.generic ) a version of config.h for use in non-"configure"
+ ) environments
+
+(F) Auxiliary files for building PCRE2 using other build systems
+
+ BUILD.bazel ) files used by the Bazel
+ MODULE.bazel ) build system
+ build.zig file used by zig's build system
+ build.zig.zon file used by zig's package manager
+
+(G) Auxiliary files for building PCRE2 under OpenVMS
+
+ vms/configure.com )
+ vms/openvms_readme.txt ) These files were contributed by a PCRE2 user.
+ vms/pcre2.h_patch )
+ vms/stdint.h )
+
+============================
+Last updated: 08 August 2026
+============================
+
diff --git a/RunGrepTest b/RunGrepTest
new file mode 100755
index 0000000..eaed73f
--- /dev/null
+++ b/RunGrepTest
@@ -0,0 +1,1366 @@
+#! /bin/sh
+
+# Run pcre2grep tests. The assumption is that the PCRE2 tests check the library
+# itself. What we are checking here is the file handling and options that are
+# supported by pcre2grep. This script must be run in the build directory.
+
+# CODING CONVENTIONS:
+# * Put printf arguments in single, not double quotes to avoid unwanted
+# escaping.
+# * Use \0 for binary zero in printf, not \x0, for the benefit of older
+# versions (and use octal for other special values).
+
+# Set the C locale, so that sort(1) behaves predictably.
+
+LC_ALL=C
+export LC_ALL
+
+# Remove any non-default colouring and aliases that the caller may have set.
+
+unset PCRE2GREP_COLOUR PCRE2GREP_COLOR PCREGREP_COLOUR PCREGREP_COLOR
+unset GREP_COLOR GREP_COLORS
+unset cp ls mv rm
+
+# Remember the current (build) directory, set the program to be tested, and
+# valgrind settings when requested.
+
+builddir=`pwd`
+: ${pcre2grep:=$builddir/pcre2grep}
+: ${pcre2test:=$builddir/pcre2test}
+
+if [ ! -x $pcre2grep ] ; then
+ echo "** $pcre2grep does not exist or is not executable."
+ exit 1
+fi
+
+if [ ! -x $pcre2test ] ; then
+ echo "** $pcre2test does not exist or is not executable."
+ exit 1
+fi
+
+valgrind=
+while [ $# -gt 0 ] ; do
+ case $1 in
+ valgrind|-valgrind) valgrind="valgrind -q --leak-check=no --smc-check=all-non-file --error-exitcode=70";;
+ *) echo "RunGrepTest: Unknown argument $1"; exit 1;;
+ esac
+ shift
+done
+
+pcre2grep_version=`$pcre2grep -V`
+if [ "$valgrind" = "" ] ; then
+ echo "Testing $pcre2grep_version"
+else
+ echo "Testing $pcre2grep_version using valgrind"
+fi
+
+# Set up a suitable "diff" command for comparison. Some systems have a diff
+# that lacks a -u option. Try to deal with this; better do the test for the -b
+# option as well.
+
+cf="diff"
+diff -b /dev/null /dev/null 2>/dev/null && cf="diff -b"
+diff -u /dev/null /dev/null 2>/dev/null && cf="diff -u"
+diff -ub /dev/null /dev/null 2>/dev/null && cf="diff -ub"
+
+# Add a -a (always treat as text) if available. This was added in an attempt
+# to get more detail from an Alpine Linux test failure on GitHub.
+
+$cf -a /dev/null /dev/null 2>/dev/null && cf="$cf -a"
+
+# Some tests involve NUL characters. It seems impossible to handle them easily
+# in many operating systems. An earlier version of this script used sed to
+# translate NUL into the string ZERO, but this didn't work on Solaris (aka
+# SunOS), where the version of sed explicitly doesn't like them, and also MacOS
+# (Darwin), OpenBSD, FreeBSD, NetBSD, and some Linux distributions like Alpine,
+# even when using GNU sed. A user suggested using tr instead, which
+# necessitates translating to a single character. However, on (some versions
+# of?) Solaris, the normal "tr" cannot handle binary zeros, but if
+# /usr/xpg4/bin/tr is available, it can do so, so test for that.
+
+if [ -x /usr/xpg4/bin/tr ] ; then
+ tr=/usr/xpg4/bin/tr
+else
+ tr=tr
+fi
+
+# If this test is being run from "make check", $srcdir will be set. If not, set
+# it to the current or parent directory, whichever one contains the test data.
+# Subsequently, we run most of the pcre2grep tests in the source directory so
+# that the file names in the output are always the same.
+
+if [ -z "$srcdir" -o ! -d "$srcdir/testdata" ] ; then
+ if [ -d "./testdata" ] ; then
+ srcdir=.
+ elif [ -d "../testdata" ] ; then
+ srcdir=..
+ else
+ echo "Cannot find the testdata directory"
+ exit 1
+ fi
+fi
+
+# Set up the path to the valgrind JIT suppressions
+
+vjs=
+if [ "$valgrind" != "" ] ; then
+ $pcre2test -C jit >/dev/null
+ if [ $? -ne 0 ]; then
+ vjs="--suppressions=`realpath "$srcdir"`/testdata/valgrind-jit.supp"
+ fi
+fi
+
+# Check for the availability of UTF-8 support
+
+$pcre2test -C unicode >/dev/null
+utf8=$?
+
+# Check default newline convention. If it does not include LF, force LF.
+
+nl=`$pcre2test -C newline`
+if [ "$nl" != "LF" -a "$nl" != "ANY" -a "$nl" != "ANYCRLF" ]; then
+ pcre2grep="$pcre2grep -N LF"
+ echo "Default newline setting forced to LF"
+fi
+
+# ------ Function to run and check a special pcre2grep arguments test -------
+
+checkspecial()
+ {
+ $valgrind $pcre2grep $1 >>testtrygrep 2>&1
+ if [ $? -ne $2 ] ; then
+ echo "** pcre2grep $1 failed - check testtrygrep"
+ exit 1
+ fi
+ }
+
+# ------ Normal tests ------
+
+echo "Testing pcre2grep main features"
+
+echo "---------------------------- Test 1 ------------------------------" >testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep PATTERN ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 2 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep '^PATTERN' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 3 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -in PATTERN ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 4 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -ic PATTERN ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 5 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -in PATTERN ./testdata/grepinput ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 6 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -inh PATTERN ./testdata/grepinput ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 7 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -il PATTERN ./testdata/grepinput ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 8 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -l PATTERN ./testdata/grepinput ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 9 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -q PATTERN ./testdata/grepinput ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 10 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -q NEVER-PATTERN ./testdata/grepinput ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 11 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -vn pattern ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 12 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -ix pattern ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 13 -----------------------------" >>testtrygrep
+echo seventeen >testtemp1grep
+(cd $srcdir; $valgrind $vjs $pcre2grep -f./testdata/greplist -f $builddir/testtemp1grep ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 14 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -w pat ./testdata/grepinput ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 15 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep 'abc^*' ./testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 16 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep abc ./testdata/grepinput ./testdata/nonexistfile) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 17 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -M 'the\noutput' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 18 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -Mn '(the\noutput|dog\.\n--)' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 19 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -Mix 'Pattern' ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 20 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -Mixn 'complete pair\nof lines' ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 21 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -nA3 'four' ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 22 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -nB3 'four' ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 23 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -C3 'four' ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 24 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -A9 'four' ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 25 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -nB9 'four' ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 26 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -A9 -B9 'four' ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 27 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -A10 'four' ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 28 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -nB10 'four' ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 29 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -C12 -B10 'four' ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 30 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -inB3 'pattern' ./testdata/grepinput ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 31 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -inA3 'pattern' ./testdata/grepinput ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 32 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -L 'fox' ./testdata/grepinput ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 33 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep 'fox' ./testdata/grepnonexist) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 34 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -s 'fox' ./testdata/grepnonexist) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 35 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -L -r --include=grepinputx --include grepinput8 --exclude-dir='^\.' 'fox' ./testdata | sort) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 36 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -L -r --include='grepinput[^C]' --exclude 'grepinput$' --exclude='grepinput(Bad)?8' --exclude=grepinputM --exclude=grepinputUN --exclude-dir='^\.' 'fox' ./testdata | sort) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 37 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep '^(a+)*\d' ./testdata/grepinput) >>testtrygrep 2>teststderrgrep
+echo "RC=$?" >>testtrygrep
+echo "======== STDERR ========" >>testtrygrep
+cat teststderrgrep >>testtrygrep
+
+echo "---------------------------- Test 38 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep '>\x00<' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 39 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -A1 'before the binary zero' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 40 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -B1 'after the binary zero' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 41 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -B1 -o '\w+ the binary zero' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 42 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -B1 -onH '\w+ the binary zero' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 43 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -on 'before|zero|after' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 44 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -on -e before -ezero -e after ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 45 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -on -f ./testdata/greplist -e binary ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 46 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -e 'unopened)' -e abc ./testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -eabc -e '(unclosed' ./testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -eabc -e xyz -e '[unclosed' ./testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --regex=123 -eabc -e xyz -e '[unclosed' ./testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 47 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -Fx "AB.VE
+elephant" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 48 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -F "AB.VE
+elephant" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 49 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -F -e DATA -e "AB.VE
+elephant" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 50 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep "^(abc|def|ghi|jkl)" ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 51 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -Mv "brown\sfox" ./testdata/grepinputv) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 52 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --colour=always jumps ./testdata/grepinputv) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 53 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --file-offsets 'before|zero|after' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 54 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --line-offsets 'before|zero|after' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 55 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -f./testdata/greplist --color=always ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 56 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -c --exclude=grepinputC lazy ./testdata/grepinput*) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 57 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -c -l --exclude=grepinputC lazy ./testdata/grepinput*) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 58 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --regex=PATTERN ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 59 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --regexp=PATTERN ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 60 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --regex PATTERN ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 61 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --regexp PATTERN ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 62 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $pcre2grep --match-limit=1000 --no-jit -M 'This is a file(.|\R)*file.' ./testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 63 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $pcre2grep --recursion-limit=1K --no-jit -M 'This is a file(.|\R)*file.' ./testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 64 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o1 '(?<=PAT)TERN (ap(pear)s)' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 65 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o2 '(?<=PAT)TERN (ap(pear)s)' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 66 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o3 '(?<=PAT)TERN (ap(pear)s)' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 67 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o12 '(?<=PAT)TERN (ap(pear)s)' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 68 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --only-matching=2 '(?<=PAT)TERN (ap(pear)s)' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 69 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -vn --colour=always pattern ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 70 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --color=always -M "triple:\t.*\n\n" ./testdata/grepinput3) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --color=always -M -n "triple:\t.*\n\n" ./testdata/grepinput3) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -M "triple:\t.*\n\n" ./testdata/grepinput3) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -M -n "triple:\t.*\n\n" ./testdata/grepinput3) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 71 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o "^01|^02|^03" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 72 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --color=always "^01|^02|^03" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 73 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o --colour=always "^01|^02|^03" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 74 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o "^01|02|^03" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 75 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --color=always "^01|02|^03" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 76 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o --colour=always "^01|02|^03" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 77 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o "^01|^02|03" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 78 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --color=always "^01|^02|03" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 79 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o --colour=always "^01|^02|03" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 80 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o "\b01|\b02" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 81 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --color=always "\\b01|\\b02" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 82 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o --colour=always "\\b01|\\b02" ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 83 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --buffer-size=10 --max-buffer-size=100 "^a" ./testdata/grepinput3) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 84 -----------------------------" >>testtrygrep
+echo testdata/grepinput3 >testtemp1grep
+(cd $srcdir; $valgrind $vjs $pcre2grep --file-list ./testdata/grepfilelist --file-list $builddir/testtemp1grep "fox|complete|t7") >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 85 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --file-list=./testdata/grepfilelist "dolor" ./testdata/grepinput3) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 86 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep "dog" ./testdata/grepbinary) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 87 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep "cat" ./testdata/grepbinary) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 88 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -v "cat" ./testdata/grepbinary) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 89 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -I "dog" ./testdata/grepbinary) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 90 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --binary-files=without-match "dog" ./testdata/grepbinary) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 91 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -a "dog" ./testdata/grepbinary) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 92 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --binary-files=text "dog" ./testdata/grepbinary) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 93 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --text "dog" ./testdata/grepbinary) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 94 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -L -r --include=grepinputx --include grepinput8 'fox' ./testdata/grepinput* | sort) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 95 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --file-list ./testdata/grepfilelist --exclude grepinputv "fox|complete") >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 96 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -L -r --include-dir=testdata --exclude '^(?!grepinput)' --exclude=grepinput[MCU] 'fox' ./test* | sort) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 97 -----------------------------" >>testtrygrep
+echo "grepinput$" >testtemp1grep
+echo "grepinput8" >>testtemp1grep
+echo "grepinputBad8" >>testtemp1grep
+(cd $srcdir; $valgrind $vjs $pcre2grep -L -r --include=grepinput --exclude=grepinput[MCU] --exclude-from $builddir/testtemp1grep --exclude-dir='^\.' 'fox' ./testdata | sort) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 98 -----------------------------" >>testtrygrep
+echo "grepinput$" >testtemp1grep
+echo "grepinput8" >>testtemp1grep
+echo "grepinputBad8" >>testtemp1grep
+(cd $srcdir; $valgrind $vjs $pcre2grep -L -r --exclude=grepinput3 --exclude=grepinput[MCU] --include=grepinput --exclude-from $builddir/testtemp1grep --exclude-dir='^\.' 'fox' ./testdata | sort) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 99 -----------------------------" >>testtrygrep
+echo "grepinput$" >testtemp1grep
+echo "grepinput8" >testtemp2grep
+echo "grepinputBad8" >>testtemp1grep
+(cd $srcdir; $valgrind $vjs $pcre2grep -L -r --include grepinput --exclude=grepinput[MCU] --exclude-from $builddir/testtemp1grep --exclude-from=$builddir/testtemp2grep --exclude-dir='^\.' 'fox' ./testdata | sort) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 100 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -Ho2 --only-matching=1 -o3 '(\w+) binary (\w+)(\.)?' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 101 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o3 -Ho2 -o12 --only-matching=1 -o3 --colour=always --om-separator='|' '(\w+) binary (\w+)(\.)?' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 102 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -n "^$" ./testdata/grepinput3) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 103 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --only-matching "^$" ./testdata/grepinput3) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 104 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -n --only-matching "^$" ./testdata/grepinput3) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 105 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --colour=always "ipsum|" ./testdata/grepinput3) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 106 -----------------------------" >>testtrygrep
+(cd $srcdir; echo "a" | $valgrind $vjs $pcre2grep -M "|a" ) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 107 -----------------------------" >>testtrygrep
+echo "a" >testtemp1grep
+echo "aaaaa" >>testtemp1grep
+(cd $srcdir; $valgrind $vjs $pcre2grep --line-offsets --allow-lookaround-bsk '(?<=\Ka)' $builddir/testtemp1grep) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 108 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -lq PATTERN ./testdata/grepinput ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 109 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -cq --exclude=grepinputC lazy ./testdata/grepinput*) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 110 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --om-separator / -Mo0 -o1 -o2 'match (\d+):\n (.)\n' testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 111 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --line-offsets -M 'match (\d+):\n (.)\n' testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 112 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --file-offsets -M 'match (\d+):\n (.)\n' testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 113 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --total-count --exclude=grepinputC 'the' testdata/grepinput*) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 114 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -tc --exclude=grepinputC 'the' testdata/grepinput*) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 115 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -tlc --exclude=grepinputC 'the' testdata/grepinput*) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 116 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --exclude=grepinput[MCU] -th 'the' testdata/grepinput*) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 117 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -tch --exclude=grepinputC 'the' testdata/grepinput*) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 118 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -tL --exclude=grepinputC 'the' testdata/grepinput*) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 119 -----------------------------" >>testtrygrep
+printf '123\n456\n789\n---abc\ndef\nxyz\n---\n' >testNinputgrep
+$valgrind $vjs $pcre2grep -Mo '(\n|[^-])*---' testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 120 ------------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -HO '$0:$2$1$3' '(\w+) binary (\w+)(\.)?' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -HO '$&:$2$1$3' '(\w+) binary (\w+)(\.)?' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -m 1 -O '$0:$a$b$e$f$r$t$v' '(\w+) binary (\w+)(\.)?' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -HO '${X}' '(\w+) binary (\w+)(\.)?' ./testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -HO 'XX$' '(\w+) binary (\w+)(\.)?' ./testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -O '$x{12345678}' '(\w+) binary (\w+)(\.)?' ./testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -O '$x{123Z' '(\w+) binary (\w+)(\.)?' ./testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --output '$x{1234}' '(\w+) binary (\w+)(\.)?' ./testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 121 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -F '\E and (regex)' testdata/grepinputv) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 122 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -w 'cat|dog' testdata/grepinputv) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 123 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -w 'dog|cat' testdata/grepinputv) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 124 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -Mn --colour=always 'start[\s]+end' testdata/grepinputM) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -Mn --colour=always -A2 'start[\s]+end' testdata/grepinputM) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -Mn 'start[\s]+end' testdata/grepinputM) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -Mn -A2 'start[\s]+end' testdata/grepinputM) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 125 -----------------------------" >>testtrygrep
+printf 'abcd\n' >testNinputgrep
+$valgrind $vjs $pcre2grep --colour=always --allow-lookaround-bsk '(?<=\K.)' testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --colour=always --allow-lookaround-bsk '(?=.\K)' testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --colour=always --allow-lookaround-bsk '(?<=\K[ac])' testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --colour=always --allow-lookaround-bsk '(?=[ac]\K)' testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+GREP_COLORS='ms=1;20' $valgrind $vjs $pcre2grep --colour=always --allow-lookaround-bsk '(?=[ac]\K)' testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 126 -----------------------------" >>testtrygrep
+printf 'Next line pattern has binary zero\nABC\0XYZ\n' >testtemp1grep
+printf 'ABC\0XYZ\nABCDEF\nDEFABC\n' >testtemp2grep
+$valgrind $vjs $pcre2grep -a -f testtemp1grep testtemp2grep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+printf 'Next line pattern is erroneous.\n^abc)(xy' >testtemp1grep
+$valgrind $vjs $pcre2grep -a -f testtemp1grep testtemp2grep >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 127 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o --om-capture=0 'pattern()()()()' testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 128 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -m1M -o1 --om-capture=0 'pattern()()()()' testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 129 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -m 2 'fox' testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 130 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o -m2 'fox' testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 131 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -oc -m2 'fox' testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 132 -----------------------------" >>testtrygrep
+(cd $srcdir; exec 3>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 133 -----------------------------" >>testtrygrep
+(cd $srcdir; exec 3>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 134 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --max-count=1 -nH -O '=$x{41}$x423$o{103}$o1045=' 'fox' -) <$srcdir/testdata/grepinputv >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 135 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -HZ 'word' ./testdata/grepinputv) | $tr '\000' '@' >>testtrygrep
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -lZ 'word' ./testdata/grepinputv ./testdata/grepinputv) | $tr '\000' '@' >>testtrygrep
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -A 1 -B 1 -HZ 'word' ./testdata/grepinputv) | $tr '\000' '@' >>testtrygrep
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -MHZn 'start[\s]+end' testdata/grepinputM) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 136 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -m1MK -o1 --om-capture=0 'pattern()()()()' testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --max-count=1MK -o1 --om-capture=0 'pattern()()()()' testdata/grepinput) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 137 -----------------------------" >>testtrygrep
+printf 'Last line\nhas no newline' >testtemp1grep
+$valgrind $vjs $pcre2grep -A1 Last testtemp1grep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 138 -----------------------------" >>testtrygrep
+printf 'AbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\n' >testtemp1grep
+$valgrind $vjs $pcre2grep --no-jit --heap-limit=0 b testtemp1grep >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 139 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --line-buffered 'fox' testdata/grepinputv) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 140 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --buffer-size=10 -A1 'brown' testdata/grepinputv) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 141 -----------------------------" >>testtrygrep
+printf "%s/testdata/grepinputv\n-\n" "$srcdir" >testtemp1grep
+printf 'This is a line from stdin.' >testtemp2grep
+$valgrind $vjs $pcre2grep --file-list testtemp1grep "line from stdin" >testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 142 -----------------------------" >>testtrygrep
+printf "/does/not/exist\n" >testtemp1grep
+printf 'This is a line from stdin.' >testtemp2grep
+$valgrind $vjs $pcre2grep --file-list testtemp1grep "line from stdin" >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 143 -----------------------------" >>testtrygrep
+printf 'fox|cat' >testtemp1grep
+$valgrind $vjs $pcre2grep -f - $srcdir/testdata/grepinputv >testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 144 -----------------------------" >>testtrygrep
+$valgrind $vjs $pcre2grep -f /non/exist $srcdir/testdata/grepinputv >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 145 -----------------------------" >>testtrygrep
+printf '*meta*\rdog.' >testtemp1grep
+$valgrind $vjs $pcre2grep -Ncr -F -f testtemp1grep $srcdir/testdata/grepinputv >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 146 -----------------------------" >>testtrygrep
+printf 'A123B' >testtemp1grep
+$valgrind $vjs $pcre2grep -H -e '123|fox' - >testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep -h -e '123|fox' - $srcdir/testdata/grepinputv >testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep - $srcdir/testdata/grepinputv >testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 147 -----------------------------" >>testtrygrep
+$valgrind $vjs $pcre2grep -e '123|fox' -- -nonfile >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+printf 'A123B' >testtemp1grep
+printf 'C123D' > ./-testtemp1grep
+$valgrind $vjs $pcre2grep '123' -- -testtemp1grep >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep '123' testtemp1grep -- -testtemp1grep >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep '123' -- >testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+printf 'E123F' > ./--
+$valgrind $vjs $pcre2grep -- '123' -- >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 148 -----------------------------" >>testtrygrep
+$valgrind $vjs $pcre2grep --nonexist >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep -n-n-bad >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --context >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --only-matching --output=xx >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --colour=badvalue >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --newline=badvalue >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep -d badvalue >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep -D badvalue >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --buffer-size=0 >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --exclude '(badpat' abc /dev/null >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --exclude-from /non/exist abc /dev/null >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --include-from /non/exist abc /dev/null >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --file-list=/non/exist abc /dev/null >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 149 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --binary-files=binary "dog" ./testdata/grepbinary) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --binary-files=wrong "dog" ./testdata/grepbinary) >>testtrygrep 2>&1
+echo "RC=$?" >>testtrygrep
+
+# This test runs the code that tests locale support. However, on some systems
+# (e.g. Alpine Linux) there is no locale support and running this test just
+# generates a "no match" result. Therefore, we test for locale support, and if
+# it is found missing, we pretend that the test has run as expected so that the
+# output matches.
+
+echo "---------------------------- Test 150 -----------------------------" >>testtrygrep
+which locale >/dev/null 2>&1
+if [ $? -ne 0 ]; then
+ echo "pcre2grep: Failed to set locale locale.bad (obtained from LC_CTYPE)" >>testtrygrep
+ echo "RC=2" >>testtrygrep
+else
+
+ (cd $srcdir; unset LC_ALL; LC_CTYPE=locale.bad; export LC_CTYPE; $valgrind $vjs $pcre2grep abc /dev/null >>$builddir/testtrygrep 2>&1) >testtemp1grep 2>&1
+ echo "RC=$?" >>testtrygrep
+ shell_errors=`cat testtemp1grep`
+ if [ x"$shell_errors" != x ] ; then
+ printf "shell errors during locale test: "
+ echo "$shell_errors"
+ fi
+fi
+
+echo "---------------------------- Test 151 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep --colour=always -e this -e The -e 'The wo' testdata/grepinputv) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 152 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -nA3 --group-separator='++' 'four' ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 153 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -nA3 --no-group-separator 'four' ./testdata/grepinputx) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 154 -----------------------------" >>testtrygrep
+>testtemp1grep
+(cd $srcdir; $valgrind $vjs $pcre2grep -f $builddir/testtemp1grep ./testdata/grepinputv) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 155 -----------------------------" >>testtrygrep
+echo "" >testtemp1grep
+(cd $srcdir; $valgrind $vjs $pcre2grep -f $builddir/testtemp1grep ./testdata/grepinputv) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 156 -----------------------------" >>testtrygrep
+echo "" >testtemp1grep
+(cd $srcdir; $valgrind $vjs $pcre2grep --posix-pattern-file --file $builddir/testtemp1grep ./testdata/grepinputv) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 157 -----------------------------" >>testtrygrep
+echo "spaces " >testtemp1grep
+(cd $srcdir; $valgrind $vjs $pcre2grep -o --posix-pattern-file --file=$builddir/testtemp1grep ./testdata/grepinputv >$builddir/testtemp2grep && $valgrind $vjs $pcre2grep -q "s " $builddir/testtemp2grep) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 158 -----------------------------" >>testtrygrep
+echo "spaces." >testtemp1grep
+(cd $srcdir; $valgrind $vjs $pcre2grep -f $builddir/testtemp1grep ./testdata/grepinputv) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 159 -----------------------------" >>testtrygrep
+printf "spaces.\r\n" >testtemp1grep
+(cd $srcdir; $valgrind $vjs $pcre2grep --posix-pattern-file -f$builddir/testtemp1grep ./testdata/grepinputv) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 160 -----------------------------" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -nC3 '^(ert|jkl)' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+(cd $srcdir; $valgrind $vjs $pcre2grep -n -B4 -A2 '^(ert|dfg)' ./testdata/grepinput) >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "---------------------------- Test 161 -----------------------------" >>testtrygrep
+printf 'XfooY\n' >testNinputgrep
+$valgrind $vjs $pcre2grep --allow-lookaround-bsk -o '(?=foo\K)' testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --allow-lookaround-bsk --output '$0' '(?=foo\K)' testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --allow-lookaround-bsk --line-offsets '(?=foo\K)' testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep --allow-lookaround-bsk --file-offsets '(?=foo\K)' testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+
+# Now compare the results.
+
+$cf $srcdir/testdata/grepoutput testtrygrep
+if [ $? != 0 ] ; then exit 1; fi
+
+
+# These tests require UTF-8 support
+
+if [ $utf8 -ne 0 ] ; then
+ echo "Testing pcre2grep UTF-8 features"
+
+ echo "---------------------------- Test U1 ------------------------------" >testtrygrep
+ (cd $srcdir; $valgrind $vjs $pcre2grep -n -u --newline=any "^X" ./testdata/grepinput8) >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+
+ echo "---------------------------- Test U2 ------------------------------" >>testtrygrep
+ (cd $srcdir; $valgrind $vjs $pcre2grep -n -u -C 3 --newline=any "Match" ./testdata/grepinput8) >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+
+ echo "---------------------------- Test U3 ------------------------------" >>testtrygrep
+ (cd $srcdir; $valgrind $vjs $pcre2grep --line-offsets -u --newline=any --allow-lookaround-bsk '(?<=\K\x{17f})' ./testdata/grepinput8) >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+
+ echo "---------------------------- Test U4 ------------------------------" >>testtrygrep
+ (cd $srcdir; $valgrind $vjs $pcre2grep -u -o '....' ./testdata/grepinputBad8) >>testtrygrep 2>&1
+ echo "RC=$?" >>testtrygrep
+
+ echo "---------------------------- Test U5 ------------------------------" >>testtrygrep
+ (cd $srcdir; $valgrind $vjs $pcre2grep -U -o '....' ./testdata/grepinputBad8) >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+
+ echo "---------------------------- Test U6 -----------------------------" >>testtrygrep
+ (cd $srcdir; $valgrind $vjs $pcre2grep -u -m1 -O '=$x{1d3}$o{744}=' 'fox') <$srcdir/testdata/grepinputv >>testtrygrep 2>&1
+ echo "RC=$?" >>testtrygrep
+
+ echo "---------------------------- Test U7 ------------------------------" >>testtrygrep
+ (cd $srcdir; $valgrind $vjs $pcre2grep -ui --colour=always 'k+|\babc\b' ./testdata/grepinput8) >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+
+ echo "---------------------------- Test U8 ------------------------------" >>testtrygrep
+ (cd $srcdir; $valgrind $vjs $pcre2grep -UiEP --colour=always 'k+|\babc\b' ./testdata/grepinput8) >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+
+ echo "---------------------------- Test U9 ------------------------------" >>testtrygrep
+ (cd $srcdir; $valgrind $vjs $pcre2grep -u --colour=always 'A\d' ./testdata/grepinput8) >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+
+ echo "---------------------------- Test U10 ------------------------------" >>testtrygrep
+ (cd $srcdir; $valgrind $vjs $pcre2grep -u --posix-digit --colour=always 'A\d' ./testdata/grepinput8) >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+
+ echo "---------------------------- Test U11 ------------------------------" >>testtrygrep
+ printf '................................................' | tr '.' '\200' >testtemp1grep
+ printf 'x\n' >>testtemp1grep
+ $valgrind $vjs $pcre2grep --no-jit --buffer-size=16 -U --allow-lookaround-bsk -o '(?<=\K.)' testtemp1grep >>testtrygrep 2>&1
+ echo "only-matching RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep --no-jit --buffer-size=16 -U --allow-lookaround-bsk -M '(?<=\K.)' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep --no-jit --buffer-size=16 -U --allow-lookaround-bsk --colour=always '(?<=\K.)' testtemp1grep >>testtrygrep 2>&1
+ echo "colour RC=$?" >>testtrygrep
+
+ echo "---------------------------- Test U12 ------------------------------" >>testtrygrep
+ # Colouring only, so the subject is a single line. An empty match at the end
+ # of the subject, then one that matches before retrying at the end.
+ printf 'abc\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n --colour=always -u '$' testtemp1grep >>testtrygrep 2>&1
+ echo "colour-empty-at-end RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n --colour=always -u '.?' testtemp1grep >>testtrygrep 2>&1
+ echo "colour-nonempty-then-empty RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n --colour=always -u '^' testtemp1grep >>testtrygrep 2>&1
+ echo "colour-empty-at-start RC=$?" >>testtrygrep
+
+ # An empty line, so the first match is empty with nothing following it, and a
+ # final line with no newline, so a restart can reach the end of the line.
+ printf '\nabc\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n --colour=always -u '.?' testtemp1grep >>testtrygrep 2>&1
+ echo "colour-empty-line RC=$?" >>testtrygrep
+ printf 'abc' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n --colour=always -u '.?' testtemp1grep >>testtrygrep 2>&1
+ echo "colour-no-final-newline RC=$?" >>testtrygrep
+
+ # Multiline, where a restart may have to move on to a following line.
+ printf 'a\nb\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n -M -u '$' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-empty-at-line-end RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n -M -u '^' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-empty-at-line-start RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n -M -u '.?' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-nonempty-then-empty RC=$?" >>testtrygrep
+
+ # A match that spans several lines, so that the restart has to skip over more
+ # than one line before looking for the next match.
+ printf 'a\nb\nc\nd\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n -M -u '(?s)a.*c' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-spanning RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n -M -u '(?s)a.*c|$' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-spanning-then-empty RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n -M --colour=always -u '(?s)a.*c|$' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-colour-spanning RC=$?" >>testtrygrep
+
+ # Invalid UTF-8 after an empty match, which is when the scan over
+ # continuation bytes that follow the restart point can run. Here the scan
+ # stops at the start of the next character.
+ printf 'x\200\200y\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n --colour=always -U '^' testtemp1grep >>testtrygrep 2>&1
+ echo "colour-utf-scan-to-char RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n -M -U '^' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-utf-scan-to-char RC=$?" >>testtrygrep
+
+ # The continuation bytes run up to the newline, and then up to the end of the
+ # subject, when there is no newline to stop the scan.
+ printf 'x\200\200\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n --colour=always -U '^' testtemp1grep >>testtrygrep 2>&1
+ echo "colour-utf-scan-to-newline RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n -M -U '^' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-utf-scan-to-newline RC=$?" >>testtrygrep
+ printf 'x\200\200' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n --colour=always -U '^' testtemp1grep >>testtrygrep 2>&1
+ echo "colour-utf-scan-to-end RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n -M -U '^' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-utf-scan-to-end RC=$?" >>testtrygrep
+
+ # A subject that is nothing but continuation bytes, so the very first match
+ # is empty and the scan immediately reaches the end.
+ printf '\200\200' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n --colour=always -U '.?' testtemp1grep >>testtrygrep 2>&1
+ echo "colour-utf-only-continuations RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n -M -U '.?' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-utf-only-continuations RC=$?" >>testtrygrep
+
+ # Continuation bytes at the end of a multi-line subject, reached after an
+ # empty match on an earlier line, and after a match that spans lines.
+ printf 'a\nb\n\n\200\200' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n -M -U '.?' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-utf-trailing RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n -M -U '$' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-utf-trailing-empty RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n -M --colour=always -U '(?s)a.*b|$' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-colour-utf-trailing-spanning RC=$?" >>testtrygrep
+
+ echo "---------------------------- Test U13 ------------------------------" >>testtrygrep
+ # The same restart, but reached by \K rather than by an empty match.
+ printf 'abc\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n --colour=always -u --allow-lookaround-bsk '(?<=\K.)' testtemp1grep >>testtrygrep 2>&1
+ echo "colour-bsk RC=$?" >>testtrygrep
+ printf 'a\nb\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n -M -u --allow-lookaround-bsk '(?<=\K.)' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-bsk RC=$?" >>testtrygrep
+
+ # The same, but with the restart landing on invalid UTF-8.
+ printf 'x\200\200y\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep --no-jit -n --colour=always -U --allow-lookaround-bsk '(?<=\K.)' testtemp1grep >>testtrygrep 2>&1
+ echo "colour-bsk-utf-scan-to-char RC=$?" >>testtrygrep
+ printf 'x\200\200' >testtemp1grep
+ $valgrind $vjs $pcre2grep --no-jit -n -M -U --allow-lookaround-bsk '(?<=\K.)' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-bsk-utf-scan-to-end RC=$?" >>testtrygrep
+ printf 'a\nx\200\200' >testtemp1grep
+ $valgrind $vjs $pcre2grep --no-jit -n -M --colour=always -U --allow-lookaround-bsk '(?<=\K.)' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-colour-bsk-utf-trailing RC=$?" >>testtrygrep
+
+
+ echo "---------------------------- Test U14 ------------------------------" >>testtrygrep
+
+ # A pattern that keeps making progress, so the restart is the ordinary one
+ # and the line is never advanced. This is the path the other U14 tests build on.
+ printf 'abcabc\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n -o -u 'a.' testtemp1grep >>testtrygrep 2>&1
+ echo "control-progress RC=$?" >>testtrygrep
+
+ # An empty match, which is the case the restart exists for. "$" matches only
+ # at the end of the subject, so the restart is immediately at the end; "^"
+ # matches at the start, so it has to step forward by one character first.
+ $valgrind $vjs $pcre2grep -n -o -u '$' testtemp1grep >>testtrygrep 2>&1
+ echo "empty-at-end RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n -o -u '^' testtemp1grep >>testtrygrep 2>&1
+ echo "empty-at-start RC=$?" >>testtrygrep
+
+ # \K in a lookbehind reports a non-empty match that ends no later than the
+ # offset it was started from. PCRE2_NOTEMPTY is set once a match has been
+ # found, so this, unlike an empty match, can stop the loop making progress on
+ # every iteration and not just the first.
+ $valgrind $vjs $pcre2grep -n -o -u --allow-lookaround-bsk '(?<=\K.)' testtemp1grep >>testtrygrep 2>&1
+ echo "bsk-restart RC=$?" >>testtrygrep
+
+ # The step forward lands on invalid UTF-8, so the scan over continuation
+ # bytes runs. Here it stops at the start of the next character, and then at
+ # the newline, both of which are within the subject.
+ printf 'x\200\200y\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep --no-jit -n -o -U --allow-lookaround-bsk '(?<=\K.)' testtemp1grep >>testtrygrep 2>&1
+ echo "bsk-utf-scan-to-char RC=$?" >>testtrygrep
+ printf 'x\200\200\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep --no-jit -n -o -U --allow-lookaround-bsk '(?<=\K.)' testtemp1grep >>testtrygrep 2>&1
+ echo "bsk-utf-scan-to-newline RC=$?" >>testtrygrep
+
+ # The same, but with no newline to stop the scan, so it runs to the end of
+ # the subject and then looks at the byte after it.
+ printf 'x\200\200' >testtemp1grep
+ $valgrind $vjs $pcre2grep --no-jit -n -o -U --allow-lookaround-bsk '(?<=\K.)' testtemp1grep >>testtrygrep 2>&1
+ echo "bsk-utf-scan-to-end RC=$?" >>testtrygrep
+
+ # Moving on to another line, which only happens in multiline mode. The first
+ # match ends exactly at the start of the next line, so the line is advanced
+ # and the line number with it; the second ends two lines further on.
+ printf 'ab\ncd\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n -o -M -u 'ab\n' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-line-boundary RC=$?" >>testtrygrep
+ printf 'ab\ncd\nef\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n -o -M -u '(?s)ab.*ef' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-spanning RC=$?" >>testtrygrep
+
+ # An empty match in multiline mode, where the step forward is what takes the
+ # restart past the end of the line.
+ printf 'a\nb\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n -o -M -u '$' testtemp1grep >>testtrygrep 2>&1
+ echo "multiline-empty RC=$?" >>testtrygrep
+
+ # A match that ends between the CR and the LF of a CRLF line ending, so the
+ # restart is past the text of the line but short of the start of the next
+ # one. Without -M the line is never advanced, so that is the control.
+ printf 'ab\r\ncd\r\n' >testtemp1grep
+ $valgrind $vjs $pcre2grep -n -o -N CRLF '\r' testtemp1grep >>testtrygrep 2>&1
+ echo "crlf-not-multiline RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n -o -M -N CRLF '\r' testtemp1grep >>testtrygrep 2>&1
+ echo "crlf-mid-terminator RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -n -o -M -N ANY '\r' testtemp1grep >>testtrygrep 2>&1
+ echo "any-mid-terminator RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep -M -N CRLF --line-offsets '\r' testtemp1grep >>testtrygrep 2>&1
+ echo "crlf-mid-terminator-line-offsets RC=$?" >>testtrygrep
+
+ $cf $srcdir/testdata/grepoutput8 testtrygrep
+ if [ $? != 0 ] ; then exit 1; fi
+
+else
+ echo "Skipping pcre2grep UTF-8 tests: no UTF-8 support in PCRE2 library"
+fi
+
+
+# We go to some contortions to try to ensure that the tests for the various
+# newline settings will work in environments where the normal newline sequence
+# is not \n. Do not use exported files, whose line endings might be changed.
+# Instead, create an input file using printf so that its contents are exactly
+# what we want. Note the messy fudge to get printf to write a string that
+# starts with a hyphen. These tests are run in the build directory.
+
+echo "Testing pcre2grep newline settings"
+printf 'abc\rdef\r\nghi\njkl' >testNinputgrep
+
+printf '%c--------------------------- Test N1 ------------------------------\r\n' - >testtrygrep
+$valgrind $vjs $pcre2grep -n -N CR "^(abc|def|ghi|jkl)" testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep -B1 -n -N CR "^def" testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+printf '%c--------------------------- Test N2 ------------------------------\r\n' - >>testtrygrep
+$valgrind $vjs $pcre2grep -n --newline=crlf "^(abc|def|ghi|jkl)" testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep -B1 -n -N CRLF "^ghi" testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+printf '%c--------------------------- Test N3 ------------------------------\r\n' - >>testtrygrep
+pattern=`printf 'def\rjkl'`
+$valgrind $vjs $pcre2grep -n --newline=cr -F "$pattern" testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+printf '%c--------------------------- Test N4 ------------------------------\r\n' - >>testtrygrep
+$valgrind $vjs $pcre2grep -n --newline=crlf -F -f $srcdir/testdata/greppatN4 testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+printf '%c--------------------------- Test N5 ------------------------------\r\n' - >>testtrygrep
+$valgrind $vjs $pcre2grep -n --newline=any "^(abc|def|ghi|jkl)" testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep -B1 -n --newline=any "^def" testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+printf '%c--------------------------- Test N6 ------------------------------\r\n' - >>testtrygrep
+$valgrind $vjs $pcre2grep -n --newline=anycrlf "^(abc|def|ghi|jkl)" testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep -B1 -n --newline=anycrlf "^jkl" testNinputgrep >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+printf '%c--------------------------- Test N7 ------------------------------\r\n' - >>testtrygrep
+printf 'xyz\0abc\0def' >testNinputgrep
+$valgrind $vjs $pcre2grep -na --newline=nul "^(abc|def)" testNinputgrep | $tr '\000' '@' >>testtrygrep
+echo "RC=$?" >>testtrygrep
+$valgrind $vjs $pcre2grep -B1 -na --newline=nul "^(abc|def)" testNinputgrep | $tr '\000' '@' >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+printf '%c--------------------------- Test N8 ------------------------------\r\n' - >>testtrygrep
+$valgrind $vjs $pcre2grep -na --newline=anycrlf "^a" $srcdir/testdata/grepinputBad8_Trail >>testtrygrep
+echo "RC=$?" >>testtrygrep
+
+echo "" >>testtrygrep
+
+$cf $srcdir/testdata/grepoutputN testtrygrep
+if [ $? != 0 ] ; then exit 1; fi
+
+
+# These newline tests need UTF support.
+
+if [ $utf8 -ne 0 ] ; then
+ echo "Testing pcre2grep newline settings with UTF-8 features"
+
+ printf '%c--------------------------- Test UN1 ------------------------------\r\n' - >testtrygrep
+ $valgrind $vjs $pcre2grep -nau --newline=anycrlf "^(abc|def)" $srcdir/testdata/grepinputUN >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+
+ printf '%c--------------------------- Test UN2 ------------------------------\r\n' - >testtrygrep
+ $valgrind $vjs $pcre2grep -nauU --newline=anycrlf "^a" $srcdir/testdata/grepinputBad8_Trail >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+
+ echo "" >>testtrygrep
+
+ $cf $srcdir/testdata/grepoutputUN testtrygrep
+ if [ $? != 0 ] ; then exit 1; fi
+else
+ echo "Skipping pcre2grep newline UTF-8 tests: no UTF-8 support in PCRE2 library"
+fi
+
+
+# If pcre2grep supports script callouts, run some tests on them. It is possible
+# to restrict these callouts to the non-fork case, either for security, or for
+# environments that do not support fork(). This is handled by comparing to a
+# different output.
+
+if $valgrind $vjs $pcre2grep --help | $valgrind $vjs $pcre2grep -q 'callout scripts in patterns are supported'; then
+ echo "Testing pcre2grep script callouts"
+ echo "--- Test 1 ---" >testtrygrep
+ $valgrind $vjs $pcre2grep '(T)(..(.))(?C"/bin/echo|Arg1: [$1] [$2] [$3]|Arg2: $|${1}$| ($4) ($14) ($0)")()' $srcdir/testdata/grepinputv >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+ echo "--- Test 2 ---" >>testtrygrep
+ $valgrind $vjs $pcre2grep '(T)(..(.))()()()()()()()(..)(?C"/bin/echo|Arg1: [$11] [${11}]")' $srcdir/testdata/grepinputv >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+ echo "--- Test 3 ---" >>testtrygrep
+ $valgrind $vjs $pcre2grep '(T)(?C"|$0:$1$n")' $srcdir/testdata/grepinputv >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+ echo "--- Test 4 ---" >>testtrygrep
+ $valgrind $vjs $pcre2grep '(T)(?C"/bin/echo|$0:$1$n")' $srcdir/testdata/grepinputv >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+ echo "--- Test 5 ---" >>testtrygrep
+ $valgrind $vjs $pcre2grep '(T)(?C"|$1$n")(*F)' $srcdir/testdata/grepinputv >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+ echo "--- Test 6 ---" >>testtrygrep
+ $valgrind $vjs $pcre2grep -m1 '(T)(?C"|$0:$1:$x{41}$o{101}$n")' $srcdir/testdata/grepinputv >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+
+ if $valgrind $vjs $pcre2grep --help | $valgrind $vjs $pcre2grep -q 'Non-fork callout scripts in patterns are supported'; then
+ nonfork=1
+ $cf $srcdir/testdata/grepoutputCN testtrygrep
+ else
+ nonfork=0
+ $cf $srcdir/testdata/grepoutputC testtrygrep
+ fi
+ if [ $? != 0 ] ; then exit 1; fi
+
+ # These callout tests need UTF support.
+
+ if [ $utf8 -ne 0 ] ; then
+ echo "Testing pcre2grep script callout with UTF-8 features"
+ echo "--- Test 1 ---" >testtrygrep
+ $valgrind $vjs $pcre2grep -u '(T)(?C"|$0:$x{a6}$n")' $srcdir/testdata/grepinputv >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+ echo "--- Test 2 ---" >>testtrygrep
+ $valgrind $vjs $pcre2grep -u '(T)(?C"/bin/echo|$0:$x{a6}$n")' $srcdir/testdata/grepinputv >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+
+ if [ $nonfork = 1 ] ; then
+ $cf $srcdir/testdata/grepoutputCNU testtrygrep
+ else
+ $cf $srcdir/testdata/grepoutputCU testtrygrep
+ fi
+ if [ $? != 0 ] ; then exit 1; fi
+ else
+ echo "Skipping pcre2grep script callout UTF-8 tests: no UTF-8 support in PCRE2 library"
+ fi
+
+ unset nonfork
+else
+ echo "Script callouts are not supported"
+fi
+
+
+# Test reading .gz and .bz2 files when supported.
+
+if $valgrind $vjs $pcre2grep --help | $valgrind $vjs $pcre2grep -q '\.gz are read using zlib'; then
+ echo "Testing reading .gz file"
+ $valgrind $vjs $pcre2grep 'one|two' $srcdir/testdata/grepinputC.gz >testtrygrep
+ echo "RC=$?" >>testtrygrep
+ $cf $srcdir/testdata/grepoutputCgz testtrygrep
+ if [ $? != 0 ] ; then exit 1; fi
+fi
+
+if $valgrind $vjs $pcre2grep --help | $valgrind $vjs $pcre2grep -q '\.bz2 are read using bzlib2'; then
+ echo "Testing reading .bz2 file"
+ $valgrind $vjs $pcre2grep 'one|two' $srcdir/testdata/grepinputC.bz2 >testtrygrep
+ echo "RC=$?" >>testtrygrep
+ $valgrind $vjs $pcre2grep 'one|two' $srcdir/testdata/grepnot.bz2 >>testtrygrep
+ echo "RC=$?" >>testtrygrep
+ $cf $srcdir/testdata/grepoutputCbz2 testtrygrep
+ if [ $? != 0 ] ; then exit 1; fi
+fi
+
+
+# Finally, some tests to exercise code that is not tested above, just to be
+# sure that it runs OK. Doing this improves the coverage statistics. The output
+# is not checked.
+
+echo "Testing miscellaneous pcre2grep arguments (unchecked)"
+echo '' >testtrygrep
+checkspecial '-xxxxx' 2
+checkspecial '--help' 0
+checkspecial '--line-buffered --colour=auto abc /dev/null' 1
+checkspecial '--line-buffered --color abc /dev/null' 1
+checkspecial '-dskip abc .' 1
+checkspecial '-Dread -Dskip abc /dev/null' 1
+checkspecial "-f $srcdir/testdata/greplistBad /dev/null" 2
+checkspecial "(unpaired /dev/null" 2
+checkspecial "-e (unpaired1 -e (unpaired2 /dev/null" 2
+
+# Clean up local working files
+rm -f testNinputgrep teststderrgrep testtrygrep testtemp1grep testtemp2grep
+rm -f ./-testtemp1grep ./--
+
+exit 0
+
+# End
diff --git a/RunGrepTest.bat b/RunGrepTest.bat
new file mode 100644
index 0000000..38eeabe
--- /dev/null
+++ b/RunGrepTest.bat
@@ -0,0 +1,1338 @@
+@echo off
+
+:: Run pcre2grep tests. The assumption is that the PCRE2 tests check the library
+:: itself. What we are checking here is the file handling and options that are
+:: supported by pcre2grep. This script must be run in the build directory.
+:: (jmh: I've only tested in the main directory, using my own builds.)
+
+setlocal enabledelayedexpansion
+
+:: Remove any non-default colouring that the caller may have set.
+
+set PCRE2GREP_COLOUR=
+set PCRE2GREP_COLOR=
+set PCREGREP_COLOUR=
+set PCREGREP_COLOR=
+set GREP_COLORS=
+set GREP_COLOR=
+
+:: Remember the current (build) directory and set the program to be tested.
+
+set builddir="%CD%"
+
+if [%pcre2grep%]==[] set pcre2grep=%builddir%\pcre2grep.exe
+if [%pcre2test%]==[] set pcre2test=%builddir%\pcre2test.exe
+
+if NOT exist %pcre2grep% (
+ echo ** %pcre2grep% does not exist.
+ exit /b 1
+)
+
+if NOT exist %pcre2test% (
+ echo ** %pcre2test% does not exist.
+ exit /b 1
+)
+
+for /f "delims=" %%a in ('"%pcre2grep%" -V') do set pcre2grep_version=%%a
+echo Testing %pcre2grep_version%
+
+:: Set up a suitable "diff" command for comparison. Some systems have a diff
+:: that lacks a -u option. Try to deal with this; better do the test for the -b
+:: option as well. Use FC if there's no diff, taking care to ignore equality.
+
+set cf=
+set cfout=
+diff -b nul nul 2>nul && set cf=diff -b
+diff -u nul nul 2>nul && set cf=diff -u
+diff -ub nul nul 2>nul && set cf=diff -ub
+if NOT defined cf (
+ set cf=fc /n
+ set "cfout=>testcf || (type testcf & cmd /c exit /b 1)"
+)
+
+:: Set srcdir to the current or parent directory, whichever one contains the
+:: test data. Subsequently, we run most of the pcre2grep tests in the source
+:: directory so that the file names in the output are always the same.
+
+if NOT defined srcdir set srcdir=.
+if NOT exist %srcdir%\testdata\ (
+ if exist testdata\ (
+ set srcdir=.
+ ) else if exist ..\testdata\ (
+ set srcdir=..
+ ) else if exist ..\..\testdata\ (
+ set srcdir=..\..
+ ) else (
+ echo Cannot find the testdata directory
+ exit /b 1
+ )
+)
+
+:: Check for the availability of UTF-8 support
+
+%pcre2test% -C unicode >nul
+set utf8=%ERRORLEVEL%
+
+:: Check default newline convention. If it does not include LF, force LF.
+
+for /f %%a in ('"%pcre2test%" -C newline') do set nl=%%a
+if NOT "%nl%" == "LF" if NOT "%nl%" == "ANY" if NOT "%nl%" == "ANYCRLF" (
+ set pcre2grep=%pcre2grep% -N LF
+ echo Default newline setting forced to LF
+)
+
+:: Provide "printf" and "tr" via pcre2test. Windows has no dependable version
+:: of either: the obvious candidates translate what they write according to the
+:: current code page, which mangles any byte greater than 0x7f, and an actual
+:: printf may turn LF into CRLF. pcre2test has undocumented options that do just
+:: as much as these tests need, so that this script can produce exactly the same
+:: bytes as RunGrepTest does with the real printf and tr.
+::
+:: %printf% supports \r, \n, \\, an octal escape such as \0 or \200, and one
+:: %%s substitution; any other escape is left alone, so a literal backslash
+:: has to be written as \\. %tr% changes one byte value into another as it
+:: copies its input.
+
+set printf=%pcre2test% -printf
+set tr=%pcre2test% -tr
+
+:: pcre2grep ends the lines it writes with CRLF on Windows and with LF
+:: elsewhere, which comparison copes with, but a line whose own text ends with
+:: CR then comes out with one CR too many. %fixcrlf% removes it, for tests that
+:: match a CR at the end of a line.
+
+set fixcrlf=%pcre2test% -fixcrlf
+
+:: The script callout tests run printf as a callout, where the program name
+:: cannot be quoted, so keep an unquoted version of the path for them.
+
+set pcre2test_unquoted=%pcre2test:"=%
+
+:: ------ Normal tests ------
+
+echo Testing pcre2grep main features
+
+echo ---------------------------- Test 1 ------------------------------>testtrygrep
+(pushd %srcdir% & %pcre2grep% PATTERN ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 2 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% "^PATTERN" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 3 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -in PATTERN ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 4 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -ic PATTERN ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 5 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -in PATTERN ./testdata/grepinput ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 6 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -inh PATTERN ./testdata/grepinput ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 7 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -il PATTERN ./testdata/grepinput ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 8 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -l PATTERN ./testdata/grepinput ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 9 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -q PATTERN ./testdata/grepinput ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 10 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -q NEVER-PATTERN ./testdata/grepinput ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 11 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -vn pattern ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 12 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -ix pattern ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 13 ----------------------------->>testtrygrep
+echo seventeen >testtemp1grep
+(pushd %srcdir% & %pcre2grep% -f./testdata/greplist -f %builddir%\testtemp1grep ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 14 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -w pat ./testdata/grepinput ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 15 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% "abc^*" ./testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 16 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% abc ./testdata/grepinput ./testdata/nonexistfile & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 17 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -M "the\noutput" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 18 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -Mn "(the\noutput|dog\.\n--)" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 19 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -Mix "Pattern" ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 20 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -Mixn "complete pair\nof lines" ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 21 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -nA3 "four" ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 22 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -nB3 "four" ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 23 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -C3 "four" ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 24 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -A9 "four" ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 25 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -nB9 "four" ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 26 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -A9 -B9 "four" ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 27 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -A10 "four" ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 28 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -nB10 "four" ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 29 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -C12 -B10 "four" ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 30 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -inB3 "pattern" ./testdata/grepinput ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 31 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -inA3 "pattern" ./testdata/grepinput ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 32 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -L "fox" ./testdata/grepinput ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 33 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% "fox" ./testdata/grepnonexist & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 34 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -s "fox" ./testdata/grepnonexist & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 35 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -L -r --include=grepinputx --include grepinput8 --exclude-dir="^\." "fox" ./testdata | sort & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 36 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -L -r --include="grepinput[^C]" --exclude "grepinput$" --exclude="grepinput(Bad)?8" --exclude=grepinputM --exclude=grepinputUN --exclude-dir="^\." "fox" ./testdata | sort & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 37 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% "^(a+)*\d" ./testdata/grepinput & popd) >>testtrygrep 2>teststderrgrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+echo ======== STDERR ========>>testtrygrep
+type teststderrgrep >>testtrygrep
+
+echo ---------------------------- Test 38 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% ">\x00<" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 39 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -A1 "before the binary zero" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 40 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -B1 "after the binary zero" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 41 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -B1 -o "\w+ the binary zero" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 42 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -B1 -onH "\w+ the binary zero" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 43 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -on "before|zero|after" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 44 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -on -e before -ezero -e after ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 45 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -on -f ./testdata/greplist -e binary ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 46 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -e "unopened)" -e abc ./testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -eabc -e "(unclosed" ./testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -eabc -e xyz -e "[unclosed" ./testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% --regex=123 -eabc -e xyz -e "[unclosed" ./testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 47 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -Fx AB.VE^
+
+elephant ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 48 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -F AB.VE^
+
+elephant ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 49 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -F -e DATA -e AB.VE^
+
+elephant ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 50 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% "^(abc|def|ghi|jkl)" ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 51 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -Mv "brown\sfox" ./testdata/grepinputv & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 52 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% --colour=always jumps ./testdata/grepinputv & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 53 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% --file-offsets "before|zero|after" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 54 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% --line-offsets "before|zero|after" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 55 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -f./testdata/greplist --color=always ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 56 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -c --exclude=grepinputC lazy ./testdata/grepinput* & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 57 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -c -l --exclude=grepinputC lazy ./testdata/grepinput* & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 58 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --regex=PATTERN ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 59 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --regexp=PATTERN ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 60 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --regex PATTERN ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 61 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --regexp PATTERN ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 62 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --match-limit=1000 --no-jit -M "This is a file(.|\R)*file." ./testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 63 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --recursion-limit=1000 --no-jit -M "This is a file(.|\R)*file." ./testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 64 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o1 "(?<=PAT)TERN (ap(pear)s)" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 65 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o2 "(?<=PAT)TERN (ap(pear)s)" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 66 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o3 "(?<=PAT)TERN (ap(pear)s)" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 67 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o12 "(?<=PAT)TERN (ap(pear)s)" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 68 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% --only-matching=2 "(?<=PAT)TERN (ap(pear)s)" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 69 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -vn --colour=always pattern ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 70 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --color=always -M "triple:\t.*\n\n" ./testdata/grepinput3 & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% --color=always -M -n "triple:\t.*\n\n" ./testdata/grepinput3 & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -M "triple:\t.*\n\n" ./testdata/grepinput3 & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -M -n "triple:\t.*\n\n" ./testdata/grepinput3 & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 71 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o "^01|^02|^03" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 72 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --color=always "^01|^02|^03" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 73 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o --colour=always "^01|^02|^03" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 74 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o "^01|02|^03" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 75 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --color=always "^01|02|^03" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 76 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o --colour=always "^01|02|^03" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 77 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o "^01|^02|03" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 78 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --color=always "^01|^02|03" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 79 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o --colour=always "^01|^02|03" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 80 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o "\b01|\b02" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 81 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --color=always "\b01|\b02" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 82 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o --colour=always "\b01|\b02" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 83 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --buffer-size=10 --max-buffer-size=100 "^a" ./testdata/grepinput3 & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 84 ----------------------------->>testtrygrep
+echo testdata/grepinput3 >testtemp1grep
+(pushd %srcdir% & %pcre2grep% --file-list ./testdata/grepfilelist --file-list %builddir%\testtemp1grep "fox|complete|t7" & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 85 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --file-list=./testdata/grepfilelist "dolor" ./testdata/grepinput3 & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 86 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% "dog" ./testdata/grepbinary & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 87 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% "cat" ./testdata/grepbinary & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 88 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -v "cat" ./testdata/grepbinary & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 89 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -I "dog" ./testdata/grepbinary & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 90 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --binary-files=without-match "dog" ./testdata/grepbinary & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 91 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -a "dog" ./testdata/grepbinary & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 92 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --binary-files=text "dog" ./testdata/grepbinary & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 93 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --text "dog" ./testdata/grepbinary & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 94 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -L -r --include=grepinputx --include grepinput8 "fox" ./testdata/grepinput* | sort & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 95 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --file-list ./testdata/grepfilelist --exclude grepinputv "fox|complete" & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 96 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -L -r --include-dir=testdata --exclude "^^(?^!grepinput)" --exclude=grepinput[MCU] "fox" ./test* | sort & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 97 ----------------------------->>testtrygrep
+echo grepinput$>testtemp1grep
+echo grepinput8>>testtemp1grep
+echo grepinputBad8>>testtemp1grep
+(pushd %srcdir% & %pcre2grep% -L -r --include=grepinput --exclude=grepinput[MCU] --exclude-from %builddir%\testtemp1grep --exclude-dir="^\." "fox" ./testdata | sort & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 98 ----------------------------->>testtrygrep
+echo grepinput$>testtemp1grep
+echo grepinput8>>testtemp1grep
+echo grepinputBad8>>testtemp1grep
+(pushd %srcdir% & %pcre2grep% -L -r --exclude=grepinput3 --exclude=grepinput[MCU] --include=grepinput --exclude-from %builddir%\testtemp1grep --exclude-dir="^\." "fox" ./testdata | sort & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 99 ----------------------------->>testtrygrep
+echo grepinput$>testtemp1grep
+echo grepinput8>testtemp2grep
+echo grepinputBad8>>testtemp1grep
+(pushd %srcdir% & %pcre2grep% -L -r --include grepinput --exclude=grepinput[MCU] --exclude-from %builddir%\testtemp1grep --exclude-from=%builddir%\testtemp2grep --exclude-dir="^\." "fox" ./testdata | sort & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 100 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -Ho2 --only-matching=1 -o3 "(\w+) binary (\w+)(\.)?" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 101 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o3 -Ho2 -o12 --only-matching=1 -o3 --colour=always --om-separator="|" "(\w+) binary (\w+)(\.)?" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 102 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -n "^$" ./testdata/grepinput3 & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 103 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --only-matching "^$" ./testdata/grepinput3 & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 104 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -n --only-matching "^$" ./testdata/grepinput3 & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 105 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --colour=always "ipsum|" ./testdata/grepinput3 & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 106 ----------------------------->>testtrygrep
+(pushd %srcdir% & echo a| %pcre2grep% -M "|a" & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 107 ----------------------------->>testtrygrep
+echo a>testtemp1grep
+echo aaaaa>>testtemp1grep
+(pushd %srcdir% & %pcre2grep% --line-offsets --allow-lookaround-bsk "(?<=\Ka)" %builddir%\testtemp1grep & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 108 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -lq PATTERN ./testdata/grepinput ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 109 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -cq --exclude=grepinputC lazy ./testdata/grepinput* & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 110 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --om-separator / -Mo0 -o1 -o2 "match (\d+):\n (.)\n" testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 111 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --line-offsets -M "match (\d+):\n (.)\n" testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 112 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --file-offsets -M "match (\d+):\n (.)\n" testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 113 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --total-count --exclude=grepinputC "the" testdata/grepinput* & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 114 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -tc --exclude=grepinputC "the" testdata/grepinput* & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 115 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -tlc --exclude=grepinputC "the" testdata/grepinput* & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 116 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --exclude=grepinput[MCU] -th "the" testdata/grepinput* & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 117 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -tch --exclude=grepinputC "the" testdata/grepinput* & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 118 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -tL --exclude=grepinputC "the" testdata/grepinput* & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 119 ----------------------------->>testtrygrep
+%printf% "123\n456\n789\n---abc\ndef\nxyz\n---\n" >testNinputgrep
+%pcre2grep% -Mo "(\n|[^-])*---" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 120 ------------------------------>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -HO "$0:$2$1$3" "(\w+) binary (\w+)(\.)?" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -HO "$&:$2$1$3" "(\w+) binary (\w+)(\.)?" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -m 1 -O "$0:$a$b$e$f$r$t$v" "(\w+) binary (\w+)(\.)?" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -HO "${X}" "(\w+) binary (\w+)(\.)?" ./testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -HO "XX$" "(\w+) binary (\w+)(\.)?" ./testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -O "$x{12345678}" "(\w+) binary (\w+)(\.)?" ./testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -O "$x{123Z" "(\w+) binary (\w+)(\.)?" ./testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% --output "$x{1234}" "(\w+) binary (\w+)(\.)?" ./testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 121 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -F "\E and (regex)" testdata/grepinputv & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 122 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -w "cat|dog" testdata/grepinputv & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 123 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -w "dog|cat" testdata/grepinputv & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 124 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -Mn --colour=always "start[\s]+end" testdata/grepinputM & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -Mn --colour=always -A2 "start[\s]+end" testdata/grepinputM & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -Mn "start[\s]+end" testdata/grepinputM & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -Mn -A2 "start[\s]+end" testdata/grepinputM & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 125 ----------------------------->>testtrygrep
+%printf% "abcd\n" >testNinputgrep
+%pcre2grep% --colour=always --allow-lookaround-bsk "(?<=\K.)" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --colour=always --allow-lookaround-bsk "(?=.\K)" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --colour=always --allow-lookaround-bsk "(?<=\K[ac])" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --colour=always --allow-lookaround-bsk "(?=[ac]\K)" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+set GREP_COLORS=ms=1;20
+%pcre2grep% --colour=always --allow-lookaround-bsk "(?=[ac]\K)" testNinputgrep >>testtrygrep
+set GREP_COLORS=
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 126 ----------------------------->>testtrygrep
+%printf% "Next line pattern has binary zero\nABC\0XYZ\n" >testtemp1grep
+%printf% "ABC\0XYZ\nABCDEF\nDEFABC\n" >testtemp2grep
+%pcre2grep% -a -f testtemp1grep testtemp2grep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%printf% "Next line pattern is erroneous.\n^abc)(xy" >testtemp1grep
+%pcre2grep% -a -f testtemp1grep testtemp2grep >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 127 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o --om-capture=0 "pattern()()()()" testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 128 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -m1M -o1 --om-capture=0 "pattern()()()()" testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 129 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -m 2 "fox" testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 130 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -o -m2 "fox" testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 131 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -oc -m2 "fox" testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 132 ----------------------------->>testtrygrep
+:: The Unix tests use fd3 here, but Windows only has StdIn/StdOut/StdErr (which, at the kernel
+:: level, are not even numbered). Use a subshell instead.
+(pushd %srcdir% & (%pcre2grep% -m1 -A3 "^match" & echo ---& %pcre2grep% -m1 ".*") >testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 133 ----------------------------->>testtrygrep
+:: The Unix tests use fd3 here, but Windows only has StdIn/StdOut/StdErr (which, at the kernel
+:: level, are not even numbered). Use a subshell instead.
+(pushd %srcdir% & (%pcre2grep% -m1 -A3 "^match" & echo ---& %pcre2grep% -m1 -A3 "^match") >testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 134 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --max-count=1 -nH -O "=$x{41}$x423$o{103}$o1045=" "fox" - & popd) <%srcdir%\testdata\grepinputv >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 135 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -HZ "word" ./testdata/grepinputv & popd) | %tr% \0 @ >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -lZ "word" ./testdata/grepinputv ./testdata/grepinputv & popd) | %tr% \0 @ >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -A 1 -B 1 -HZ "word" ./testdata/grepinputv & popd) | %tr% \0 @ >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -MHZn "start[\s]+end" testdata/grepinputM & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 136 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -m1MK -o1 --om-capture=0 "pattern()()()()" testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% --max-count=1MK -o1 --om-capture=0 "pattern()()()()" testdata/grepinput & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 137 ----------------------------->>testtrygrep
+%printf% "Last line\nhas no newline" >testtemp1grep
+%pcre2grep% -A1 Last testtemp1grep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 138 ----------------------------->>testtrygrep
+%printf% "AbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\nAbC\n" >testtemp1grep
+%pcre2grep% --no-jit --heap-limit=0 b testtemp1grep >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 139 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --line-buffered "fox" testdata/grepinputv & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 140 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --buffer-size=10 -A1 "brown" testdata/grepinputv & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 141 ----------------------------->>testtrygrep
+%printf% "%%s\\testdata\\grepinputv\n-\n" "%srcdir%" >testtemp1grep
+%printf% "This is a line from stdin." >testtemp2grep
+%pcre2grep% --file-list testtemp1grep "line from stdin" >testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 142 ----------------------------->>testtrygrep
+%printf% "/does/not/exist\n" >testtemp1grep
+%printf% "This is a line from stdin." >testtemp2grep
+%pcre2grep% --file-list testtemp1grep "line from stdin" >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 143 ----------------------------->>testtrygrep
+%printf% "fox|cat" >testtemp1grep
+%pcre2grep% -f - %srcdir%\testdata\grepinputv >testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 144 ----------------------------->>testtrygrep
+%pcre2grep% -f /non/exist %srcdir%\testdata\grepinputv >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 145 ----------------------------->>testtrygrep
+%printf% "*meta*\rdog." >testtemp1grep
+%pcre2grep% -Ncr -F -f testtemp1grep %srcdir%\testdata\grepinputv >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 146 ----------------------------->>testtrygrep
+%printf% "A123B" >testtemp1grep
+%pcre2grep% -H -e "123|fox" - >testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% -h -e "123|fox" - %srcdir%\testdata\grepinputv >testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% - %srcdir%\testdata\grepinputv >testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 147 ----------------------------->>testtrygrep
+%pcre2grep% -e "123|fox" -- -nonfile >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%printf% "A123B" >testtemp1grep
+%printf% "C123D" >.\-testtemp1grep
+%pcre2grep% "123" -- -testtemp1grep >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% "123" testtemp1grep -- -testtemp1grep >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% "123" -- >testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%printf% "E123F" >.\--
+%pcre2grep% -- "123" -- >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 148 ----------------------------->>testtrygrep
+%pcre2grep% --nonexist >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% -n-n-bad >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --context >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --only-matching --output=xx >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --colour=badvalue >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --newline=badvalue >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% -d badvalue >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% -D badvalue >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --buffer-size=0 >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --exclude "(badpat" abc /dev/null >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --exclude-from /non/exist abc /dev/null >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --include-from /non/exist abc /dev/null >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --file-list=/non/exist abc /dev/null >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 149 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --binary-files=binary "dog" ./testdata/grepbinary & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% --binary-files=wrong "dog" ./testdata/grepbinary & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 150 ----------------------------->>testtrygrep
+:: The Unix version of this tests checks for whether locales are supported. On Windows,
+:: we assume they always are.
+set LC_ALL=
+set LC_CTYPE=locale.bad
+(pushd %srcdir% & %pcre2grep% abc /dev/null & popd) >>testtrygrep 2>&1
+echo RC=^%ERRORLEVEL%>>testtrygrep
+set LC_CTYPE=
+
+echo ---------------------------- Test 151 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% --colour=always -e this -e The -e "The wo" testdata/grepinputv & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 152 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -nA3 --group-separator="++" "four" ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 153 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -nA3 --no-group-separator "four" ./testdata/grepinputx & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 154 ----------------------------->>testtrygrep
+echo. >nul 2>testtemp1grep
+(pushd %srcdir% & %pcre2grep% -f %builddir%\testtemp1grep ./testdata/grepinputv & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 155 ----------------------------->>testtrygrep
+echo. >testtemp1grep
+(pushd %srcdir% & %pcre2grep% -f %builddir%\testtemp1grep ./testdata/grepinputv & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 156 ----------------------------->>testtrygrep
+%printf% "\n" >testtemp1grep
+(pushd %srcdir% & %pcre2grep% --posix-pattern-file --file %builddir%\testtemp1grep ./testdata/grepinputv & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 157 ----------------------------->>testtrygrep
+%printf% "spaces \n" >testtemp1grep
+(pushd %srcdir% & %pcre2grep% -o --posix-pattern-file --file=%builddir%\testtemp1grep ./testdata/grepinputv >%builddir%\testtemp2grep && %pcre2grep% -q "s " %builddir%\testtemp2grep & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 158 ----------------------------->>testtrygrep
+%printf% "spaces.\n" >testtemp1grep
+(pushd %srcdir% & %pcre2grep% -f %builddir%\testtemp1grep ./testdata/grepinputv & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 159 ----------------------------->>testtrygrep
+%printf% "spaces.\r\n" >testtemp1grep
+(pushd %srcdir% & %pcre2grep% --posix-pattern-file -f%builddir%\testtemp1grep ./testdata/grepinputv & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 160 ----------------------------->>testtrygrep
+(pushd %srcdir% & %pcre2grep% -nC3 "^(ert|jkl)" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+(pushd %srcdir% & %pcre2grep% -n -B4 -A2 "^(ert|dfg)" ./testdata/grepinput & popd) >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test 161 ----------------------------->>testtrygrep
+%printf% "XfooY\n" >testNinputgrep
+%pcre2grep% --allow-lookaround-bsk -o "(?=foo\K)" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --allow-lookaround-bsk --output "$0" "(?=foo\K)" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --allow-lookaround-bsk --line-offsets "(?=foo\K)" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% --allow-lookaround-bsk --file-offsets "(?=foo\K)" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+:: Now compare the results.
+
+%cf% %srcdir%\testdata\grepoutput testtrygrep %cfout%
+if ERRORLEVEL 1 exit /b 1
+
+
+:: These tests require UTF-8 support
+
+if %utf8% neq 0 (
+ echo Testing pcre2grep UTF-8 features
+
+ echo ---------------------------- Test U1 ------------------------------>testtrygrep
+ (pushd %srcdir% & %pcre2grep% -n -u --newline=any "^X" ./testdata/grepinput8 & popd) >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+
+ echo ---------------------------- Test U2 ------------------------------>>testtrygrep
+ (pushd %srcdir% & %pcre2grep% -n -u -C 3 --newline=any "Match" ./testdata/grepinput8 & popd) >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+
+ echo ---------------------------- Test U3 ------------------------------>>testtrygrep
+ (pushd %srcdir% & %pcre2grep% --line-offsets -u --newline=any --allow-lookaround-bsk "(?<=\K\x{17f})" ./testdata/grepinput8 & popd) >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+
+ echo ---------------------------- Test U4 ------------------------------>>testtrygrep
+ (pushd %srcdir% & %pcre2grep% -u -o "...." ./testdata/grepinputBad8 & popd) >>testtrygrep 2>&1
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+
+ echo ---------------------------- Test U5 ------------------------------>>testtrygrep
+ (pushd %srcdir% & %pcre2grep% -U -o "...." ./testdata/grepinputBad8 & popd) >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+
+ echo ---------------------------- Test U6 ----------------------------->>testtrygrep
+ (pushd %srcdir% & %pcre2grep% -u -m1 -O "=$x{1d3}$o{744}=" "fox" & popd) <%srcdir%\testdata\grepinputv >>testtrygrep 2>&1
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+
+ echo ---------------------------- Test U7 ------------------------------>>testtrygrep
+ (pushd %srcdir% & %pcre2grep% -ui --colour=always "k+|\babc\b" ./testdata/grepinput8 & popd) >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+
+ echo ---------------------------- Test U8 ------------------------------>>testtrygrep
+ (pushd %srcdir% & %pcre2grep% -UiEP --colour=always "k+|\babc\b" ./testdata/grepinput8 & popd) >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+
+ echo ---------------------------- Test U9 ------------------------------>>testtrygrep
+ (pushd %srcdir% & %pcre2grep% -u --colour=always "A\d" ./testdata/grepinput8 & popd) >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+
+ echo ---------------------------- Test U10 ------------------------------>>testtrygrep
+ (pushd %srcdir% & %pcre2grep% -u --posix-digit --colour=always "A\d" ./testdata/grepinput8 & popd) >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+
+ echo ---------------------------- Test U11 ------------------------------>>testtrygrep
+ %printf% "................................................" | %tr% . \200 >testtemp1grep
+ %printf% "x\n" >>testtemp1grep
+ %pcre2grep% --no-jit --buffer-size=16 -U --allow-lookaround-bsk -o "(?<=\K.)" testtemp1grep >>testtrygrep 2>&1
+ echo only-matching RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% --no-jit --buffer-size=16 -U --allow-lookaround-bsk -M "(?<=\K.)" testtemp1grep >>testtrygrep 2>&1
+ echo multiline RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% --no-jit --buffer-size=16 -U --allow-lookaround-bsk --colour=always "(?<=\K.)" testtemp1grep >>testtrygrep 2>&1
+ echo colour RC=^!ERRORLEVEL!>>testtrygrep
+
+ echo ---------------------------- Test U12 ------------------------------>>testtrygrep
+ @REM Colouring only, so the subject is a single line. An empty match at the end
+ @REM of the subject, then one that matches before retrying at the end.
+ %printf% "abc\n" >testtemp1grep
+ %pcre2grep% -n --colour=always -u "$" testtemp1grep >>testtrygrep 2>&1
+ echo colour-empty-at-end RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% -n --colour=always -u ".?" testtemp1grep >>testtrygrep 2>&1
+ echo colour-nonempty-then-empty RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% -n --colour=always -u "^" testtemp1grep >>testtrygrep 2>&1
+ echo colour-empty-at-start RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM An empty line, so the first match is empty with nothing following it, and a
+ @REM final line with no newline, so a restart can reach the end of the line.
+ %printf% "\nabc\n" >testtemp1grep
+ %pcre2grep% -n --colour=always -u ".?" testtemp1grep >>testtrygrep 2>&1
+ echo colour-empty-line RC=^!ERRORLEVEL!>>testtrygrep
+ %printf% "abc" >testtemp1grep
+ %pcre2grep% -n --colour=always -u ".?" testtemp1grep >>testtrygrep 2>&1
+ echo colour-no-final-newline RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM Multiline, where a restart may have to move on to a following line.
+ %printf% "a\nb\n" >testtemp1grep
+ %pcre2grep% -n -M -u "$" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-empty-at-line-end RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% -n -M -u "^" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-empty-at-line-start RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% -n -M -u ".?" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-nonempty-then-empty RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM A match that spans several lines, so that the restart has to skip over more
+ @REM than one line before looking for the next match.
+ %printf% "a\nb\nc\nd\n" >testtemp1grep
+ %pcre2grep% -n -M -u "(?s)a.*c" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-spanning RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% -n -M -u "(?s)a.*c|$" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-spanning-then-empty RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% -n -M --colour=always -u "(?s)a.*c|$" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-colour-spanning RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM Invalid UTF-8 after an empty match, which is when the scan over
+ @REM continuation bytes that follow the restart point can run. Here the scan
+ @REM stops at the start of the next character.
+ %printf% "x\200\200y\n" >testtemp1grep
+ %pcre2grep% -n --colour=always -U "^" testtemp1grep >>testtrygrep 2>&1
+ echo colour-utf-scan-to-char RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% -n -M -U "^" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-utf-scan-to-char RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM The continuation bytes run up to the newline, and then up to the end of the
+ @REM subject, when there is no newline to stop the scan.
+ %printf% "x\200\200\n" >testtemp1grep
+ %pcre2grep% -n --colour=always -U "^" testtemp1grep >>testtrygrep 2>&1
+ echo colour-utf-scan-to-newline RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% -n -M -U "^" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-utf-scan-to-newline RC=^!ERRORLEVEL!>>testtrygrep
+ %printf% "x\200\200" >testtemp1grep
+ %pcre2grep% -n --colour=always -U "^" testtemp1grep >>testtrygrep 2>&1
+ echo colour-utf-scan-to-end RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% -n -M -U "^" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-utf-scan-to-end RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM A subject that is nothing but continuation bytes, so the very first match
+ @REM is empty and the scan immediately reaches the end.
+ %printf% "\200\200" >testtemp1grep
+ %pcre2grep% -n --colour=always -U ".?" testtemp1grep >>testtrygrep 2>&1
+ echo colour-utf-only-continuations RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% -n -M -U ".?" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-utf-only-continuations RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM Continuation bytes at the end of a multi-line subject, reached after an
+ @REM empty match on an earlier line, and after a match that spans lines.
+ %printf% "a\nb\n\n\200\200" >testtemp1grep
+ %pcre2grep% -n -M -U ".?" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-utf-trailing RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% -n -M -U "$" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-utf-trailing-empty RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% -n -M --colour=always -U "(?s)a.*b|$" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-colour-utf-trailing-spanning RC=^!ERRORLEVEL!>>testtrygrep
+
+ echo ---------------------------- Test U13 ------------------------------>>testtrygrep
+ @REM The same restart, but reached by \K rather than by an empty match.
+ %printf% "abc\n" >testtemp1grep
+ %pcre2grep% -n --colour=always -u --allow-lookaround-bsk "(?<=\K.)" testtemp1grep >>testtrygrep 2>&1
+ echo colour-bsk RC=^!ERRORLEVEL!>>testtrygrep
+ %printf% "a\nb\n" >testtemp1grep
+ %pcre2grep% -n -M -u --allow-lookaround-bsk "(?<=\K.)" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-bsk RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM The same, but with the restart landing on invalid UTF-8.
+ %printf% "x\200\200y\n" >testtemp1grep
+ %pcre2grep% --no-jit -n --colour=always -U --allow-lookaround-bsk "(?<=\K.)" testtemp1grep >>testtrygrep 2>&1
+ echo colour-bsk-utf-scan-to-char RC=^!ERRORLEVEL!>>testtrygrep
+ %printf% "x\200\200" >testtemp1grep
+ %pcre2grep% --no-jit -n -M -U --allow-lookaround-bsk "(?<=\K.)" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-bsk-utf-scan-to-end RC=^!ERRORLEVEL!>>testtrygrep
+ %printf% "a\nx\200\200" >testtemp1grep
+ %pcre2grep% --no-jit -n -M --colour=always -U --allow-lookaround-bsk "(?<=\K.)" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-colour-bsk-utf-trailing RC=^!ERRORLEVEL!>>testtrygrep
+
+ echo ---------------------------- Test U14 ------------------------------>>testtrygrep
+
+ @REM A pattern that keeps making progress, so the restart is the ordinary one
+ @REM and the line is never advanced. This is the path the other U14 tests build on.
+ %printf% "abcabc\n" >testtemp1grep
+ %pcre2grep% -n -o -u "a." testtemp1grep >>testtrygrep 2>&1
+ echo control-progress RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM An empty match, which is the case the restart exists for. "$" matches only
+ @REM at the end of the subject, so the restart is immediately at the end; "^"
+ @REM matches at the start, so it has to step forward by one character first.
+ %pcre2grep% -n -o -u "$" testtemp1grep >>testtrygrep 2>&1
+ echo empty-at-end RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% -n -o -u "^" testtemp1grep >>testtrygrep 2>&1
+ echo empty-at-start RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM \K in a lookbehind reports a non-empty match that ends no later than the
+ @REM offset it was started from. PCRE2_NOTEMPTY is set once a match has been
+ @REM found, so this, unlike an empty match, can stop the loop making progress on
+ @REM every iteration and not just the first.
+ %pcre2grep% -n -o -u --allow-lookaround-bsk "(?<=\K.)" testtemp1grep >>testtrygrep 2>&1
+ echo bsk-restart RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM The step forward lands on invalid UTF-8, so the scan over continuation
+ @REM bytes runs. Here it stops at the start of the next character, and then at
+ @REM the newline, both of which are within the subject.
+ %printf% "x\200\200y\n" >testtemp1grep
+ %pcre2grep% --no-jit -n -o -U --allow-lookaround-bsk "(?<=\K.)" testtemp1grep >>testtrygrep 2>&1
+ echo bsk-utf-scan-to-char RC=^!ERRORLEVEL!>>testtrygrep
+ %printf% "x\200\200\n" >testtemp1grep
+ %pcre2grep% --no-jit -n -o -U --allow-lookaround-bsk "(?<=\K.)" testtemp1grep >>testtrygrep 2>&1
+ echo bsk-utf-scan-to-newline RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM The same, but with no newline to stop the scan, so it runs to the end of
+ @REM the subject and then looks at the byte after it.
+ %printf% "x\200\200" >testtemp1grep
+ %pcre2grep% --no-jit -n -o -U --allow-lookaround-bsk "(?<=\K.)" testtemp1grep >>testtrygrep 2>&1
+ echo bsk-utf-scan-to-end RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM Moving on to another line, which only happens in multiline mode. The first
+ @REM match ends exactly at the start of the next line, so the line is advanced
+ @REM and the line number with it; the second ends two lines further on.
+ %printf% "ab\ncd\n" >testtemp1grep
+ %pcre2grep% -n -o -M -u "ab\n" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-line-boundary RC=^!ERRORLEVEL!>>testtrygrep
+ %printf% "ab\ncd\nef\n" >testtemp1grep
+ %pcre2grep% -n -o -M -u "(?s)ab.*ef" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-spanning RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM An empty match in multiline mode, where the step forward is what takes the
+ @REM restart past the end of the line.
+ %printf% "a\nb\n" >testtemp1grep
+ %pcre2grep% -n -o -M -u "$" testtemp1grep >>testtrygrep 2>&1
+ echo multiline-empty RC=^!ERRORLEVEL!>>testtrygrep
+
+ @REM A match that ends between the CR and the LF of a CRLF line ending, so the
+ @REM restart is past the text of the line but short of the start of the next
+ @REM one. Without -M the line is never advanced, so that is the control.
+ @REM These match a CR at the end of a line, which pcre2grep then follows with
+ @REM STDOUT_NL, so the CR has to be unpicked from the line ending to match
+ @REM what RunGrepTest produces. See the -fixcrlf helper in pcre2test.
+ %printf% "ab\r\ncd\r\n" >testtemp1grep
+ %pcre2grep% -n -o -N CRLF "\r" testtemp1grep >>testtrygrep 2>&1
+ echo crlf-not-multiline RC=^!ERRORLEVEL!>>testtrygrep
+ %pcre2grep% -n -o -M -N CRLF "\r" testtemp1grep >testtemp2grep 2>&1
+ set rc=^!ERRORLEVEL!
+ %fixcrlf% >testtrygrep
+ echo crlf-mid-terminator RC=^!rc!>>testtrygrep
+ %pcre2grep% -n -o -M -N ANY "\r" testtemp1grep >testtemp2grep 2>&1
+ set rc=^!ERRORLEVEL!
+ %fixcrlf% >testtrygrep
+ echo any-mid-terminator RC=^!rc!>>testtrygrep
+ %pcre2grep% -M -N CRLF --line-offsets "\r" testtemp1grep >>testtrygrep 2>&1
+ echo crlf-mid-terminator-line-offsets RC=^!ERRORLEVEL!>>testtrygrep
+
+ %cf% %srcdir%\testdata\grepoutput8 testtrygrep %cfout%
+ if ERRORLEVEL 1 exit /b 1
+
+) else (
+ echo Skipping pcre2grep UTF-8 tests: no UTF-8 support in PCRE2 library
+)
+
+
+:: We go to some contortions to try to ensure that the tests for the various
+:: newline settings will work in environments where the normal newline sequence
+:: is not \n. Do not use exported files, whose line endings might be changed.
+:: Instead, create an input file so that its contents are exactly what we want.
+:: These tests are run in the build directory.
+
+echo Testing pcre2grep newline settings
+%printf% "abc\rdef\r\nghi\njkl" >testNinputgrep
+
+echo ---------------------------- Test N1 ------------------------------>testtrygrep
+%pcre2grep% -n -N CR "^(abc|def|ghi|jkl)" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% -B1 -n -N CR "^def" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test N2 ------------------------------>>testtrygrep
+%pcre2grep% -n --newline=crlf "^(abc|def|ghi|jkl)" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% -B1 -n -N CRLF "^ghi" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test N3 ------------------------------>>testtrygrep
+@REM The pattern contains a CR, which for /f keeps, but the command has to be
+@REM read from a file: %printf% starts with a quoted path, and cmd mangles the
+@REM quoting of a command given directly to for /f.
+%printf% "def\rjkl" >testtemp1grep
+for /f %%a in (testtemp1grep) do set pattern=%%a
+%pcre2grep% -n --newline=cr -F "!pattern!" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test N4 ------------------------------>>testtrygrep
+%pcre2grep% -n --newline=crlf -F -f %srcdir%\testdata\greppatN4 testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test N5 ------------------------------>>testtrygrep
+%pcre2grep% -n --newline=any "^(abc|def|ghi|jkl)" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% -B1 -n --newline=any "^def" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test N6 ------------------------------>>testtrygrep
+%pcre2grep% -n --newline=anycrlf "^(abc|def|ghi|jkl)" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% -B1 -n --newline=anycrlf "^jkl" testNinputgrep >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test N7 ------------------------------>>testtrygrep
+%printf% "xyz\0abc\0def" >testNinputgrep
+%pcre2grep% -na --newline=nul "^(abc|def)" testNinputgrep | %tr% \0 @ >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+%pcre2grep% -B1 -na --newline=nul "^(abc|def)" testNinputgrep | %tr% \0 @ >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+echo ---------------------------- Test N8 ------------------------------>>testtrygrep
+%pcre2grep% -na --newline=anycrlf "^a" %srcdir%\testdata\grepinputBad8_Trail >>testtrygrep
+echo RC=^%ERRORLEVEL%>>testtrygrep
+
+%printf% "\n" >>testtrygrep
+
+%cf% %srcdir%\testdata\grepoutputN testtrygrep %cfout%
+if ERRORLEVEL 1 exit /b 1
+
+
+:: These newline tests need UTF support.
+
+if %utf8% neq 0 (
+ echo Testing pcre2grep newline settings with UTF-8 features
+
+ echo ---------------------------- Test UN1 ------------------------------>testtrygrep
+ %pcre2grep% -nau --newline=anycrlf "^(abc|def)" %srcdir%\testdata\grepinputUN >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+
+ echo ---------------------------- Test UN2 ------------------------------>testtrygrep
+ %pcre2grep% -nauU --newline=anycrlf "^a" %srcdir%\testdata\grepinputBad8_Trail >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+
+ %printf% "\n" >>testtrygrep
+
+ %cf% %srcdir%\testdata\grepoutputUN testtrygrep %cfout%
+ if ERRORLEVEL 1 exit /b 1
+
+) else (
+ echo Skipping pcre2grep newline UTF-8 tests: no UTF-8 support in PCRE2 library
+)
+
+
+:: If pcre2grep supports script callouts, run some tests on them. It is possible
+:: to restrict these callouts to the non-fork case, either for security, or for
+:: environments that do not support fork(). This is handled by comparing to a
+:: different output.
+
+%pcre2grep% --help | %pcre2grep% -q "callout scripts in patterns are supported"
+if %ERRORLEVEL% equ 0 (
+ echo Testing pcre2grep script callouts
+
+ echo --- Test 1 --->testtrygrep
+ %pcre2grep% "(T)(..(.))(?C'cmd|/c echo|Arg1: [$1] [$2] [$3]|Arg2: ^$|${1}^$| ($4) ($14) ($0)')()" %srcdir%\testdata\grepinputv >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+ echo --- Test 2 --->>testtrygrep
+ %pcre2grep% "(T)(..(.))()()()()()()()(..)(?C'cmd|/c echo|Arg1: [$11] [${11}]')" %srcdir%\testdata\grepinputv >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+ echo --- Test 3 --->>testtrygrep
+ %pcre2grep% "(T)(?C'|$0:$1$n')" %srcdir%\testdata\grepinputv >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+ echo --- Test 4 --->>testtrygrep
+ %pcre2grep% "(T)(?C'%pcre2test_unquoted%|-printf|%%s\r\n|$0:$1$n')" %srcdir%\testdata\grepinputv >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+ echo --- Test 5 --->>testtrygrep
+ %pcre2grep% "(T)(?C'|$1$n')(*F)" %srcdir%\testdata\grepinputv >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+ echo --- Test 6 --->>testtrygrep
+ %pcre2grep% -m1 "(T)(?C'|$0:$1:$x{41}$o{101}$n')" %srcdir%\testdata\grepinputv >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+
+ %pcre2grep% --help | %pcre2grep% -q "Non-fork callout scripts in patterns are supported"
+ if ^!ERRORLEVEL! equ 0 (
+ set nonfork=1
+ %cf% %srcdir%\testdata\grepoutputCN testtrygrep %cfout%
+ ) else (
+ set nonfork=0
+ %cf% %srcdir%\testdata\grepoutputC testtrygrep %cfout%
+ )
+ if ERRORLEVEL 1 exit /b 1
+
+ @REM These callout tests need UTF support.
+
+ if %utf8% neq 0 (
+ echo Testing pcre2grep script callout with UTF-8 features
+
+ echo --- Test 1 --->testtrygrep
+ %pcre2grep% -u "(T)(?C'|$0:$x{a6}$n')" %srcdir%\testdata\grepinputv >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+ echo --- Test 2 --->>testtrygrep
+ %pcre2grep% -u "(T)(?C'%pcre2test_unquoted%|-printf|%%s\r\n|$0:$x{a6}$n')" %srcdir%\testdata\grepinputv >>testtrygrep
+ echo RC=^!ERRORLEVEL!>>testtrygrep
+
+ if ^!nonfork! equ 1 (
+ %cf% %srcdir%\testdata\grepoutputCNU testtrygrep %cfout%
+ ) else (
+ %cf% %srcdir%\testdata\grepoutputCU testtrygrep %cfout%
+ )
+ if ERRORLEVEL 1 exit /b 1
+
+ ) else (
+ echo Skipping pcre2grep script callout UTF-8 tests: no UTF-8 support in PCRE2 library
+ )
+
+) else (
+ echo Script callouts are not supported
+)
+
+
+:: Finally, some tests to exercise code that is not tested above, just to be
+:: sure that it runs OK. Doing this improves the coverage statistics. The output
+:: is not checked.
+
+echo Testing miscellaneous pcre2grep arguments (unchecked)
+echo. >nul 2>testtrygrep
+call :checkspecial "-xxxxx" 2 || exit /b 1
+call :checkspecial "--help" 0 || exit /b 1
+call :checkspecial "--line-buffered --colour=auto abc nul" 1 || exit /b 1
+call :checkspecial "--line-buffered --color abc nul" 1 || exit /b 1
+call :checkspecial "-dskip abc ." 1 || exit /b 1
+call :checkspecial "-Dread -Dskip abc nul" 1 || exit /b 1
+call :checkspecial "-f %srcdir%\testdata\greplistBad nul" 2 || exit /b 1
+call :checkspecial "(unpaired nul" 2 || exit /b 1
+call :checkspecial "-e (unpaired1 -e (unpaired2 nul" 2 || exit /b 1
+
+
+:: Clean up local working files
+del testcf testNinputgrep teststderrgrep testtrygrep testtemp1grep testtemp2grep -testtemp1grep --
+
+exit /b 0
+
+:: ------ Function to run and check a special pcre2grep arguments test -------
+
+:checkspecial
+ %pcre2grep% %~1 >>testtrygrep 2>&1
+ if %ERRORLEVEL% neq %2 (
+ echo ** pcre2grep %~1 failed - check testtrygrep
+ exit /b 1
+ )
+ exit /b 0
+
+:: End
diff --git a/RunTest b/RunTest
new file mode 100755
index 0000000..306427b
--- /dev/null
+++ b/RunTest
@@ -0,0 +1,1041 @@
+#! /bin/sh
+
+###############################################################################
+# Run the PCRE2 tests using the pcre2test program. The appropriate tests are
+# selected, depending on which build-time options were used.
+#
+# When JIT support is available, all appropriate tests are run with and without
+# JIT, unless "-nojit" is given on the command line. There are also two tests
+# for JIT-specific features, one to be run when JIT support is available
+# (unless "-nojit" is specified), and one when it is not.
+#
+# Whichever of the 8-, 16- and 32-bit libraries exist are tested. It is also
+# possible to select which to test by giving "-8", "-16" or "-32" on the
+# command line.
+#
+# As well as "-nojit", "-8", "-16", and "-32", arguments for this script are
+# individual test numbers, ranges of tests such as 3-6 or 3- (meaning 3 to the
+# end), or a number preceded by ~ to exclude a test. For example, "3-15 ~10"
+# runs tests 3 to 15, excluding test 10, and just "~10" runs all the tests
+# except test 10. Whatever order the arguments are in, these tests are always
+# run in numerical order.
+#
+# If no specific tests are selected (which is the case when this script is run
+# via 'make check') the default is to run all the numbered tests.
+#
+# There may also be named (as well as numbered) tests for special purposes. At
+# present there is just one, called "heap". This test's output contains the
+# sizes of heap frames and frame vectors, which depend on the environment. It
+# is therefore not run unless explicitly requested.
+#
+# Inappropriate tests are automatically skipped (with a comment to say so). For
+# example, if JIT support is not compiled, test 16 is skipped, whereas if JIT
+# support is compiled, test 15 is skipped.
+#
+# Other arguments can be one of the words "-valgrind", "-valgrind-log", or
+# "-sim" followed by an argument to run cross-compiled executables under a
+# simulator, for example:
+#
+# RunTest 3 -sim "qemu-arm -s 8388608"
+#
+# For backwards compatibility, -nojit, -valgrind, -valgrind-log, and -sim may
+# be given without the leading "-" character.
+#
+# When PCRE2 is compiled by clang with -fsanitize arguments, some tests need
+# very much more stack than normal. In environments where the stack can be
+# set at runtime, -bigstack sets a gigantic stack.
+#
+# Special cases where only one argument is allowed:
+# - If the script is invoked as "RunTest list", a list of available tests is
+# output, but none of them are run.
+###############################################################################
+
+# Define test titles in variables so that they can be output as a list. Some
+# of them are modified (e.g. with -8 or -16) when used in the actual tests.
+
+title0="Test 0: Unchecked pcre2test argument tests (to improve coverage)"
+title1="Test 1: Main non-UTF, non-UCP functionality (compatible with Perl >= 5.10)"
+title2="Test 2: API, errors, internals and non-Perl stuff"
+title3="Test 3: Locale-specific features"
+title4A="Test 4: UTF"
+title4B=" and Unicode property support (compatible with Perl >= 5.10)"
+title5A="Test 5: API, internals, and non-Perl stuff for UTF"
+title5B=" and UCP support"
+title6="Test 6: DFA matching main non-UTF, non-UCP functionality"
+title7A="Test 7: DFA matching with UTF"
+title7B=" and Unicode property support"
+title8="Test 8: Internal offsets and code size tests"
+title9="Test 9: Specials for the basic 8-bit library"
+title10="Test 10: Specials for the 8-bit library with UTF-8 and UCP support"
+title11="Test 11: Specials for the basic 16-bit and 32-bit libraries"
+title12="Test 12: Specials for the 16-bit and 32-bit libraries UTF and UCP support"
+title13="Test 13: DFA specials for the basic 16-bit and 32-bit libraries"
+title14="Test 14: DFA specials for UTF and UCP support"
+title15="Test 15: Non-JIT limits and other non-JIT tests"
+title16="Test 16: JIT-specific features when JIT is not available"
+title17="Test 17: JIT-specific features when JIT is available"
+title18="Test 18: Tests of the POSIX interface, excluding UTF/UCP"
+title19="Test 19: Tests of the POSIX interface with UTF/UCP"
+title20="Test 20: Serialization and code copy tests"
+title21="Test 21: \C tests without UTF (supported for DFA matching)"
+title22="Test 22: \C tests with UTF (not supported for DFA matching)"
+title23="Test 23: \C disabled test"
+title24="Test 24: Non-UTF pattern conversion tests"
+title25="Test 25: UTF pattern conversion tests"
+title26="Test 26: Unicode property tests (compatible with Perl >= 5.38)"
+title27="Test 27: Auto-generated unicode property tests"
+title28="Test 28: EBCDIC-specific tests"
+title29="Test 29: EBCDIC-specific tests (for NL=0x25)"
+maxtest=29
+titleheap="Test 'heap': Environment-specific heap tests"
+
+if [ $# -eq 1 -a "$1" = "list" ]; then
+ echo $title0
+ echo $title1
+ echo $title2 "(not UTF or UCP)"
+ echo $title3
+ echo $title4A $title4B
+ echo $title5A $title5B
+ echo $title6
+ echo $title7A $title7B
+ echo $title8
+ echo $title9
+ echo $title10
+ echo $title11
+ echo $title12
+ echo $title13
+ echo $title14
+ echo $title15
+ echo $title16
+ echo $title17
+ echo $title18
+ echo $title19
+ echo $title20
+ echo $title21
+ echo $title22
+ echo $title23
+ echo $title24
+ echo $title25
+ echo $title26
+ echo $title27
+ echo $title28
+ echo $title29
+ echo ""
+ echo $titleheap
+ echo ""
+ echo "Numbered tests are automatically run if nothing selected."
+ echo "Named tests must be explicitly selected."
+ exit 0
+fi
+
+# Set up a suitable "diff" command for comparison. Some systems
+# have a diff that lacks a -u option. Try to deal with this.
+# Use gdiff if available.
+
+cf="diff"
+gdiff /dev/null /dev/null 2>/dev/null && cf="gdiff"
+$cf -u /dev/null /dev/null 2>/dev/null && cf="$cf -u"
+
+# Find the test data
+
+if [ -n "$srcdir" -a -d "$srcdir" ] ; then
+ testdata="$srcdir/testdata"
+elif [ -d "./testdata" ] ; then
+ testdata=./testdata
+elif [ -d "../testdata" ] ; then
+ testdata=../testdata
+else
+ echo "Cannot find the testdata directory"
+ exit 1
+fi
+
+yield=0
+
+
+# ------ Function to check results of a test -------
+
+# This function is called with three parameters:
+#
+# $1 the value of $? after a call to pcre2test
+# $2 the suffix of the output file to compare with
+# $3 the $opt value (empty, -jit, or -dfa)
+#
+# Note: must define using name(), not "function name", for Solaris.
+
+checkresult()
+ {
+ if [ $1 -ne 0 ] ; then
+ echo "** pcre2test failed - check testoutput$bits$3/testoutput$2"
+ yield=1
+ return
+ fi
+ case "$3" in
+ -jit) with=" with JIT";;
+ -dfa) with=" with DFA";;
+ *) with="";;
+ esac
+ cf_out="$testdata/testoutput$2"
+ if [ $ebcdic -eq 1 ] || [ $utf -eq 0 ]; then
+ # We currently only use the #if ... #endif support in pcre2test for tests
+ # which are excluded in certain builds:
+ # - EBCDIC
+ # - No-UTF
+ # Run in "preprocess-only" mode (-E) on the testoutput file to trim
+ # the output lines matching the input lines which are discarded.
+ $sim $pcre2test -q -E "$cf_out" >testoutput$bits$3/testoutput$2-expected
+ cf_out=testoutput$bits$3/testoutput$2-expected
+ fi
+ $cf "$cf_out" testoutput$bits$3/testoutput$2
+ if [ $? != 0 ] ; then
+ echo ""
+ echo "** Test $2 failed$with"
+ yield=1
+ return
+ fi
+ echo " OK$with"
+ }
+
+
+# ------ Function to run and check a special pcre2test arguments test -------
+
+checkspecial()
+ {
+ expect=${2:-0}
+ $sim $valgrind $vjs $pcre2test $1 >>testSoutput 2>&1
+ if [ $? -ne "$expect" ] ; then
+ echo "** pcre2test $1 failed - check testSoutput"
+ yield=1
+ return 1
+ fi
+ return 0
+ }
+
+
+# ------ Test setup ------
+
+# Default values
+
+arg8=
+arg16=
+arg32=
+nojit=
+bigstack=
+malloc=
+sim=
+skip=
+valgrind=
+vjs=
+globalopts="-q"
+: ${pcre2test:=./pcre2test}
+
+# This is in case the caller has set aliases (as I do - PH)
+unset cp ls mv rm
+
+if [ ! -x $pcre2test ] ; then
+ echo "** $pcre2test does not exist or is not executable."
+ exit 1
+fi
+
+# Process options and select which tests to run; for those that are explicitly
+# requested, check that the necessary optional facilities are available.
+
+do0=no
+do1=no
+do2=no
+do3=no
+do4=no
+do5=no
+do6=no
+do7=no
+do8=no
+do9=no
+do10=no
+do11=no
+do12=no
+do13=no
+do14=no
+do15=no
+do16=no
+do17=no
+do18=no
+do19=no
+do20=no
+do21=no
+do22=no
+do23=no
+do24=no
+do25=no
+do26=no
+do27=no
+do28=no
+do29=no
+doheap=no
+
+while [ $# -gt 0 ] ; do
+ case $1 in
+ 0) do0=yes;;
+ 1) do1=yes;;
+ 2) do2=yes;;
+ 3) do3=yes;;
+ 4) do4=yes;;
+ 5) do5=yes;;
+ 6) do6=yes;;
+ 7) do7=yes;;
+ 8) do8=yes;;
+ 9) do9=yes;;
+ 10) do10=yes;;
+ 11) do11=yes;;
+ 12) do12=yes;;
+ 13) do13=yes;;
+ 14) do14=yes;;
+ 15) do15=yes;;
+ 16) do16=yes;;
+ 17) do17=yes;;
+ 18) do18=yes;;
+ 19) do19=yes;;
+ 20) do20=yes;;
+ 21) do21=yes;;
+ 22) do22=yes;;
+ 23) do23=yes;;
+ 24) do24=yes;;
+ 25) do25=yes;;
+ 26) do26=yes;;
+ 27) do27=yes;;
+ 28) do28=yes;;
+ 29) do29=yes;;
+ heap) doheap=yes;;
+ -8) arg8=yes;;
+ -16) arg16=yes;;
+ -32) arg32=yes;;
+ bigstack|-bigstack) bigstack=yes;;
+ malloc|-malloc) malloc=yes;;
+ nojit|-nojit) nojit=yes;;
+ sim|-sim) shift; sim=$1;;
+ valgrind|-valgrind) valgrind="valgrind --tool=memcheck -q --leak-check=yes --errors-for-leak-kinds=all --smc-check=all-non-file --error-exitcode=70";;
+ valgrind-log|-valgrind-log) valgrind="valgrind --tool=memcheck --num-callers=30 --leak-check=yes --errors-for-leak-kinds=all --error-limit=no --smc-check=all-non-file --log-file=report.%p ";;
+ ~*)
+ if expr "$1" : '~[0-9][0-9]*$' >/dev/null; then
+ skip="$skip `expr "$1" : '~\([0-9]*\)*$'`"
+ else
+ echo "Unknown option or test selector '$1'"; exit 1
+ fi
+ ;;
+ *-*)
+ if expr "$1" : '[0-9][0-9]*-[0-9]*$' >/dev/null; then
+ tf=`expr "$1" : '\([0-9]*\)'`
+ tt=`expr "$1" : '.*-\([0-9]*\)'`
+ if [ "$tt" = "" ] ; then tt=$maxtest; fi
+ if expr \( "$tt" ">" "$maxtest" \) >/dev/null; then
+ echo "Invalid test range '$1'"; exit 1
+ fi
+ while expr "$tf" "<=" "$tt" >/dev/null; do
+ eval do${tf}=yes
+ tf=`expr $tf + 1`
+ done
+ else
+ echo "Invalid test range '$1'"; exit 1
+ fi
+ ;;
+ *) echo "Unknown option or test selector '$1'"; exit 1;;
+ esac
+ shift
+done
+
+# If it is possible to set the system stack size and -bigstack was given,
+# set up a large stack.
+
+$sim $pcre2test -S 32 /dev/null /dev/null >/dev/null 2>&1
+support_setstack=$?
+if [ $support_setstack -eq 0 -a "$bigstack" != "" ] ; then
+ globalopts="$globalopts -S 32"
+fi
+
+# If the malloc option is given, then call pcre2test with -malloc.
+
+if [ "$malloc" != "" ] ; then
+ globalopts="$globalopts -malloc"
+fi
+
+# All of 8-bit, 16-bit, and 32-bit character strings may be supported, but only
+# one need be.
+
+$sim $pcre2test -C pcre2-8 >/dev/null
+support8=$?
+$sim $pcre2test -C pcre2-16 >/dev/null
+support16=$?
+$sim $pcre2test -C pcre2-32 >/dev/null
+support32=$?
+
+# \C may be disabled
+
+$sim $pcre2test -C backslash-C >/dev/null
+supportBSC=$?
+
+# Check if compiled in EBCDIC mode, and whether we have EBCDIC I/O and NL=0x25
+$sim $pcre2test -C ebcdic >/dev/null
+ebcdic=$?
+$sim $pcre2test -C ebcdic-io >/dev/null
+ebcdic_io=$?
+$sim $pcre2test -C ebcdic-nl25 >/dev/null
+ebcdic_nl25=$?
+
+if [ $ebcdic -eq 1 ]; then
+ if [ $ebcdic_io -eq 0 ]; then
+ echo "Running tests in EBCDIC mode, and expecting ASCII test data"
+ else
+ echo "Running tests in EBCDIC mode, and expecting EBCDIC test data"
+ echo "If you are on an EBCDIC machine, you will need to convert the PCRE2"
+ echo "testdata/ directory from ISO8859-1, so the data match the EBCDIC"
+ echo "codepage that your C compiler is using for C character literals."
+ echo "For example:"
+ echo " iconv -f ISO8859-1 -t IBM-1047 ..."
+ fi
+fi
+
+# Initialize all bitsizes skipped
+
+test8=skip
+test16=skip
+test32=skip
+
+# If no bitsize arguments, select all that are available
+
+if [ "$arg8$arg16$arg32" = "" ] ; then
+ if [ $support8 -ne 0 ] ; then
+ test8=-8
+ fi
+ if [ $support16 -ne 0 ] ; then
+ test16=-16
+ fi
+ if [ $support32 -ne 0 ] ; then
+ test32=-32
+ fi
+
+# Otherwise, select requested bit sizes
+
+else
+ if [ "$arg8" = yes ] ; then
+ if [ $support8 -eq 0 ] ; then
+ echo "Cannot run 8-bit library tests: 8-bit library not compiled"
+ exit 1
+ fi
+ test8=-8
+ fi
+ if [ "$arg16" = yes ] ; then
+ if [ $support16 -eq 0 ] ; then
+ echo "Cannot run 16-bit library tests: 16-bit library not compiled"
+ exit 1
+ fi
+ test16=-16
+ fi
+ if [ "$arg32" = yes ] ; then
+ if [ $support32 -eq 0 ] ; then
+ echo "Cannot run 32-bit library tests: 32-bit library not compiled"
+ exit 1
+ fi
+ test32=-32
+ fi
+fi
+
+# UTF support is implied by Unicode support, and it always applies to all bit
+# sizes if both are supported; we can't have UTF-8 support without UTF-16 or
+# UTF-32 support.
+
+$sim $pcre2test -C unicode >/dev/null
+utf=$?
+
+# When JIT is used with valgrind, we need to set up valgrind suppressions as
+# otherwise there are a lot of false positive valgrind reports when the
+# the hardware supports SSE2.
+
+jitopt=
+$sim $pcre2test -C jit >/dev/null
+jit=$?
+if [ $jit -ne 0 -a "$nojit" != "yes" ] ; then
+ jitopt=-jit
+ if [ "$valgrind" != "" ] ; then
+ vjs="--suppressions=$testdata/valgrind-jit.supp"
+ fi
+fi
+
+# If no specific tests were requested, select all the numbered tests. Those
+# that are not relevant will be automatically skipped.
+
+if [ $do0 = no -a $do1 = no -a $do2 = no -a $do3 = no -a \
+ $do4 = no -a $do5 = no -a $do6 = no -a $do7 = no -a \
+ $do8 = no -a $do9 = no -a $do10 = no -a $do11 = no -a \
+ $do12 = no -a $do13 = no -a $do14 = no -a $do15 = no -a \
+ $do16 = no -a $do17 = no -a $do18 = no -a $do19 = no -a \
+ $do20 = no -a $do21 = no -a $do22 = no -a $do23 = no -a \
+ $do24 = no -a $do25 = no -a $do26 = no -a $do27 = no -a \
+ $do28 = no -a $do29 = no -a $doheap = no \
+ ]; then
+ do0=yes
+ do1=yes
+ do2=yes
+ do3=yes
+ do4=yes
+ do5=yes
+ do6=yes
+ do7=yes
+ do8=yes
+ do9=yes
+ do10=yes
+ do11=yes
+ do12=yes
+ do13=yes
+ do14=yes
+ do15=yes
+ do16=yes
+ do17=yes
+ do18=yes
+ do19=yes
+ do20=yes
+ do21=yes
+ do22=yes
+ do23=yes
+ do24=yes
+ do25=yes
+ do26=yes
+ do27=yes
+ do28=yes
+ do29=yes
+fi
+
+# Handle any explicit skips at this stage, so that an argument list may consist
+# only of explicit skips.
+
+for i in $skip; do eval do$i=no; done
+
+# Show which release and which test data
+
+echo ""
+echo PCRE2 C library tests using test data from $testdata
+$sim $pcre2test /dev/null
+echo ""
+
+
+# ------ Normal Tests ------
+
+for bmode in "$test8" "$test16" "$test32"; do
+ case "$bmode" in
+ skip) continue;;
+ -16) if [ "$test8$test32" != "skipskip" ] ; then echo ""; fi
+ bits=16; echo "---- Testing 16-bit library ----"; echo "";;
+ -32) if [ "$test8$test16" != "skipskip" ] ; then echo ""; fi
+ bits=32; echo "---- Testing 32-bit library ----"; echo "";;
+ -8) bits=8; echo "---- Testing 8-bit library ----"; echo "";;
+ esac
+
+ # Set up directories for test output.
+ [ -d testoutput$bits ] || mkdir testoutput$bits
+ [ -d testoutput$bits$jitopt ] || mkdir testoutput$bits$jitopt
+ [ -d testoutput$bits-dfa ] || mkdir testoutput$bits-dfa
+
+ # Test 0 is a special test. Its output is not checked, because it will
+ # be different on different hardware and with different configurations.
+ # Running this test just exercises the code.
+
+ if [ $do0 = yes ] ; then
+ echo $title0
+ echo '/abc/jit,memory,framesize' >testSinput
+ echo ' abc' >>testSinput
+ echo '' >testSoutput
+ saverc=0
+ checkspecial "$bmode -C" || saverc=$?
+ checkspecial '--help' || saverc=$?
+ checkspecial "$bmode testSinput" || saverc=$?
+ checkspecial "$bmode $testdata/testinputheap" || saverc=$?
+ if [ $support_setstack -eq 0 ] ; then
+ checkspecial "$bmode -S 1 -t 10 testSinput" || saverc=$?
+ fi
+ checkspecial "$bmode reallydoesnotexist" 1 || saverc=$?
+ checkspecial "$bmode testSinput reallydoesnotexist/outfile" 1 || saverc=$?
+ checkspecial "$bmode -pattern debug testSinput" || saverc=$?
+ checkspecial "$bmode -pattern INVALID testSinput" 1 2>/dev/null || saverc=$?
+ checkspecial "$bmode -subject notempty testSinput" || saverc=$?
+ checkspecial "$bmode -subject INVALID testSinput" 1 2>/dev/null || saverc=$?
+ checkspecial -LM || saverc=$?
+ checkspecial -LP || saverc=$?
+ checkspecial -LS || saverc=$?
+ checkspecial "$bmode -unittest" || saverc=$?
+ if [ $saverc -eq 0 ] ; then
+ echo " OK"
+ fi
+ fi
+
+ # Primary non-UTF test, compatible with JIT and all versions of Perl >= 5.8
+
+ if [ $do1 = yes ] ; then
+ echo $title1
+ for opt in "" $jitopt; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $testdata/testinput1 testoutput$bits$opt/testoutput1
+ checkresult $? 1 "$opt"
+ done
+ fi
+
+ # PCRE2 tests that are not Perl-compatible: API, errors, internals. We copy
+ # the testbtables file to the current directory for use by this test.
+
+ if [ $do2 = yes ] ; then
+ echo $title2 "(excluding UTF-$bits)"
+ cp $testdata/testbtables .
+ for opt in "" $jitopt; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $testdata/testinput2 testoutput$bits$opt/testoutput2
+ saverc=$?
+ if [ $saverc = 0 ] ; then
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt -error -80,-62,-2,-1,0,100,101,191,300 >>testoutput$bits$opt/testoutput2
+ checkresult $? 2 "$opt"
+ else
+ checkresult $saverc 2 "$opt"
+ fi
+ done
+ fi
+
+ # Locale-specific tests, provided that either the "fr_FR", "fr_CA", "french"
+ # or "fr" locale is available. The first two are Unix-like standards; the
+ # last two are for Windows. Unfortunately, different versions of the French
+ # locale give different outputs for some items. This test passes if the
+ # output matches any one of the alternative output files.
+
+ if [ $do3 = yes ] ; then
+ locale=
+
+ # In some environments locales that are listed by the "locale -a"
+ # command do not seem to work with setlocale(). Therefore, we do
+ # a preliminary test to see if pcre2test can set one before going
+ # on to use it.
+
+ for loc in 'fr_FR' 'french' 'fr' 'fr_CA'; do
+ locale -a | grep "^$loc\$" >/dev/null
+ if [ $? -eq 0 ] ; then
+ echo "/a/locale=$loc" | \
+ $sim $valgrind $pcre2test -q $bmode | \
+ grep "Failed to set locale" >/dev/null
+ if [ $? -ne 0 ] ; then
+ locale=$loc
+ if [ "$locale" = "fr_FR" ] ; then
+ infile=$testdata/testinput3
+ outfile=$testdata/testoutput3
+ outfile2=$testdata/testoutput3A
+ outfile3=$testdata/testoutput3B
+ outfile4=$testdata/testoutput3C
+ else
+ infile=test3input
+ outfile=test3output
+ outfile2=test3outputA
+ outfile3=test3outputB
+ outfile4=test3outputC
+ sed "s/fr_FR/$loc/" $testdata/testinput3 >test3input
+ sed "s/fr_FR/$loc/" $testdata/testoutput3 >test3output
+ sed "s/fr_FR/$loc/" $testdata/testoutput3A >test3outputA
+ sed "s/fr_FR/$loc/" $testdata/testoutput3B >test3outputB
+ sed "s/fr_FR/$loc/" $testdata/testoutput3C >test3outputC
+ fi
+ break
+ fi
+ fi
+ done
+
+ if [ "$locale" != "" ] ; then
+ echo $title3 "(using '$locale' locale)"
+ for opt in "" $jitopt; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $infile testoutput$bits/testoutput3
+ if [ $? = 0 ] ; then
+ case "$opt" in
+ -jit) with=" with JIT";;
+ *) with="";;
+ esac
+ if $cf $outfile testoutput$bits/testoutput3 >teststdout || \
+ $cf $outfile2 testoutput$bits/testoutput3 >>teststdout || \
+ $cf $outfile3 testoutput$bits/testoutput3 >>teststdout || \
+ $cf $outfile4 testoutput$bits/testoutput3 >>teststdout
+ then
+ echo " OK$with"
+ else
+ cat teststdout
+ echo ""
+ echo "** Locale test did not run successfully$with. The output did not match"
+ echo " $outfile, $outfile2, $outfile3 or $outfile4."
+ echo " This may mean that there is a problem with the locale settings rather"
+ echo " than a bug in PCRE2."
+ yield=1
+ fi
+ else
+ echo "** pcre2test failed - check testoutput$bits/testoutput3"
+ yield=1
+ fi
+ done
+ else
+ echo "Cannot test locale-specific features - none of the 'fr_FR', 'fr_CA',"
+ echo "'fr' or 'french' locales can be set, or the \"locale\" command is"
+ echo "not available to check for them."
+ echo " "
+ fi
+ fi
+
+ # Tests for UTF and Unicode property support
+
+ if [ $do4 = yes ] ; then
+ echo ${title4A}-${bits}${title4B}
+ if [ $utf -eq 0 ] ; then
+ echo " Skipped because UTF-$bits support is not available"
+ else
+ for opt in "" $jitopt; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $testdata/testinput4 testoutput$bits$opt/testoutput4
+ checkresult $? 4 "$opt"
+ done
+ fi
+ fi
+
+ if [ $do5 = yes ] ; then
+ echo ${title5A}-${bits}$title5B
+ if [ $utf -eq 0 ] ; then
+ echo " Skipped because UTF-$bits support is not available"
+ else
+ for opt in "" $jitopt; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $testdata/testinput5 testoutput$bits$opt/testoutput5
+ checkresult $? 5 "$opt"
+ done
+ fi
+ fi
+
+ # Tests for DFA matching support
+
+ if [ $do6 = yes ] ; then
+ echo $title6
+ $sim $valgrind $pcre2test $globalopts $bmode $testdata/testinput6 testoutput$bits/testoutput6
+ checkresult $? 6 ""
+ fi
+
+ if [ $do7 = yes ] ; then
+ echo ${title7A}-${bits}$title7B
+ if [ $utf -eq 0 ] ; then
+ echo " Skipped because UTF-$bits support is not available"
+ else
+ $sim $valgrind $pcre2test $globalopts $bmode $testdata/testinput7 testoutput$bits/testoutput7
+ checkresult $? 7 ""
+ fi
+ fi
+
+ # Test of internal offsets and code sizes. This test is run only when there
+ # is UTF/UCP support. The actual tests are mostly the same as in some of the
+ # above, but in this test we inspect some offsets and sizes. This is a
+ # doublecheck for the maintainer, just in case something changes unexpectedly.
+ # The output from this test is different in 8-bit, 16-bit, and 32-bit modes
+ # and for different link sizes, so there are different output files for each
+ # mode and link size.
+
+ if [ $do8 = yes ] ; then
+ echo $title8
+ $sim $pcre2test -$bits -C linksize >/dev/null
+ bits_link_size=$?
+ if [ $utf -eq 0 ] ; then
+ echo " Skipped because UTF-$bits support is not available"
+ else
+ $sim $valgrind $pcre2test $globalopts $bmode $testdata/testinput8 testoutput$bits/testoutput8-$bits-$bits_link_size
+ checkresult $? 8-$bits-$bits_link_size ""
+ fi
+ fi
+
+ # Tests for 8-bit-specific features
+
+ if [ "$do9" = yes ] ; then
+ echo $title9
+ if [ "$bits" = "16" -o "$bits" = "32" ] ; then
+ echo " Skipped when running 16/32-bit tests"
+ else
+ for opt in "" $jitopt; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $testdata/testinput9 testoutput$bits$opt/testoutput9
+ checkresult $? 9 "$opt"
+ done
+ fi
+ fi
+
+ # Tests for UTF-8 and UCP 8-bit-specific features
+
+ if [ "$do10" = yes ] ; then
+ echo $title10
+ if [ "$bits" = "16" -o "$bits" = "32" ] ; then
+ echo " Skipped when running 16/32-bit tests"
+ elif [ $utf -eq 0 ] ; then
+ echo " Skipped because UTF-$bits support is not available"
+ else
+ for opt in "" $jitopt; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $testdata/testinput10 testoutput$bits$opt/testoutput10
+ checkresult $? 10 "$opt"
+ done
+ fi
+ fi
+
+ # Tests for 16-bit and 32-bit features. Output is different for the two widths.
+
+ if [ $do11 = yes ] ; then
+ echo $title11
+ if [ "$bits" = "8" ] ; then
+ echo " Skipped when running 8-bit tests"
+ else
+ for opt in "" $jitopt; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $testdata/testinput11 testoutput$bits$opt/testoutput11-$bits
+ checkresult $? 11-$bits "$opt"
+ done
+ fi
+ fi
+
+ # Tests for 16-bit and 32-bit features with UTF-16/32 and UCP support. Output
+ # is different for the two widths.
+
+ if [ $do12 = yes ] ; then
+ echo $title12
+ if [ "$bits" = "8" ] ; then
+ echo " Skipped when running 8-bit tests"
+ elif [ $utf -eq 0 ] ; then
+ echo " Skipped because UTF-$bits support is not available"
+ else
+ for opt in "" $jitopt; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $testdata/testinput12 testoutput$bits$opt/testoutput12-$bits
+ checkresult $? 12-$bits "$opt"
+ done
+ fi
+ fi
+
+ # Tests for 16/32-bit-specific features in DFA non-UTF modes
+
+ if [ $do13 = yes ] ; then
+ echo $title13
+ if [ "$bits" = "8" ] ; then
+ echo " Skipped when running 8-bit tests"
+ else
+ $sim $valgrind $pcre2test $globalopts $bmode $testdata/testinput13 testoutput$bits/testoutput13
+ checkresult $? 13 ""
+ fi
+ fi
+
+ # Tests for DFA UTF and UCP features. Output is different for the different widths.
+
+ if [ $do14 = yes ] ; then
+ echo $title14
+ if [ $utf -eq 0 ] ; then
+ echo " Skipped because UTF-$bits support is not available"
+ else
+ $sim $valgrind $pcre2test $globalopts $bmode $testdata/testinput14 testoutput$bits/testoutput14-$bits
+ checkresult $? 14-$bits ""
+ fi
+ fi
+
+ # Test non-JIT match and recursion limits
+
+ if [ $do15 = yes ] ; then
+ echo $title15
+ $sim $valgrind $pcre2test $globalopts $bmode $testdata/testinput15 testoutput$bits/testoutput15
+ checkresult $? 15 ""
+ fi
+
+ # Test JIT-specific features when JIT is not available
+
+ if [ $do16 = yes ] ; then
+ echo $title16
+ if [ $jit -ne 0 ] ; then
+ echo " Skipped because JIT is available"
+ else
+ $sim $valgrind $pcre2test $globalopts $bmode $testdata/testinput16 testoutput$bits/testoutput16
+ checkresult $? 16 ""
+ fi
+ fi
+
+ # Test JIT-specific features when JIT is available
+
+ if [ $do17 = yes ] ; then
+ echo $title17
+ if [ $jit -eq 0 -o "$nojit" = "yes" ] ; then
+ echo " Skipped because JIT is not available or nojit was specified"
+ else
+ $sim $valgrind $vjs $pcre2test $globalopts $bmode $testdata/testinput17 testoutput$bits/testoutput17
+ checkresult $? 17 ""
+ fi
+ fi
+
+ # Tests for the POSIX interface without UTF/UCP (8-bit only)
+
+ if [ $do18 = yes ] ; then
+ echo $title18
+ if [ "$bits" = "16" -o "$bits" = "32" ] ; then
+ echo " Skipped when running 16/32-bit tests"
+ else
+ $sim $valgrind $pcre2test $globalopts $bmode $testdata/testinput18 testoutput$bits/testoutput18
+ checkresult $? 18 ""
+ fi
+ fi
+
+ # Tests for the POSIX interface with UTF/UCP (8-bit only)
+
+ if [ $do19 = yes ] ; then
+ echo $title19
+ if [ "$bits" = "16" -o "$bits" = "32" ] ; then
+ echo " Skipped when running 16/32-bit tests"
+ elif [ $utf -eq 0 ] ; then
+ echo " Skipped because UTF-$bits support is not available"
+ else
+ $sim $valgrind $pcre2test $globalopts $bmode $testdata/testinput19 testoutput$bits/testoutput19
+ checkresult $? 19 ""
+ fi
+ fi
+
+ # Serialization tests
+
+ if [ $do20 = yes ] ; then
+ echo $title20
+ $sim $valgrind $pcre2test $globalopts $bmode $testdata/testinput20 testoutput$bits/testoutput20
+ checkresult $? 20 ""
+ fi
+
+ # \C tests without UTF - DFA matching is supported
+
+ if [ "$do21" = yes ] ; then
+ echo $title21
+ if [ $supportBSC -eq 0 ] ; then
+ echo " Skipped because \C is disabled"
+ else
+ for opt in "" $jitopt -dfa; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $testdata/testinput21 testoutput$bits$opt/testoutput21
+ checkresult $? 21 "$opt"
+ done
+ fi
+ fi
+
+ # \C tests with UTF - DFA matching is not supported for \C in UTF mode
+
+ if [ "$do22" = yes ] ; then
+ echo $title22
+ if [ $supportBSC -eq 0 ] ; then
+ echo " Skipped because \C is disabled"
+ elif [ $utf -eq 0 ] ; then
+ echo " Skipped because UTF-$bits support is not available"
+ else
+ for opt in "" $jitopt; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $testdata/testinput22 testoutput$bits$opt/testoutput22-$bits
+ checkresult $? 22-$bits "$opt"
+ done
+ fi
+ fi
+
+ # Test when \C is disabled
+
+ if [ "$do23" = yes ] ; then
+ echo $title23
+ if [ $supportBSC -ne 0 ] ; then
+ echo " Skipped because \C is not disabled"
+ else
+ $sim $valgrind $pcre2test $globalopts $bmode $testdata/testinput23 testoutput$bits/testoutput23
+ checkresult $? 23 ""
+ fi
+ fi
+
+ # Non-UTF pattern conversion tests
+
+ if [ "$do24" = yes ] ; then
+ echo $title24
+ $sim $valgrind $pcre2test $globalopts $bmode $testdata/testinput24 testoutput$bits/testoutput24
+ checkresult $? 24 ""
+ fi
+
+ # UTF pattern conversion tests
+
+ if [ "$do25" = yes ] ; then
+ echo $title25
+ if [ $utf -eq 0 ] ; then
+ echo " Skipped because UTF-$bits support is not available"
+ else
+ $sim $valgrind $pcre2test $globalopts $bmode $testdata/testinput25 testoutput$bits/testoutput25
+ checkresult $? 25 ""
+ fi
+ fi
+
+ # Unicode property tests
+
+ if [ $do26 = yes ] ; then
+ echo $title26
+ if [ $utf -eq 0 ] ; then
+ echo " Skipped because UTF-$bits support is not available"
+ else
+ for opt in "" $jitopt; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $testdata/testinput26 testoutput$bits$opt/testoutput26
+ checkresult $? 26 "$opt"
+ done
+ fi
+ fi
+
+ # Auto-generated Unicode property tests
+
+ if [ $do27 = yes ] ; then
+ echo $title27
+ if [ $utf -eq 0 ] ; then
+ echo " Skipped because UTF-$bits support is not available"
+ else
+ for opt in "" $jitopt; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $testdata/testinput27 testoutput$bits$opt/testoutput27
+ checkresult $? 27 "$opt"
+ done
+ fi
+ fi
+
+ # EBCDIC tests
+
+ if [ $do28 = yes ] ; then
+ echo $title28
+ if [ $ebcdic -eq 0 ] ; then
+ echo " Skipped when not targetting EBCDIC"
+ else
+ for opt in "" $jitopt "-dfa"; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $testdata/testinput28 testoutput$bits$opt/testoutput28
+ checkresult $? 28 "$opt"
+ done
+ fi
+ fi
+
+ # EBCDIC tests (for NL=0x25)
+
+ if [ $do29 = yes ] ; then
+ echo $title29
+ if [ $ebcdic -eq 0 ] ; then
+ echo " Skipped when not targetting EBCDIC"
+ elif [ $ebcdic_nl25 -eq 0 ] ; then
+ echo " Skipped because EBCDIC newline is not 0x25"
+ else
+ for opt in "" $jitopt "-dfa"; do
+ $sim $valgrind ${opt:+$vjs} $pcre2test $globalopts $bmode $opt $testdata/testinput29 testoutput$bits$opt/testoutput29
+ checkresult $? 29 "$opt"
+ done
+ fi
+ fi
+
+ # Manually selected heap tests - output may vary in different environments,
+ # which is why that are not automatically run.
+
+ if [ $doheap = yes ] ; then
+ echo $titleheap
+ $sim $valgrind $pcre2test $globalopts $bmode $testdata/testinputheap testoutput$bits/testoutputheap-$bits
+ checkresult $? heap-$bits ""
+ fi
+
+# End of loop for 8/16/32-bit tests
+done
+
+
+if [ $yield -eq 0 ] ; then
+ echo ""
+ echo "All tests passed."
+
+ # Clean up local working files
+ rm -f testbtables testSinput testSoutput test3input test3output test3outputA test3outputB testsaved1 testsaved2 teststdout teststderr
+ rm -rf testoutput8 testoutput8-jit testoutput8-dfa \
+ testoutput16 testoutput16-jit testoutput16-dfa \
+ testoutput32 testoutput32-jit testoutput32-dfa
+else
+ echo ""
+ echo "** Tests failed. See output above for details."
+fi
+
+exit $yield
+
+# End
diff --git a/RunTest.bat b/RunTest.bat
new file mode 100644
index 0000000..f55e5bb
--- /dev/null
+++ b/RunTest.bat
@@ -0,0 +1,603 @@
+@echo off
+@rem
+@rem MS Windows batch file to run pcre2test on testfiles with the correct
+@rem options. This file must use CRLF linebreaks to function properly.
+@rem
+@rem ------------------------ HISTORY ----------------------------------
+@rem This file was originally contributed to PCRE1 by Ralf Junker, and touched
+@rem up by Daniel Richard G. Tests 10-12 added by Philip H.
+@rem Philip H also changed test 3 to use "wintest" files.
+@rem
+@rem Updated by Tom Fortmann to support explicit test numbers on the command
+@rem line. Added argument validation and added error reporting.
+@rem
+@rem Sheri Pierce added logic to skip feature dependent tests
+@rem tests 4 5 7 10 12 14 19 22 25 and 26 require Unicode support
+@rem 8 requires Unicode
+@rem 16 requires absence of jit support
+@rem 17 requires presence of jit support
+@rem Sheri P also added override tests for study and jit testing
+@rem Zoltan Herczeg added libpcre16 support
+@rem Zoltan Herczeg added libpcre32 support
+@rem -------------------------------------------------------------------
+@rem
+@rem The file was converted for PCRE2 by PH, February 2015.
+@rem Updated for new test 14 (moving others up a number), August 2015.
+@rem Tidied and updated for new tests 21, 22, 23 by PH, October 2015.
+@rem PH added missing "set type" for test 22, April 2016.
+@rem PH added copy command for new testbtables file, November 2020
+@rem PH caused it to show comparison output when comparison failed, July 2023
+@rem PH updated unknown error number in test
+
+
+setlocal enabledelayedexpansion
+if [%srcdir%]==[] (
+if exist testdata\ set srcdir=.)
+if [%srcdir%]==[] (
+if exist ..\testdata\ set srcdir=..)
+if [%srcdir%]==[] (
+if exist ..\..\testdata\ set srcdir=..\..)
+if NOT exist %srcdir%\testdata\ (
+echo Error: distribution testdata folder not found!
+call :conferror
+exit /b 1
+goto :eof
+)
+
+if [%pcre2test%]==[] set pcre2test=.\pcre2test.exe
+
+echo source dir is %srcdir%
+echo pcre2test=%pcre2test%
+
+if NOT exist %pcre2test% (
+echo Error: %pcre2test% not found!
+echo.
+call :conferror
+exit /b 1
+)
+
+%pcre2test% -C pcre2-8 >NUL
+set support8=%ERRORLEVEL%
+%pcre2test% -C pcre2-16 >NUL
+set support16=%ERRORLEVEL%
+%pcre2test% -C pcre2-32 >NUL
+set support32=%ERRORLEVEL%
+%pcre2test% -C unicode >NUL
+set unicode=%ERRORLEVEL%
+%pcre2test% -C jit >NUL
+set jit=%ERRORLEVEL%
+%pcre2test% -C backslash-C >NUL
+set supportBSC=%ERRORLEVEL%
+%pcre2test% -C ebcdic >NUL
+set ebcdic=%ERRORLEVEL%
+%pcre2test% -C ebcdic-nl25 >NUL
+set ebcdic_nl25=%ERRORLEVEL%
+
+if %support8% EQU 1 (
+if not exist testout8 md testout8
+if not exist testoutjit8 md testoutjit8
+)
+
+if %support16% EQU 1 (
+if not exist testout16 md testout16
+if not exist testoutjit16 md testoutjit16
+)
+
+if %support32% EQU 1 (
+if not exist testout32 md testout32
+if not exist testoutjit32 md testoutjit32
+)
+
+set do1=no
+set do2=no
+set do3=no
+set do4=no
+set do5=no
+set do6=no
+set do7=no
+set do8=no
+set do9=no
+set do10=no
+set do11=no
+set do12=no
+set do13=no
+set do14=no
+set do15=no
+set do16=no
+set do17=no
+set do18=no
+set do19=no
+set do20=no
+set do21=no
+set do22=no
+set do23=no
+set do24=no
+set do25=no
+set do26=no
+set do27=no
+set do28=no
+set do29=no
+set all=yes
+
+for %%a in (%*) do (
+ set valid=no
+ for %%v in (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29) do if %%v == %%a set valid=yes
+ if "!valid!" == "yes" (
+ set do%%a=yes
+ set all=no
+ ) else (
+ echo Invalid test number - %%a!
+ echo Usage %0 [ test_number ] ...
+ echo Where test_number is one or more optional test numbers 1 through 29, default is all tests.
+ exit /b 1
+ )
+)
+set failed="no"
+
+if "%all%" == "yes" (
+ set do1=yes
+ set do2=yes
+ set do3=yes
+ set do4=yes
+ set do5=yes
+ set do6=yes
+ set do7=yes
+ set do8=yes
+ set do9=yes
+ set do10=yes
+ set do11=yes
+ set do12=yes
+ set do13=yes
+ set do14=yes
+ set do15=yes
+ set do16=yes
+ set do17=yes
+ set do18=yes
+ set do19=yes
+ set do20=yes
+ set do21=yes
+ set do22=yes
+ set do23=yes
+ set do24=yes
+ set do25=yes
+ set do26=yes
+ set do27=yes
+ set do28=yes
+ set do29=yes
+)
+
+@echo RunTest.bat's pcre2test output is written to newly created subfolders
+@echo named testout{8,16,32} and testoutjit{8,16,32}.
+@echo.
+
+set mode=
+set bits=8
+
+:nextMode
+if "%mode%" == "" (
+ if %support8% EQU 0 goto modeSkip
+ echo.
+ echo ---- Testing 8-bit library ----
+ echo.
+)
+if "%mode%" == "-16" (
+ if %support16% EQU 0 goto modeSkip
+ echo.
+ echo ---- Testing 16-bit library ----
+ echo.
+)
+if "%mode%" == "-32" (
+ if %support32% EQU 0 goto modeSkip
+ echo.
+ echo ---- Testing 32-bit library ----
+ echo.
+)
+if "%do1%" == "yes" call :do1
+if "%do2%" == "yes" call :do2
+if "%do3%" == "yes" call :do3
+if "%do4%" == "yes" call :do4
+if "%do5%" == "yes" call :do5
+if "%do6%" == "yes" call :do6
+if "%do7%" == "yes" call :do7
+if "%do8%" == "yes" call :do8
+if "%do9%" == "yes" call :do9
+if "%do10%" == "yes" call :do10
+if "%do11%" == "yes" call :do11
+if "%do12%" == "yes" call :do12
+if "%do13%" == "yes" call :do13
+if "%do14%" == "yes" call :do14
+if "%do15%" == "yes" call :do15
+if "%do16%" == "yes" call :do16
+if "%do17%" == "yes" call :do17
+if "%do18%" == "yes" call :do18
+if "%do19%" == "yes" call :do19
+if "%do20%" == "yes" call :do20
+if "%do21%" == "yes" call :do21
+if "%do22%" == "yes" call :do22
+if "%do23%" == "yes" call :do23
+if "%do24%" == "yes" call :do24
+if "%do25%" == "yes" call :do25
+if "%do26%" == "yes" call :do26
+if "%do27%" == "yes" call :do27
+if "%do28%" == "yes" call :do28
+if "%do29%" == "yes" call :do29
+:modeSkip
+if "%mode%" == "" (
+ set mode=-16
+ set bits=16
+ goto nextMode
+)
+if "%mode%" == "-16" (
+ set mode=-32
+ set bits=32
+ goto nextMode
+)
+
+@rem If mode is -32, testing is finished
+if %failed% == "yes" (
+echo In above output, one or more of the various tests failed!
+exit /b 1
+)
+echo All OK
+goto :eof
+
+:runsub
+@rem Function to execute pcre2test and compare the output
+@rem Arguments are as follows:
+@rem
+@rem 1 = test number
+@rem 2 = outputdir
+@rem 3 = test name use double quotes
+@rem 4 - 9 = pcre2test options
+
+if [%1] == [] (
+ echo Missing test number argument!
+ exit /b 1
+)
+
+if [%2] == [] (
+ echo Missing outputdir!
+ exit /b 1
+)
+
+if [%3] == [] (
+ echo Missing test name argument!
+ exit /b 1
+)
+
+if %1 == 8 (
+ %pcre2test% -%bits% -C linksize >NUL
+ set bits_link_size=!ERRORLEVEL!
+ set outnum=%1-%bits%-!bits_link_size!
+) else if %1 == 11 (
+ set outnum=%1-%bits%
+) else if %1 == 12 (
+ set outnum=%1-%bits%
+) else if %1 == 14 (
+ set outnum=%1-%bits%
+) else if %1 == 22 (
+ set outnum=%1-%bits%
+) else (
+ set outnum=%1
+)
+set testinput=testinput%1
+set testoutput=testoutput%outnum%
+if exist %srcdir%\testdata\win%testinput% (
+ set testinput=wintestinput%1
+ set testoutput=wintestoutput%outnum%
+)
+
+echo Test %1: %3
+%pcre2test% %mode% %4 %5 %6 %7 %8 %9 %srcdir%\testdata\%testinput% >%2%bits%\%testoutput%
+if errorlevel 1 (
+ echo. failed executing command-line:
+ echo. %pcre2test% %mode% %4 %5 %6 %7 %8 %9 %srcdir%\testdata\%testinput% ^>%2%bits%\%testoutput%
+ set failed="yes"
+ goto :eof
+) else if [%1]==[2] (
+ %pcre2test% %mode% %4 %5 %6 %7 %8 %9 -error -80,-62,-2,-1,0,100,101,191,300 >>%2%bits%\%testoutput%
+)
+
+set testexpected=%srcdir%\testdata\%testoutput%
+
+if %ebcdic% EQU 1 (
+ @rem We currently only use the #if ... #endif support in pcre2test for EBCDIC
+ @rem testing. Run in "preprocess-only" mode (-E) on the testoutput file to trim
+ @rem the output lines matching the input lines which are discarded.
+ %pcre2test% -q -E %testexpected% >%2%bits%\%testoutput%-trimmed
+ set testexpected=%2%bits%\%testoutput%-trimmed
+)
+
+fc /n %testexpected% %2%bits%\%testoutput% >NUL
+
+if errorlevel 1 (
+ echo. failed comparison: fc /n %testexpected% %2%bits%\%testoutput%
+ if [%1]==[3] (
+ echo.
+ echo ** Test 3 failure usually means french locale is not
+ echo ** available on the system, rather than a bug or problem with PCRE2.
+ echo.
+ goto :eof
+)
+ fc /n %testexpected% %2%bits%\%testoutput%
+
+ set failed="yes"
+ goto :eof
+)
+
+echo. Passed.
+goto :eof
+
+:do1
+call :runsub 1 testout "Main non-UTF, non-UCP functionality (Compatible with Perl >= 5.10)" -q
+if %jit% EQU 1 call :runsub 1 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:do2
+ copy /y %srcdir%\testdata\testbtables testbtables
+ call :runsub 2 testout "API, errors, internals, and non-Perl stuff" -q
+ if %jit% EQU 1 call :runsub 2 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:do3
+ call :runsub 3 testout "Locale-specific features" -q
+ if %jit% EQU 1 call :runsub 3 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:do4
+if %unicode% EQU 0 (
+ echo Test 4 Skipped due to absence of Unicode support.
+ goto :eof
+)
+ call :runsub 4 testout "UTF-%bits% and Unicode property support - (Compatible with Perl >= 5.10)" -q
+ if %jit% EQU 1 call :runsub 4 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:do5
+if %unicode% EQU 0 (
+ echo Test 5 Skipped due to absence of Unicode support.
+ goto :eof
+)
+ call :runsub 5 testout "API, internals, and non-Perl stuff for UTF-%bits% and UCP" -q
+ if %jit% EQU 1 call :runsub 5 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:do6
+ call :runsub 6 testout "DFA matching main non-UTF, non-UCP functionality" -q
+goto :eof
+
+:do7
+if %unicode% EQU 0 (
+ echo Test 7 Skipped due to absence of Unicode support.
+ goto :eof
+)
+ call :runsub 7 testout "DFA matching with UTF-%bits% and Unicode property support" -q
+ goto :eof
+
+:do8
+if %unicode% EQU 0 (
+ echo Test 8 Skipped due to absence of Unicode support.
+ goto :eof
+)
+ call :runsub 8 testout "Internal offsets and code size tests" -q
+goto :eof
+
+:do9
+if NOT %bits% EQU 8 (
+ echo Test 9 Skipped when running 16/32-bit tests.
+ goto :eof
+)
+ call :runsub 9 testout "Specials for the basic 8-bit library" -q
+ if %jit% EQU 1 call :runsub 9 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:do10
+if NOT %bits% EQU 8 (
+ echo Test 10 Skipped when running 16/32-bit tests.
+ goto :eof
+)
+if %unicode% EQU 0 (
+ echo Test 10 Skipped due to absence of Unicode support.
+ goto :eof
+)
+ call :runsub 10 testout "Specials for the 8-bit library with Unicode support" -q
+ if %jit% EQU 1 call :runsub 10 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:do11
+if %bits% EQU 8 (
+ echo Test 11 Skipped when running 8-bit tests.
+ goto :eof
+)
+ call :runsub 11 testout "Specials for the basic 16/32-bit library" -q
+ if %jit% EQU 1 call :runsub 11 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:do12
+if %bits% EQU 8 (
+ echo Test 12 Skipped when running 8-bit tests.
+ goto :eof
+)
+if %unicode% EQU 0 (
+ echo Test 12 Skipped due to absence of Unicode support.
+ goto :eof
+)
+ call :runsub 12 testout "Specials for the 16/32-bit library with Unicode support" -q
+ if %jit% EQU 1 call :runsub 12 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:do13
+if %bits% EQU 8 (
+ echo Test 13 Skipped when running 8-bit tests.
+ goto :eof
+)
+ call :runsub 13 testout "DFA specials for the basic 16/32-bit library" -q
+goto :eof
+
+:do14
+if %unicode% EQU 0 (
+ echo Test 14 Skipped due to absence of Unicode support.
+ goto :eof
+)
+ call :runsub 14 testout "DFA specials for UTF and UCP support" -q
+ goto :eof
+
+:do15
+call :runsub 15 testout "Non-JIT limits and other non_JIT tests" -q
+goto :eof
+
+:do16
+if %jit% EQU 1 (
+ echo Test 16 Skipped due to presence of JIT support.
+ goto :eof
+)
+ call :runsub 16 testout "JIT-specific features when JIT is not available" -q
+goto :eof
+
+:do17
+if %jit% EQU 0 (
+ echo Test 17 Skipped due to absence of JIT support.
+ goto :eof
+)
+ call :runsub 17 testout "JIT-specific features when JIT is available" -q
+goto :eof
+
+:do18
+if %bits% EQU 16 (
+ echo Test 18 Skipped when running 16-bit tests.
+ goto :eof
+)
+if %bits% EQU 32 (
+ echo Test 18 Skipped when running 32-bit tests.
+ goto :eof
+)
+ call :runsub 18 testout "POSIX interface, excluding UTF-8 and UCP" -q
+goto :eof
+
+:do19
+if %bits% EQU 16 (
+ echo Test 19 Skipped when running 16-bit tests.
+ goto :eof
+)
+if %bits% EQU 32 (
+ echo Test 19 Skipped when running 32-bit tests.
+ goto :eof
+)
+if %unicode% EQU 0 (
+ echo Test 19 Skipped due to absence of Unicode support.
+ goto :eof
+)
+ call :runsub 19 testout "POSIX interface with UTF-8 and UCP" -q
+goto :eof
+
+:do20
+call :runsub 20 testout "Serialization tests" -q
+goto :eof
+
+:do21
+if %supportBSC% EQU 0 (
+ echo Test 21 Skipped due to absence of backslash-C support.
+ goto :eof
+)
+ call :runsub 21 testout "Backslash-C tests without UTF" -q
+ call :runsub 21 testout "Backslash-C tests without UTF (DFA)" -q -dfa
+ if %jit% EQU 1 call :runsub 21 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:do22
+if %supportBSC% EQU 0 (
+ echo Test 22 Skipped due to absence of backslash-C support.
+ goto :eof
+)
+if %unicode% EQU 0 (
+ echo Test 22 Skipped due to absence of Unicode support.
+ goto :eof
+)
+ call :runsub 22 testout "Backslash-C tests with UTF" -q
+ if %jit% EQU 1 call :runsub 22 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:do23
+if %supportBSC% EQU 1 (
+ echo Test 23 Skipped due to presence of backslash-C support.
+ goto :eof
+)
+ call :runsub 23 testout "Backslash-C disabled test" -q
+goto :eof
+
+:do24
+call :runsub 24 testout "Non-UTF pattern conversion tests" -q
+goto :eof
+
+:do25
+if %unicode% EQU 0 (
+ echo Test 25 Skipped due to absence of Unicode support.
+ goto :eof
+)
+ call :runsub 25 testout "UTF pattern conversion tests" -q
+goto :eof
+
+:do26
+if %unicode% EQU 0 (
+ echo Test 26 Skipped due to absence of Unicode support.
+ goto :eof
+)
+ call :runsub 26 testout "Unicode property tests (Compatible with Perl >= 5.38)" -q
+ if %jit% EQU 1 call :runsub 26 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:do27
+if %unicode% EQU 0 (
+ echo Test 27 Skipped due to absence of Unicode support.
+ goto :eof
+)
+ call :runsub 27 testout "Auto-generated unicode property tests" -q
+ if %jit% EQU 1 call :runsub 27 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:do28
+if %ebcdic% EQU 0 (
+ echo Test 28 Skipped when not targetting EBCDIC.
+ goto :eof
+)
+ call :runsub 28 testout "EBCDIC-specific tests" -q
+ call :runsub 28 testout "EBCDIC-specific tests (DFA)" -q -dfa
+ if %jit% EQU 1 call :runsub 28 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:do29
+if %ebcdic% EQU 0 (
+ echo Test 29 Skipped when not targetting EBCDIC.
+ goto :eof
+)
+if %ebcdic_nl25% EQU 0 (
+ echo Test 29 Skipped because EBCDIC newline is not 0x25.
+ goto :eof
+)
+ call :runsub 29 testout "EBCDIC-specific tests for NL=0x25" -q
+ call :runsub 29 testout "EBCDIC-specific tests for NL=0x25 (DFA)" -q -dfa
+ if %jit% EQU 1 call :runsub 29 testoutjit "Test with JIT Override" -q -jit
+goto :eof
+
+:conferror
+@echo.
+@echo Either your build is incomplete or you have a configuration error.
+@echo.
+@echo If configured with cmake and executed via "make test" or the MSVC "RUN_TESTS"
+@echo project, pcre2_test.bat defines variables and automatically calls RunTest.bat.
+@echo For manual testing of all available features, after configuring with cmake
+@echo and building, you can run the built pcre2_test.bat. For best results with
+@echo cmake builds and tests avoid directories with full path names that include
+@echo spaces for source or build.
+@echo.
+@echo Otherwise, if the build dir is in a subdir of the source dir, testdata needed
+@echo for input and verification should be found automatically when (from the
+@echo location of the the built exes) you call RunTest.bat. By default RunTest.bat
+@echo runs all tests compatible with the linked pcre2 library but it can be given
+@echo a test number as an argument.
+@echo.
+@echo If the build dir is not under the source dir you can either copy your exes
+@echo to the source folder or copy RunTest.bat and the testdata folder to the
+@echo location of your built exes and then run RunTest.bat.
+@echo.
+goto :eof
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..b5dba4f
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,90 @@
+Security policies
+=================
+
+Release security
+----------------
+
+The PCRE2 project provides source-only releases, with no binaries.
+
+These source releases can be downloaded from the
+[GitHub Releases](https://github.com/PCRE2Project/pcre2/releases) page. Each
+release file is GPG-signed.
+
+* Releases up to and including 10.44 are signed by Philip Hazel (GPG key:
+ 45F68D54BBE23FB3039B46E59766E084FB0F43D8)
+* Releases from 10.45 onwards will be signed by Nicholas Wilson (GPG key:
+ A95536204A3BB489715231282A98E77EB6F24CA8, cross-signed by Philip
+ Hazel's key for release continuity)
+
+From releases 10.45 onwards, the source code will additionally be provided via
+Git checkout of the (GPG-signed) release tag.
+
+Please contact the maintainers for any queries about release integrity or the
+project's supply-chain.
+
+Support lifecycle
+-----------------
+
+See the documentation under [SUPPORT-LIFECYCLE](./SUPPORT-LIFECYCLE.md) for
+details on how to distribute versions of PCRE2 older than the latest, with
+backported security and high-severity bug fixes.
+
+Reporting vulnerabilities
+-------------------------
+
+The PCRE2 project prioritises security. We appreciate third-party testing and
+security research, and would be grateful if you could responsibly disclose your
+findings to us. We will make every effort to acknowledge your contributions.
+
+To report a security issue, please use the GitHub Security Advisory
+["Report a Vulnerability"](https://github.com/PCRE2Project/pcre2/security/advisories/new)
+tab. (Alternatively, if you prefer you may send a GPG-encrypted email to one of
+the maintainers.)
+
+### Timeline
+
+As a very small volunteer team, we cannot guarantee rapid response, but would
+aim to respond within 1 week, or perhaps 2 during holidays.
+
+### Response procedure
+
+PCRE2 has in the past made rapid releases in response to security incidents.
+
+We have never produced an embargoed release, or provided preferential
+access to security fixes to any clients.
+
+We would aim to notify security managers from trusted downstream distributors,
+such as major Linux distributions, via the `pcre2-dev` mailing list, by
+publicly signalling an upcoming security release before disclosing the
+vulnerability publicly, where advance notification is possible.
+
+Previous vulnerabilities
+------------------------
+
+* GHSA-2p8c-ff85-vh9x (July 2026). Affects 10.47 and earlier, and is fixed
+ in 10.48.
+* GHSA-3r4p-g7gg-ppmf (July 2026). Affects 10.32-10.47, and is fixed in 10.48.
+* GHSA-q8g2-wprr-34m9 (May 2026). Affects 10.30-10.47, and is fixed in 10.48.
+* GHSA-9qww-pwc4-77qq (May 2026). Affects 10.34-10.47, and is fixed in 10.48.
+* GHSA-fmgr-6ggq-9859 (January 2026). Affects 10.47 and earlier, and is fixed
+ in 10.48.
+* GHSA-q7rw-r7qq-2hx6 (October 2025). Affects 10.45 and later, and is fixed in
+ 10.48.
+* CVE-2025-58050 [GHSA-c2gv-xgf5-5cc2] (August 2025). Affects 10.45 only (not
+ earlier), and is fixed in 10.46.
+* CVE-2022-41409 (July 2023). Only affects test code; no expected impact. Fixed
+ in 10.41.
+* CVE-2022-1587 and CVE-2022-1586 (May 2020). Affect versions before 10.40, and
+ fixed in 10.40.
+* CVE-2019-20454 (February 2020). Affects versions 10.31 to 10.33, and is fixed
+ in 10.34.
+* CVE-2017-8786 (May 2017). Only affects test code. Fixed in 10.30.
+* CVE-2017-8399 (May 2017). High severity. Fixed in 10.30.
+* CVE-2017-7186 (March 2017). Fixed in 10.30.
+* CVE-2016-3191 (March 2016). High severity. Fixed in 10.22.
+* CVE-2015-8381, CVE-2015-3217 and CVE-2015-3210 (December 2015). High severity.
+ Fixed in 10.20.
+
+Common Platform Enumeration (CPE) names:
+* CPE name version 2.3: `cpe:2.3:a:pcre:pcre2:-:*:*:*:*:*:*:*`
+* CPE name version 2.2: `cpe:/a:pcre:pcre2:-`
diff --git a/SUPPORT-LIFECYCLE.md b/SUPPORT-LIFECYCLE.md
new file mode 100644
index 0000000..a4ff17f
--- /dev/null
+++ b/SUPPORT-LIFECYCLE.md
@@ -0,0 +1,432 @@
+# PCRE2 Support Lifecycle
+
+This document outlines the support lifecycle policy for PCRE2 releases. It is
+intended to provide clear guidance to distributors on the supported versions of
+PCRE2, and the actions required to distribute older versions of PCRE2 securely.
+
+## Release policy
+
+PCRE2 releases follow a rolling version policy. There is one linear history of
+releases, with each new release providing a mixture of enhancements and fixes to
+the previous release.
+
+PCRE2 is designed to have a high level of backwards-compatibility and stability.
+Where possible, we recommend that consumers of the library update to the latest
+version.
+
+However, we recognise that Linux distributions in particular bundle older
+versions for many years. To enable this practice, this document provides advice
+on how to package and distribute older releases of PCRE2.
+
+This document will be updated with each new PCRE2 release to reflect the current
+support status and any new lifecycle recommendations.
+
+## Actions for PCRE2 distributors and packagers
+
+* Check this document on each release of PCRE2.
+* Each version of PCRE2 that you are supporting should be listed here.
+* Check for changes in that version's "backports to apply" section. Apply
+ commits from the release branch according to your distribution's backporting
+ criteria.
+
+The patches are made available in two ways:
+
+* For tarball-based workflows, I am including the dump of the commits
+ containing the changes to be backported. These flat files record the
+ canonical changes, but may require adaptation to an old release.
+
+* For git-based workflows (preferable), I am publishing a release branch for
+ each release - for example, `release/pcre2-10.47`. This branch will always
+ be ahead of the `pcre2-10.47` release tag, and the additional commits
+ consist of the cherry-picked commits, with approved and tested conflict
+ resolutions applied.
+
+ To apply all recommended commits for a release, fetch its branch and
+ merge (or cherry-pick) the commits after the release tag.
+
+## Support Policy
+
+1. Each PCRE2 version will be supported for at least 5 years from its release
+ date.
+2. Selected releases older than 5 years may continue to receive support if they
+ are actively distributed.
+3. For supported versions, security and high-severity bug fixes will be
+ backported and listed in this document.
+
+The following distributions have been considered to determine support
+requirements:
+
+- RHEL/CentOS/Fedora: Long lifecycle. Although it's listed at 10+ years, there
+ is effectively a freeze after five years of "Full Support", with presumably only
+ CVE fixes being backported after that during "Maintenance Support".
+
+ Packages: https://src.fedoraproject.org/rpms/pcre2
+
+ Packages: https://gitlab.com/redhat/centos-stream/rpms/pcre2
+
+- Debian: Five year lifecycle. There is a three-year period of full support. In
+ practice, backports to "oldoldstable" releases are made only if absolutely
+ required, such as a CVE that requires fixing for compliance reasons. The
+ "stable" and "oldstable" releases actively accumulate backported fixes.
+
+ Packages: https://tracker.debian.org/pkg/pcre2
+
+- Ubuntu: Five year LTS. I believe most customers update fairly promptly every
+ two years, and few if any non-security backports are made to LTS releases
+ older than the current one.
+
+ Packages: https://code.launchpad.net/ubuntu/+source/pcre2
+
+- Alpine: Two year lifecycle.
+
+ Packages: https://gitlab.alpinelinux.org/alpine/aports/-/tree/master/main/pcre2?ref_type=heads
+
+- SUSE: Extremely long lifecycle; PCRE2 will stop backporting fixes long before
+ SUSE drops support.
+
+ Packages: https://build.opensuse.org/package/show/openSUSE:Factory/pcre2
+
+- Arch: Rolling release. No need for backports. However, it is a major upstream
+ packaging source for the Arch-based ecosystem.
+
+ Packages: https://gitlab.archlinux.org/archlinux/packaging/packages/pcre2
+
+- Other notable primary packaging sources include:
+ * Gentoo
+
+ https://gitweb.gentoo.org/repo/gentoo.git/tree/dev-libs/libpcre2
+
+ * NixOS
+
+ https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/libraries/pcre2/default.nix
+
+Please contact us if you would like the PCRE2 maintainers to be aware of your
+packages, particularly if you are a distributor of PCRE2, and provide a support
+lifecycle for old (not-latest) PCRE2 releases.
+
+## Supported Versions
+
+Below is the list of PCRE2 versions supported by upstream distributors. For
+each version, specific recommendations and backported fixes (if any) are
+provided.
+
+### PCRE2 10.23 14-February-2017
+
+* Shipped in RHEL 7 (paid Extended Life Cycle Support ends 31 May 2029).
+
+I am not providing a recommendation of what patches to apply. This release is
+beyond PCRE2's standard five-year support period and is maintained only through
+an extended-support programme.
+
+### PCRE2 10.31 12-February-2018
+
+* Shipped in Ubuntu 18.04 "Bionic Beaver" (Expanded Security Maintenance ends
+ April 2028).
+* Shipped in SUSE Linux Enterprise Server 15 SP1, SP2 and SP3 (paid LTSS
+ Reactive support ends 31 January 2027, 31 December 2027 and 31 December
+ 2028, respectively).
+
+I am not providing a recommendation of what patches to apply. These releases
+are beyond PCRE2's standard five-year support period and are maintained only
+through extended-support programmes.
+
+### PCRE2 10.32 10-September-2018
+
+* Shipped in RHEL 8 (Maintenance Support ends 31 May 2029; paid Extended Life
+ Cycle support ends 31 May 2033).
+
+This version is older than 5 years, but remains listed in SUPPORT-LIFECYCLE.md
+potentially until May 2029 (end of "Maintenance Support" for RHEL 8), in
+recognition that customer workloads may be using this version until then.
+
+I am not providing a recommendation of what patches to apply. Distributors still
+shipping this release have likely frozen their codebase at this point.
+
+For the record, RHEL 8 used the following sets of patches:
+https://src.fedoraproject.org/rpms/pcre2/tree/f28,
+https://gitlab.com/redhat/centos-stream/rpms/pcre2/-/tree/c8s?ref_type=heads
+
+The most serious of these was the backported mitigation for CVE-2019-20454 from
+the fix in 10.34.
+
+### PCRE2 10.34 21-November-2019
+
+* Shipped in Ubuntu 20.04 "Focal Fossa" (Expanded Security Maintenance ends
+ April 2030).
+* Shipped in SUSE Linux Enterprise Server 12 SP5 (paid LTSS ends 31 October
+ 2027).
+
+I am not providing a recommendation of what patches to apply. These releases
+are beyond PCRE2's standard five-year support period and are maintained only
+through extended-support programmes.
+
+### PCRE2 10.36 04-December-2020
+
+* Shipped in Debian 11 "Bullseye" (EOL 31 Aug 2026).
+
+I am not providing a recommendation of what patches to apply. Distributors still
+shipping this release have likely frozen their codebase at this point, since the
+release of Debian 12.
+
+### PCRE2 10.37 26-May-2021
+
+I am not providing a recommendation of what patches to apply. I am not aware of
+any Linux distributions providing extended support for 10.37. I have not tested
+this release with any backported fixes applied.
+
+Patches introduced:
+* `patches/pcre2-10.37-Remove-real-POSIX.patch`: To be backported to older
+ versions as required. This changes a behaviour which has been present since
+ the beginning of PCRE2's libpcre2posix.so, although the behaviour was updated
+ in 10.33. Versions prior to 10.33 cannot benefit from the backport; versions
+ 10.33-10.36 may use the backport at the distributor's discretion (that is, if
+ users have requested it; but it is not needed otherwise).
+
+### PCRE2 10.38 01-October-2021
+
+Do not use (update to 10.39).
+
+### PCRE2 10.39 29-October-2021
+
+* Shipped in Ubuntu 22.04 "Jammy Jellyfish" (EOL 01 Apr 2027).
+* Shipped in SUSE Linux Enterprise Server 15 SP4 and SP5 (paid LTSS ends 31
+ December 2026 and 31 December 2027, respectively).
+
+Backports to apply:
+* `patches/pcre2-10.40-A-Fixed-a-unicode.patch`
+* `patches/pcre2-10.40-B-Fixed-an-issue-affecting.patch`
+* `patches/pcre2-10.48-Fix-JIT-match-context-reuse.patch`
+* `patches/pcre2-10.48-Check-JIT-mode-before-validation.patch`
+* `patches/pcre2-10.48-Fix-allocation-byte-sizing.patch`
+* `patches/pcre2-10.48-Fix-invalid-UTF-backwards-scans.patch`
+* `patches/pcre2-10.48-Fix-compiler-integer-overflows.patch`
+* `patches/pcre2-10.48-Fix-DFA-workspace-overflows.patch`
+
+Patches introduced:
+* `patches/pcre2-10.39-Fix-incorrect-detection.patch`: Significant bugfix for
+ JIT matching
+
+### PCRE2 10.40 15-April-2022
+
+* Shipped in RHEL 9 (Full Support ends 31 May 2027; Maintenance Support ends 31
+ May 2032; paid Extended Life Cycle support ends 31 May 2036).
+* Shipped in CentOS Stream 9 (EOL 31 May 2027).
+
+Backports to apply:
+* `patches/pcre2-10.48-Fix-JIT-match-context-reuse.patch`
+* `patches/pcre2-10.48-Check-JIT-mode-before-validation.patch`
+* `patches/pcre2-10.48-Fix-allocation-byte-sizing.patch`
+* `patches/pcre2-10.48-Fix-invalid-UTF-backwards-scans.patch`
+* `patches/pcre2-10.48-Fix-compiler-integer-overflows.patch`
+* `patches/pcre2-10.48-Fix-DFA-workspace-overflows.patch`
+
+For the record, RHEL/CentOS 9 ships rather more backported patches than other
+distributions:
+https://gitlab.com/redhat/centos-stream/rpms/pcre2/-/tree/c9s?ref_type=heads
+
+Some of these patches may be relevant to other distributions, but I have not
+tested them myself for compatibility with 10.40 or other earlier releases.
+
+Patches introduced:
+* `patches/pcre2-10.40-A-Fixed-a-unicode.patch`: Fixed CVE-2022-1586. This
+ should be assumed to affect all previous versions of PCRE2 (lower bound of
+ affected releases unconfirmed).
+* `patches/pcre2-10.40-B-Fixed-an-issue-affecting.patch`: Fixed CVE-2022-1587.
+ This should be assumed to affect all previous versions of PCRE2 (lower bound
+ of affected releases unconfirmed).
+
+### PCRE2 10.41 06-December-2022
+
+Do not use (update to 10.42).
+
+Introduced the fix for CVE-2022-41409. This only affects the pcre2test runner
+for the test suite, so this fix is not backported.
+
+### PCRE2 10.42 11-December-2022
+
+* Shipped in Debian 12 "Bookworm" (EOL 30 Jun 2028).
+* Shipped in Ubuntu 24.04 "Noble Numbat" (EOL 31 May 2029).
+* Shipped in SUSE Linux Enterprise Server 15 SP6 and SP7 (paid LTSS ends 31
+ December 2028 and general support ends 31 July 2031, respectively).
+
+Users on RISC-V are advised to update to 10.43, or not use the JIT unless using
+a backport for https://github.com/zherczeg/sljit/pull/223. Given the small
+RISC-V userbase (especially on older releases), disabling the JIT for RISC-V
+builds is likely acceptable.
+
+Backports to apply:
+* `patches/pcre2-10.43-Avoid-LIMIT_HEAP-integer.patch`
+* `patches/pcre2-10.43-Fix-heapframe-overflow.patch`
+* `patches/pcre2-10.48-Fix-JIT-match-context-reuse.patch`
+* `patches/pcre2-10.48-Check-JIT-mode-before-validation.patch`
+* `patches/pcre2-10.48-Fix-allocation-byte-sizing.patch`
+* `patches/pcre2-10.48-Fix-invalid-UTF-backwards-scans.patch`
+* `patches/pcre2-10.48-Fix-compiler-integer-overflows.patch`
+* `patches/pcre2-10.48-Fix-DFA-workspace-overflows.patch`
+
+### PCRE2 10.43 16-February-2024
+
+* Shipped in Alpine 3.21 (EOL 01 Nov 2026).
+
+Backports to apply:
+* `patches/pcre2-10.44-Fix-locking-region.patch`
+* `patches/pcre2-10.44-Fix-incorrect-compiling.patch`
+* `patches/pcre2-10.48-Fix-JIT-STR_END.patch`
+* `patches/pcre2-10.48-Fix-JIT-match-context-reuse.patch`
+* `patches/pcre2-10.48-Check-JIT-mode-before-validation.patch`
+* `patches/pcre2-10.48-Fix-allocation-byte-sizing.patch`
+* `patches/pcre2-10.48-Fix-invalid-UTF-backwards-scans.patch`
+* `patches/pcre2-10.48-Fix-compiler-integer-overflows.patch`
+* `patches/pcre2-10.48-Fix-DFA-workspace-overflows.patch`
+
+Patches introduced:
+* `patches/pcre2-10.43-Avoid-LIMIT_HEAP-integer.patch`: Fix integer overflow in
+ handling of LIMIT_HEAP. This is not a critical fix for backporting, and in
+ 10.41, the code for handling the heapframes changed to always using a
+ heap-allocated frames vector. This patch is therefore recommended for
+ backporting to 10.42 only.
+* `patches/pcre2-10.43-Fix-heapframe-overflow.patch`: Fix buffer overrun in
+ handling of LIMIT_HEAP. The regression was introduced in d90fb238 in PCRE2
+ 10.41, so the patch is for backporting to 10.41-42.
+
+### PCRE2 10.44 07-June-2024
+
+* Shipped in RHEL 10 (Full Support ends 31 May 2030; Maintenance Support ends
+ 31 May 2035; paid Extended Life Cycle support ends 31 May 2039).
+* Shipped in CentOS Stream 10 (EOL 31 May 2030).
+
+Backports to apply:
+* `patches/pcre2-10.45-Memory-reports-only-compiled.patch`
+* `patches/pcre2-10.48-Fix-JIT-STR_END.patch`
+* `patches/pcre2-10.48-Fix-JIT-match-context-reuse.patch`
+* `patches/pcre2-10.48-Check-JIT-mode-before-validation.patch`
+* `patches/pcre2-10.48-Fix-allocation-byte-sizing.patch`
+* `patches/pcre2-10.48-Fix-invalid-UTF-backwards-scans.patch`
+* `patches/pcre2-10.48-Fix-compiler-integer-overflows.patch`
+* `patches/pcre2-10.48-Fix-DFA-workspace-overflows.patch`
+
+Patches introduced:
+* `patches/pcre2-10.44-Fix-locking-region.patch`: To be backported to 10.43 only
+ (bug introduced in 10.43). Crashes in multithreaded applications using the PCRE2
+ JIT were likely in 10.43 without this patch.
+* `patches/pcre2-10.44-Fix-incorrect-compiling.patch`: Fixes a bug causing
+ incorrect compilation of certain patterns which could crashes, for backporting
+ to 10.43. Because 10.42 and earlier required fixed-length lookbehinds, the
+ patch does not require backporting to earlier versions.
+
+### PCRE2 10.45 05-February-2025
+
+* Shipped in openSUSE Leap 16.0 (EOL 31 October 2027).
+* Shipped in SUSE Linux Enterprise Server 16.0 (general support ends 30
+ November 2027).
+
+Do not use (update to 10.46, which is is a drop-in compatible release with a
+security fix).
+
+Patches introduced:
+* `patches/pcre2-10.45-Memory-reports-only-compiled.patch`: To be backported to
+ 10.44 only. This is a test-only fix, so is not important to backport unless
+ test suite failures are observed.
+
+### PCRE2 10.46 27-August-2025
+
+* Shipped in Debian 13 "Trixie" (EOL 30 Jun 2030).
+* Shipped in Ubuntu 26.04 "Resolute Raccoon" (EOL 30 April 2031).
+* Shipped in Alpine 3.22 (EOL 01 May 2027).
+* Shipped in NixOS 26.05 (EOL 31 December 2026).
+
+Introduced the fix for CVE-2025-58050. This only affects 10.45. Do not backport
+the patch (just update to 10.46).
+
+Backports to apply:
+* `patches/pcre2-10.47-Fix-for-callback.patch`
+* `patches/pcre2-10.48-Write-serialization-padding.patch`
+* `patches/pcre2-10.48-Fix-character-list-generator.patch`
+* `patches/pcre2-10.48-Fix-scan-prefix-repeat-reset.patch`
+* `patches/pcre2-10.48-Fix-JIT-STR_END.patch`
+* `patches/pcre2-10.48-Fix-JIT-match-context-reuse.patch`
+* `patches/pcre2-10.48-Check-JIT-mode-before-validation.patch`
+* `patches/pcre2-10.48-Fix-allocation-byte-sizing.patch`
+* `patches/pcre2-10.48-Fix-invalid-UTF-backwards-scans.patch`
+* `patches/pcre2-10.48-Fix-compiler-integer-overflows.patch`
+* `patches/pcre2-10.48-Fix-DFA-workspace-overflows.patch`
+
+### PCRE2 10.47 21-October-2025
+
+* Shipped in Fedora 43 (EOL 09 December 2026) and Fedora 44 (EOL 02 June
+ 2027).
+* Shipped in Alpine 3.23 (EOL 01 November 2027) and Alpine 3.24 (EOL 01 June
+ 2028).
+
+Backports to apply:
+* `patches/pcre2-10.48-Write-serialization-padding.patch`
+* `patches/pcre2-10.48-Fix-character-list-generator.patch`
+* `patches/pcre2-10.48-Fix-repeated-substitute-escapes.patch`
+* `patches/pcre2-10.48-Fix-scan-prefix-repeat-reset.patch`
+* `patches/pcre2-10.48-Fix-JIT-STR_END.patch`
+* `patches/pcre2-10.48-Fix-JIT-match-context-reuse.patch`
+* `patches/pcre2-10.48-Check-JIT-mode-before-validation.patch`
+* `patches/pcre2-10.48-Fix-allocation-byte-sizing.patch`
+* `patches/pcre2-10.48-Keep-escape-error-offset-in-pattern.patch`
+* `patches/pcre2-10.48-Fix-invalid-UTF-backwards-scans.patch`
+* `patches/pcre2-10.48-Fix-compiler-integer-overflows.patch`
+* `patches/pcre2-10.48-Fix-DFA-workspace-overflows.patch`
+
+Patches introduced:
+* `patches/pcre2-10.47-Fix-for-callback.patch`: A fix for a significant memory
+ read overrun in a function rarely called by applications, to be backported to
+ 10.45 and 10.46 only (bug introduced in 10.45).
+* There is a new and rewritten JIT implementation for the AArch64 SIMD code,
+ fixing crashes and out-of-bounds memory reads in the previous, legacy AArch64
+ JIT. This is probably not possible to backport.
+
+### PCRE2 10.48 31-August-2026
+
+Patches introduced:
+* `patches/pcre2-10.48-Write-serialization-padding.patch`: Initializes
+ character-list padding before serialization, preventing a two-byte
+ information disclosure (GHSA-q7rw-r7qq-2hx6). The affected representation
+ was introduced in 10.45; affected releases are 10.45-10.47.
+* `patches/pcre2-10.48-Fix-character-list-generator.patch`: Fixes incorrect
+ compilation and false-negative matches for Unicode character lists around
+ U+0100 and ranges crossing U+00FF. The affected representation was
+ introduced in 10.45; affected releases are 10.45-10.47.
+* `patches/pcre2-10.48-Fix-repeated-substitute-escapes.patch`: Fixes incorrect
+ conditional substitution output and errors after consecutive extended
+ replacement escapes. This regression was introduced in 10.47 and affects
+ 10.47 only.
+* `patches/pcre2-10.48-Fix-scan-prefix-repeat-reset.patch`: Fixes JIT false
+ negatives caused by stale repeat state during prefix scanning. The affected
+ scan-prefix implementation was introduced in 10.45; affected releases are
+ 10.45-10.47.
+* `patches/pcre2-10.48-Fix-JIT-STR_END.patch`: Restores `STR_END` while JIT
+ backtracks through non-atomic variable-length lookbehinds. The affected JIT
+ support was introduced in 10.43; affected releases are 10.43-10.47.
+* `patches/pcre2-10.48-Fix-JIT-match-context-reuse.patch`: Prevents direct
+ `pcre2_jit_match()` reuse from leaking a copied subject, retaining stale
+ ownership state, or freeing caller-owned memory. Copied-subject support was
+ introduced in 10.33; affected releases are 10.33-10.47.
+* `patches/pcre2-10.48-Check-JIT-mode-before-validation.patch`: Checks that the
+ requested JIT mode exists before JIT validation and execution
+ (GHSA-2p8c-ff85-vh9x). The accompanying regression test is part of the same
+ backport series. The affected invalid-UTF fallback was introduced in 10.34;
+ affected releases are 10.34-10.47.
+* `patches/pcre2-10.48-Fix-allocation-byte-sizing.patch`: Uses byte sizes for
+ two allocations and adds overflow checks (GHSA-q8g2-wprr-34m9). One affected
+ allocation has been confirmed as far back as PCRE2 10.00; affected releases
+ are 10.47 and earlier.
+* `patches/pcre2-10.48-Keep-escape-error-offset-in-pattern.patch`: Keeps error
+ offsets within malformed patterns ending in incomplete `\x{`, `\o{`, or
+ `\N{U+` escapes. This regression was introduced in 10.47 and affects 10.47
+ only.
+* `patches/pcre2-10.48-Fix-invalid-UTF-backwards-scans.patch`: Prevents two
+ out-of-bounds reads while scanning backwards through invalid UTF data
+ (GHSA-9qww-pwc4-77qq). Invalid-UTF matching was introduced in 10.34; affected
+ releases are 10.34-10.47.
+* `patches/pcre2-10.48-Fix-compiler-integer-overflows.patch`: Adds bounds checks
+ for several integer overflows while compiling patterns
+ (GHSA-fmgr-6ggq-9859). The affected generic calculations have been confirmed
+ in PCRE2 10.00; affected releases are 10.47 and earlier.
+* `patches/pcre2-10.48-Fix-DFA-workspace-overflows.patch`: Prevents workspace
+ size and offset overflows in DFA matching (GHSA-3r4p-g7gg-ppmf). The affected
+ heap workspace was introduced in 10.32; affected releases are 10.32-10.47.
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..e8154a9
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,1599 @@
+# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
+
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],,
+[m4_warning([this file was generated for autoconf 2.71.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+
+# pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*-
+# serial 12 (pkg-config-0.29.2)
+
+dnl Copyright © 2004 Scott James Remnant .
+dnl Copyright © 2012-2015 Dan Nicholson
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+dnl 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a
+dnl configuration script generated by Autoconf, you may include it under
+dnl the same distribution terms that you use for the rest of that
+dnl program.
+
+dnl PKG_PREREQ(MIN-VERSION)
+dnl -----------------------
+dnl Since: 0.29
+dnl
+dnl Verify that the version of the pkg-config macros are at least
+dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
+dnl installed version of pkg-config, this checks the developer's version
+dnl of pkg.m4 when generating configure.
+dnl
+dnl To ensure that this macro is defined, also add:
+dnl m4_ifndef([PKG_PREREQ],
+dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
+dnl
+dnl See the "Since" comment for each macro you use to see what version
+dnl of the macros you require.
+m4_defun([PKG_PREREQ],
+[m4_define([PKG_MACROS_VERSION], [0.29.2])
+m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
+ [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
+])dnl PKG_PREREQ
+
+dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
+dnl ----------------------------------
+dnl Since: 0.16
+dnl
+dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
+dnl first found in the path. Checks that the version of pkg-config found
+dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
+dnl used since that's the first version where most current features of
+dnl pkg-config existed.
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+fi[]dnl
+])dnl PKG_PROG_PKG_CONFIG
+
+dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------------------------------
+dnl Since: 0.18
+dnl
+dnl Check to see whether a particular set of modules exists. Similar to
+dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
+dnl
+dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+dnl only at the first occurrence in configure.ac, so if the first place
+dnl it's called might be skipped (such as if it is within an "if", you
+dnl have to call PKG_CHECK_EXISTS manually
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_default([$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+dnl ---------------------------------------------
+dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
+dnl pkg_failed based on the result.
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes ],
+ [pkg_failed=yes])
+ else
+ pkg_failed=untried
+fi[]dnl
+])dnl _PKG_CONFIG
+
+dnl _PKG_SHORT_ERRORS_SUPPORTED
+dnl ---------------------------
+dnl Internal check to see if pkg-config supports short errors.
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])dnl _PKG_SHORT_ERRORS_SUPPORTED
+
+
+dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl [ACTION-IF-NOT-FOUND])
+dnl --------------------------------------------------------------
+dnl Since: 0.4.0
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
+dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $2])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ AC_MSG_RESULT([no])
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+ ])
+elif test $pkg_failed = untried; then
+ AC_MSG_RESULT([no])
+ m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see .])[]dnl
+ ])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ $3
+fi[]dnl
+])dnl PKG_CHECK_MODULES
+
+
+dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl [ACTION-IF-NOT-FOUND])
+dnl ---------------------------------------------------------------------
+dnl Since: 0.29
+dnl
+dnl Checks for existence of MODULES and gathers its build flags with
+dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
+dnl and VARIABLE-PREFIX_LIBS from --libs.
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
+dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
+dnl configure.ac.
+AC_DEFUN([PKG_CHECK_MODULES_STATIC],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+_save_PKG_CONFIG=$PKG_CONFIG
+PKG_CONFIG="$PKG_CONFIG --static"
+PKG_CHECK_MODULES($@)
+PKG_CONFIG=$_save_PKG_CONFIG[]dnl
+])dnl PKG_CHECK_MODULES_STATIC
+
+
+dnl PKG_INSTALLDIR([DIRECTORY])
+dnl -------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable pkgconfigdir as the location where a module
+dnl should install pkg-config .pc files. By default the directory is
+dnl $libdir/pkgconfig, but the default can be changed by passing
+dnl DIRECTORY. The user can override through the --with-pkgconfigdir
+dnl parameter.
+AC_DEFUN([PKG_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+ [pkg-config installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([pkgconfigdir],
+ [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
+ [with_pkgconfigdir=]pkg_default)
+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_INSTALLDIR
+
+
+dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
+dnl --------------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable noarch_pkgconfigdir as the location where a
+dnl module should install arch-independent pkg-config .pc files. By
+dnl default the directory is $datadir/pkgconfig, but the default can be
+dnl changed by passing DIRECTORY. The user can override through the
+dnl --with-noarch-pkgconfigdir parameter.
+AC_DEFUN([PKG_NOARCH_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+ [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([noarch-pkgconfigdir],
+ [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
+ [with_noarch_pkgconfigdir=]pkg_default)
+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_NOARCH_INSTALLDIR
+
+
+dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------
+dnl Since: 0.28
+dnl
+dnl Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])dnl PKG_CHECK_VAR
+
+dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND],
+dnl [DESCRIPTION], [DEFAULT])
+dnl ------------------------------------------
+dnl
+dnl Prepare a "--with-" configure option using the lowercase
+dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and
+dnl PKG_CHECK_MODULES in a single macro.
+AC_DEFUN([PKG_WITH_MODULES],
+[
+m4_pushdef([with_arg], m4_tolower([$1]))
+
+m4_pushdef([description],
+ [m4_default([$5], [build with ]with_arg[ support])])
+
+m4_pushdef([def_arg], [m4_default([$6], [auto])])
+m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes])
+m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no])
+
+m4_case(def_arg,
+ [yes],[m4_pushdef([with_without], [--without-]with_arg)],
+ [m4_pushdef([with_without],[--with-]with_arg)])
+
+AC_ARG_WITH(with_arg,
+ AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),,
+ [AS_TR_SH([with_]with_arg)=def_arg])
+
+AS_CASE([$AS_TR_SH([with_]with_arg)],
+ [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)],
+ [auto],[PKG_CHECK_MODULES([$1],[$2],
+ [m4_n([def_action_if_found]) $3],
+ [m4_n([def_action_if_not_found]) $4])])
+
+m4_popdef([with_arg])
+m4_popdef([description])
+m4_popdef([def_arg])
+
+])dnl PKG_WITH_MODULES
+
+dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl [DESCRIPTION], [DEFAULT])
+dnl -----------------------------------------------
+dnl
+dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES
+dnl check._[VARIABLE-PREFIX] is exported as make variable.
+AC_DEFUN([PKG_HAVE_WITH_MODULES],
+[
+PKG_WITH_MODULES([$1],[$2],,,[$3],[$4])
+
+AM_CONDITIONAL([HAVE_][$1],
+ [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"])
+])dnl PKG_HAVE_WITH_MODULES
+
+dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl [DESCRIPTION], [DEFAULT])
+dnl ------------------------------------------------------
+dnl
+dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after
+dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make
+dnl and preprocessor variable.
+AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES],
+[
+PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4])
+
+AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
+ [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
+])dnl PKG_HAVE_DEFINE_WITH_MODULES
+
+# Copyright (C) 2002-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.16'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.16.5], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.16.5])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# Copyright (C) 2011-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_AR([ACT-IF-FAIL])
+# -------------------------
+# Try to determine the archiver interface, and trigger the ar-lib wrapper
+# if it is needed. If the detection of archiver interface fails, run
+# ACT-IF-FAIL (default is to abort configure with a proper error message).
+AC_DEFUN([AM_PROG_AR],
+[AC_BEFORE([$0], [LT_INIT])dnl
+AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl
+AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([ar-lib])dnl
+AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false])
+: ${AR=ar}
+
+AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface],
+ [AC_LANG_PUSH([C])
+ am_cv_ar_interface=ar
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])],
+ [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD'
+ AC_TRY_EVAL([am_ar_try])
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=ar
+ else
+ am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD'
+ AC_TRY_EVAL([am_ar_try])
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=lib
+ else
+ am_cv_ar_interface=unknown
+ fi
+ fi
+ rm -f conftest.lib libconftest.a
+ ])
+ AC_LANG_POP([C])])
+
+case $am_cv_ar_interface in
+ar)
+ ;;
+lib)
+ # Microsoft lib, so override with the ar-lib wrapper script.
+ # FIXME: It is wrong to rewrite AR.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__AR in this case,
+ # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something
+ # similar.
+ AR="$am_aux_dir/ar-lib $AR"
+ ;;
+unknown)
+ m4_default([$1],
+ [AC_MSG_ERROR([could not determine $AR interface])])
+ ;;
+esac
+AC_SUBST([AR])dnl
+])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to
+# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is '.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ([2.52])dnl
+ m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+m4_if([$1], [CC], [depcc="$CC" am_compiler_list=],
+ [$1], [CXX], [depcc="$CXX" am_compiler_list=],
+ [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
+ [$1], [UPC], [depcc="$UPC" am_compiler_list=],
+ [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ am__universal=false
+ m4_case([$1], [CC],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac],
+ [CXX],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac])
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE([dependency-tracking], [dnl
+AS_HELP_STRING(
+ [--enable-dependency-tracking],
+ [do not reject slow dependency extractors])
+AS_HELP_STRING(
+ [--disable-dependency-tracking],
+ [speeds up one-time build])])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+ am__nodep='_no'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+AC_SUBST([am__nodep])dnl
+_AM_SUBST_NOTMAKE([am__nodep])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+ # Older Autoconf quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ # TODO: see whether this extra hack can be removed once we start
+ # requiring Autoconf 2.70 or later.
+ AS_CASE([$CONFIG_FILES],
+ [*\'*], [eval set x "$CONFIG_FILES"],
+ [*], [set x $CONFIG_FILES])
+ shift
+ # Used to flag and report bootstrapping failures.
+ am_rc=0
+ for am_mf
+ do
+ # Strip MF so we end up with the name of the file.
+ am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile which includes
+ # dependency-tracking related rules and includes.
+ # Grep'ing the whole file directly is not great: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
+ || continue
+ am_dirpart=`AS_DIRNAME(["$am_mf"])`
+ am_filepart=`AS_BASENAME(["$am_mf"])`
+ AM_RUN_LOG([cd "$am_dirpart" \
+ && sed -e '/# am--include-marker/d' "$am_filepart" \
+ | $MAKE -f - am--depfiles]) || am_rc=$?
+ done
+ if test $am_rc -ne 0; then
+ AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
+ for automatic dependency tracking. If GNU make was not used, consider
+ re-running the configure script with MAKE="gmake" (or whatever is
+ necessary). You can also try re-running configure with the
+ '--disable-dependency-tracking' option to at least be able to build
+ the package (albeit without support for automatic dependency tracking).])
+ fi
+ AS_UNSET([am_dirpart])
+ AS_UNSET([am_filepart])
+ AS_UNSET([am_mf])
+ AS_UNSET([am_rc])
+ rm -f conftest-deps.mk
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking is enabled.
+# This creates each '.Po' and '.Plo' makefile fragment that we'll need in
+# order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
+m4_define([AC_PROG_CC],
+m4_defn([AC_PROG_CC])
+[_AM_PROG_CC_C_O
+])
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.65])dnl
+m4_ifdef([_$0_ALREADY_INIT],
+ [m4_fatal([$0 expanded multiple times
+]m4_defn([_$0_ALREADY_INIT]))],
+ [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[AC_DIAGNOSE([obsolete],
+ [$0: two- and three-arguments forms are deprecated.])
+m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(
+ m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]),
+ [ok:ok],,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
+ AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
+AM_MISSING_PROG([AUTOCONF], [autoconf])
+AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
+AM_MISSING_PROG([AUTOHEADER], [autoheader])
+AM_MISSING_PROG([MAKEINFO], [makeinfo])
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+# For better backward compatibility. To be removed once Automake 1.9.x
+# dies out for good. For more background, see:
+#
+#
+AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+# We need awk for the "check" target (and possibly the TAP driver). The
+# system "awk" is bad on some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES([CC])],
+ [m4_define([AC_PROG_CC],
+ m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES([CXX])],
+ [m4_define([AC_PROG_CXX],
+ m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES([OBJC])],
+ [m4_define([AC_PROG_OBJC],
+ m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+ [_AM_DEPENDENCIES([OBJCXX])],
+ [m4_define([AC_PROG_OBJCXX],
+ m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
+])
+# Variables for tags utilities; see am/tags.am
+if test -z "$CTAGS"; then
+ CTAGS=ctags
+fi
+AC_SUBST([CTAGS])
+if test -z "$ETAGS"; then
+ ETAGS=etags
+fi
+AC_SUBST([ETAGS])
+if test -z "$CSCOPE"; then
+ CSCOPE=cscope
+fi
+AC_SUBST([CSCOPE])
+
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+ [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes. So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+ cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present. This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard:
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message. This
+can help us improve future automake versions.
+
+END
+ if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+ echo 'Configuration will proceed anyway, since you have set the' >&2
+ echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+ echo >&2
+ else
+ cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: .
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+ AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
+ fi
+fi
+dnl The trailing newline in this macro's definition is deliberate, for
+dnl backward compatibility and to allow trailing 'dnl'-style comments
+dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
+])
+
+dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+AC_SUBST([install_sh])])
+
+# Copyright (C) 2003-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless 'enable' is passed literally.
+# For symmetry, 'disable' may be passed as well. Anyway, the user
+# can override the default with the --enable/--disable switch.
+AC_DEFUN([AM_MAINTAINER_MODE],
+[m4_case(m4_default([$1], [disable]),
+ [enable], [m4_define([am_maintainer_other], [disable])],
+ [disable], [m4_define([am_maintainer_other], [enable])],
+ [m4_define([am_maintainer_other], [enable])
+ m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+ dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+ AC_ARG_ENABLE([maintainer-mode],
+ [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode],
+ am_maintainer_other[ make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer])],
+ [USE_MAINTAINER_MODE=$enableval],
+ [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
+ AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+ AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
+ MAINT=$MAINTAINER_MODE_TRUE
+ AC_SUBST([MAINT])dnl
+]
+)
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check whether make has an 'include' directive that can support all
+# the idioms we need for our automatic dependency tracking code.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive])
+cat > confinc.mk << 'END'
+am__doit:
+ @echo this is the am__doit target >confinc.out
+.PHONY: am__doit
+END
+am__include="#"
+am__quote=
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+ AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out])
+ AS_CASE([$?:`cat confinc.out 2>/dev/null`],
+ ['0:this is the am__doit target'],
+ [AS_CASE([$s],
+ [BSD], [am__include='.include' am__quote='"'],
+ [am__include='include' am__quote=''])])
+ if test "$am__include" != "#"; then
+ _am_result="yes ($s style)"
+ break
+ fi
+done
+rm -f confinc.* confmf.*
+AC_MSG_RESULT([${_am_result}])
+AC_SUBST([am__include])])
+AC_SUBST([am__quote])])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+ MISSING="\${SHELL} '$am_aux_dir/missing'"
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+ am_missing_run="$MISSING "
+else
+ am_missing_run=
+ AC_MSG_WARN(['missing' script is too old or missing])
+fi
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# --------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Copyright (C) 1999-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_CC_C_O
+# ---------------
+# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC
+# to automatically call this.
+AC_DEFUN([_AM_PROG_CC_C_O],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+AC_LANG_PUSH([C])dnl
+AC_CACHE_CHECK(
+ [whether $CC understands -c and -o together],
+ [am_cv_prog_cc_c_o],
+ [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+ # Make sure it works both with $CC and with simple cc.
+ # Following AC_PROG_CC_C_O, we do the test twice because some
+ # compilers refuse to overwrite an existing .o file with -o,
+ # though they will create one.
+ am_cv_prog_cc_c_o=yes
+ for am_i in 1 2; do
+ if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
+ && test -f conftest2.$ac_objext; then
+ : OK
+ else
+ am_cv_prog_cc_c_o=no
+ break
+ fi
+ done
+ rm -f core conftest*
+ unset am_i])
+if test "$am_cv_prog_cc_c_o" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+AC_LANG_POP([C])])
+
+# For backward compatibility.
+AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+ ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ (exit $ac_status); }])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[[\\\"\#\$\&\'\`$am_lf]]*)
+ AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+ *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
+ AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ am_has_slept=no
+ for am_try in 1 2; do
+ echo "timestamp, slept: $am_has_slept" > conftest.file
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+ alias in your environment])
+ fi
+ if test "$[2]" = conftest.file || test $am_try -eq 2; then
+ break
+ fi
+ # Just in case.
+ sleep 1
+ am_has_slept=yes
+ done
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT([yes])
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+ ( sleep 1 ) &
+ am_sleep_pid=$!
+fi
+AC_CONFIG_COMMANDS_PRE(
+ [AC_MSG_CHECKING([that generated files are newer than configure])
+ if test -n "$am_sleep_pid"; then
+ # Hide warnings about reused PIDs.
+ wait $am_sleep_pid 2>/dev/null
+ fi
+ AC_MSG_RESULT([done])])
+rm -f conftest.file
+])
+
+# Copyright (C) 2009-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+ [--enable-silent-rules],
+ [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+ [--disable-silent-rules],
+ [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+ yes) AM_DEFAULT_VERBOSITY=0;;
+ no) AM_DEFAULT_VERBOSITY=1;;
+ *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+ [am_cv_make_support_nested_variables],
+ [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+ dnl Using '$V' instead of '$(V)' breaks IRIX make.
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor 'install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in "make install-strip", and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip". However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# --------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004-2021 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of 'v7', 'ustar', or 'pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+#
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility. Yes, it's still used
+# in the wild :-( We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+
+m4_if([$1], [v7],
+ [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+ [m4_case([$1],
+ [ustar],
+ [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+ # There is notably a 21 bits limit for the UID and the GID. In fact,
+ # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+ # and bug#13588).
+ am_max_uid=2097151 # 2^21 - 1
+ am_max_gid=$am_max_uid
+ # The $UID and $GID variables are not portable, so we need to resort
+ # to the POSIX-mandated id(1) utility. Errors in the 'id' calls
+ # below are definitely unexpected, so allow the users to see them
+ # (that is, avoid stderr redirection).
+ am_uid=`id -u || echo unknown`
+ am_gid=`id -g || echo unknown`
+ AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+ if test $am_uid -le $am_max_uid; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ _am_tools=none
+ fi
+ AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+ if test $am_gid -le $am_max_gid; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ _am_tools=none
+ fi],
+
+ [pax],
+ [],
+
+ [m4_fatal([Unknown tar format])])
+
+ AC_MSG_CHECKING([how to create a $1 tar archive])
+
+ # Go ahead even if we have the value already cached. We do so because we
+ # need to set the values for the 'am__tar' and 'am__untar' variables.
+ _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+ for _am_tool in $_am_tools; do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar; do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works.
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar /dev/null 2>&1 && break
+ fi
+ done
+ rm -rf conftest.dir
+
+ AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+ AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([m4/ax_pthread.m4])
+m4_include([m4/libtool.m4])
+m4_include([m4/ltoptions.m4])
+m4_include([m4/ltsugar.m4])
+m4_include([m4/ltversion.m4])
+m4_include([m4/lt~obsolete.m4])
+m4_include([m4/pcre2_check_vscript.m4])
+m4_include([m4/pcre2_visibility.m4])
+m4_include([m4/pcre2_zos.m4])
diff --git a/ar-lib b/ar-lib
new file mode 100755
index 0000000..c349042
--- /dev/null
+++ b/ar-lib
@@ -0,0 +1,271 @@
+#! /bin/sh
+# Wrapper for Microsoft lib.exe
+
+me=ar-lib
+scriptversion=2019-07-04.01; # UTC
+
+# Copyright (C) 2010-2021 Free Software Foundation, Inc.
+# Written by Peter Rosin .
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to or send patches to
+# .
+
+
+# func_error message
+func_error ()
+{
+ echo "$me: $1" 1>&2
+ exit 1
+}
+
+file_conv=
+
+# func_file_conv build_file
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts.
+func_file_conv ()
+{
+ file=$1
+ case $file in
+ / | /[!/]*) # absolute file, and not a UNC file
+ if test -z "$file_conv"; then
+ # lazily determine how to convert abs files
+ case `uname -s` in
+ MINGW*)
+ file_conv=mingw
+ ;;
+ CYGWIN* | MSYS*)
+ file_conv=cygwin
+ ;;
+ *)
+ file_conv=wine
+ ;;
+ esac
+ fi
+ case $file_conv in
+ mingw)
+ file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+ ;;
+ cygwin | msys)
+ file=`cygpath -m "$file" || echo "$file"`
+ ;;
+ wine)
+ file=`winepath -w "$file" || echo "$file"`
+ ;;
+ esac
+ ;;
+ esac
+}
+
+# func_at_file at_file operation archive
+# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
+# for each of them.
+# When interpreting the content of the @FILE, do NOT use func_file_conv,
+# since the user would need to supply preconverted file names to
+# binutils ar, at least for MinGW.
+func_at_file ()
+{
+ operation=$2
+ archive=$3
+ at_file_contents=`cat "$1"`
+ eval set x "$at_file_contents"
+ shift
+
+ for member
+ do
+ $AR -NOLOGO $operation:"$member" "$archive" || exit $?
+ done
+}
+
+case $1 in
+ '')
+ func_error "no command. Try '$0 --help' for more information."
+ ;;
+ -h | --h*)
+ cat < false,
+ else => return err,
+ };
+
+ // We don't know how the sljit dependency is being provided. Either it
+ // comes via a git submodule, or it may be fetched by zig itself.
+ const sljit_include_path = if (!support_jit)
+ null
+ else if (sljit_is_checked_out)
+ null
+ else blk: {
+ const sljit = b.lazyDependency("sljit", .{}) orelse
+ break :blk null;
+
+ const files = b.addWriteFiles();
+
+ // Recreate the layout used by pcre2_jit_compile.c's relative include.
+ _ = files.addCopyDirectory(
+ sljit.path("sljit_src"),
+ "deps/sljit/sljit_src",
+ .{},
+ );
+ _ = files.add("src/.empty", "");
+
+ break :blk files.getDirectory().path(b, "src");
+ };
+
+ const pcre2_h_dir = b.addWriteFiles();
+ const pcre2_h = pcre2_h_dir.addCopyFile(b.path("src/pcre2.h.generic"), "pcre2.h");
+ b.addNamedLazyPath("pcre2.h", pcre2_h);
+
+ const is_unix = rt.os.tag != .windows;
+ const is_mingw = rt.isMinGW();
+ const is_musl = rt.isMuslLibC();
+ const is_glibc = rt.isGnuLibC();
+ const is_freebsd = rt.isFreeBSDLibC();
+
+ const cflags = &.{
+ "-fvisibility=hidden",
+ };
+
+ const config_h = b.addConfigHeader(
+ .{
+ .style = .{
+ .cmake = b.path("src/config-cmake.h.in"),
+ },
+ .include_path = "config.h",
+ },
+ // These options should be kept in-sync with those in config-cmake.h.in, and
+ // should be the same set of options (no more needed). It is permitted to
+ // specify fewer options here than in config-cmake.h.in, if an option is
+ // disabled in all zig build configurations.
+ .{
+ .HAVE_ASSERT_H = true,
+ .HAVE_DIRENT_H = is_unix or is_mingw,
+ .HAVE_SYS_STAT_H = true,
+ .HAVE_SYS_TYPES_H = true,
+ .HAVE_UNISTD_H = is_unix or is_mingw,
+ .HAVE_WINDOWS_H = rt.os.tag == .windows,
+
+ .HAVE_MEMFD_CREATE = is_musl or is_glibc or is_freebsd,
+ .HAVE_SECURE_GETENV = is_musl or is_glibc or is_freebsd,
+ .HAVE_SETRLIMIT = is_unix and !is_mingw,
+
+ // all compilation is using the Zig bundled c compiler
+ .HAVE_BUILTIN_ASSUME = null,
+ .HAVE_BUILTIN_MUL_OVERFLOW = true,
+ .HAVE_BUILTIN_UNREACHABLE = true,
+ .HAVE_ATTRIBUTE_UNINITIALIZED = true,
+
+ .SUPPORT_PCRE2_8 = codeUnitWidth == .@"8",
+ .SUPPORT_PCRE2_16 = codeUnitWidth == .@"16",
+ .SUPPORT_PCRE2_32 = codeUnitWidth == .@"32",
+ .SUPPORT_UNICODE = true,
+ .SUPPORT_JIT = support_jit,
+
+ // As for CMake builds, use visibilty attributes for both shared and static
+ // builds. Internal symbols should be hidden even in static builds, because
+ // the user could be statically linking PCRE2 into their own shared library.
+ .PCRE2_EXPORT = "__attribute__ ((visibility (\"default\")))",
+
+ .PCRE2_LINK_SIZE = 2,
+ .PCRE2_PARENS_NEST_LIMIT = 250,
+ .PCRE2_HEAP_LIMIT = 20000000,
+ .PCRE2_MAX_VARLOOKBEHIND = 255,
+ .PCRE2_MATCH_LIMIT = 10000000,
+ .PCRE2_MATCH_LIMIT_DEPTH = "MATCH_LIMIT",
+ .PCRE2GREP_BUFSIZE = 20480,
+ .PCRE2GREP_MAX_BUFSIZE = 1048576,
+ .NEWLINE_DEFAULT = 2,
+ },
+ );
+
+ // pcre2-8/16/32 library
+ const lib_mod = b.createModule(.{
+ .target = target,
+ .optimize = optimize,
+ .sanitize_c = sanitize_c,
+ .link_libc = true,
+ });
+
+ lib_mod.addCMacro("HAVE_CONFIG_H", "");
+ lib_mod.addCMacro("PCRE2_CODE_UNIT_WIDTH", @tagName(codeUnitWidth));
+ switch (linkage) {
+ .static => lib_mod.addCMacro("PCRE2_STATIC", ""),
+ .dynamic => {},
+ }
+ lib_mod.addConfigHeader(config_h);
+ lib_mod.addIncludePath(pcre2_h_dir.getDirectory());
+ lib_mod.addIncludePath(b.path("src"));
+ if (sljit_include_path) |include_path| {
+ lib_mod.addIncludePath(include_path);
+ }
+
+ lib_mod.addCSourceFile(.{
+ .file = b.addWriteFiles().addCopyFile(b.path("src/pcre2_chartables.c.dist"), "pcre2_chartables.c"),
+ .flags = cflags,
+ });
+ lib_mod.addCSourceFiles(.{
+ .files = &.{
+ "src/pcre2_auto_possess.c",
+ "src/pcre2_chkdint.c",
+ "src/pcre2_compile.c",
+ "src/pcre2_compile_cgroup.c",
+ "src/pcre2_compile_class.c",
+ "src/pcre2_config.c",
+ "src/pcre2_context.c",
+ "src/pcre2_convert.c",
+ "src/pcre2_dfa_match.c",
+ "src/pcre2_error.c",
+ "src/pcre2_extuni.c",
+ "src/pcre2_find_bracket.c",
+ "src/pcre2_jit_compile.c",
+ "src/pcre2_maketables.c",
+ "src/pcre2_match.c",
+ "src/pcre2_match_data.c",
+ "src/pcre2_match_next.c",
+ "src/pcre2_newline.c",
+ "src/pcre2_ord2utf.c",
+ "src/pcre2_pattern_info.c",
+ "src/pcre2_script_run.c",
+ "src/pcre2_serialize.c",
+ "src/pcre2_string_utils.c",
+ "src/pcre2_study.c",
+ "src/pcre2_substitute.c",
+ "src/pcre2_substring.c",
+ "src/pcre2_tables.c",
+ "src/pcre2_ucd.c",
+ "src/pcre2_valid_utf.c",
+ "src/pcre2_xclass.c",
+ },
+ .flags = cflags,
+ });
+
+ const lib = b.addLibrary(.{
+ .name = b.fmt("pcre2-{t}", .{codeUnitWidth}),
+ .root_module = lib_mod,
+ .linkage = linkage,
+ });
+
+ lib.installHeader(pcre2_h, "pcre2.h");
+ b.installArtifact(lib);
+
+ // pcre2test
+ const pcre2test_mod = b.createModule(.{
+ .target = target,
+ .optimize = optimize,
+ .sanitize_c = sanitize_c,
+ .link_libc = true,
+ });
+
+ pcre2test_mod.addCMacro("HAVE_CONFIG_H", "");
+
+ // Note: On Windows, consumers linking against the static library should
+ // probably define PCRE2_STATIC themselves (e.g. via
+ // addCMacro("PCRE2_STATIC", "")).
+ // As far as I know, Zig's build system does not currently have a mechanism
+ // to propagate compile definitions to downstream consumers (like CMake's
+ // PUBLIC target_compile_definitions). On non-Windows targets this is a no-op.
+ switch (linkage) {
+ .static => pcre2test_mod.addCMacro("PCRE2_STATIC", ""),
+ .dynamic => pcre2test_mod.addCMacro("PCRE2POSIX_SHARED", ""),
+ }
+
+ const pcre2test = b.addExecutable(.{
+ .name = "pcre2test",
+ .root_module = pcre2test_mod,
+ });
+ pcre2test_mod.addConfigHeader(config_h);
+ pcre2test_mod.addIncludePath(pcre2_h_dir.getDirectory());
+ pcre2test_mod.addIncludePath(b.path("src"));
+
+ pcre2test_mod.addCSourceFile(.{
+ .file = b.path("src/pcre2test.c"),
+ .flags = cflags,
+ });
+
+ pcre2test_mod.linkLibrary(lib);
+ b.installArtifact(pcre2test);
+
+ // pcre2-posix library
+ if (codeUnitWidth == CodeUnitWidth.@"8") {
+ const posixLib_mod = b.createModule(.{
+ .target = target,
+ .optimize = optimize,
+ .sanitize_c = sanitize_c,
+ .link_libc = true,
+ });
+
+ posixLib_mod.addCMacro("HAVE_CONFIG_H", "");
+ posixLib_mod.addCMacro("PCRE2_CODE_UNIT_WIDTH", @tagName(codeUnitWidth));
+
+ switch (linkage) {
+ .static => posixLib_mod.addCMacro("PCRE2_STATIC", ""),
+ .dynamic => posixLib_mod.addCMacro("PCRE2POSIX_SHARED", ""),
+ }
+
+ posixLib_mod.addConfigHeader(config_h);
+ posixLib_mod.addIncludePath(pcre2_h_dir.getDirectory());
+ posixLib_mod.addIncludePath(b.path("src"));
+
+ posixLib_mod.addCSourceFiles(.{
+ .files = &.{
+ "src/pcre2posix.c",
+ },
+ .flags = cflags,
+ });
+
+ posixLib_mod.linkLibrary(lib);
+
+ const posixLib = b.addLibrary(.{
+ .name = "pcre2-posix",
+ .root_module = posixLib_mod,
+ .linkage = linkage,
+ });
+
+ pcre2test_mod.linkLibrary(posixLib);
+
+ b.addNamedLazyPath("pcre2posix.h", b.path("src/pcre2posix.h"));
+ posixLib.installHeader(b.path("src/pcre2posix.h"), "pcre2posix.h");
+ b.installArtifact(posixLib);
+ }
+}
diff --git a/build.zig.zon b/build.zig.zon
new file mode 100644
index 0000000..eda9011
--- /dev/null
+++ b/build.zig.zon
@@ -0,0 +1,25 @@
+.{
+ .name = .pcre2,
+ .version = "10.48.0",
+
+ // Do NOT change this for new releases.
+ // DO change this if making a fork of PCRE2 which is used by any Zig clients.
+ .fingerprint = 0x914b3d63ebab9e21,
+
+ .minimum_zig_version = "0.16.0",
+ .dependencies = .{
+ .sljit = .{
+ .url = "git+https://github.com/zherczeg/sljit.git#de0259c7aaf36aa40cba8014f3fad3edde9307f9",
+ .hash = "N-V-__8AAN1hRgCbYkMHlPE4yQE6rN_yDbzE1yr8W1J6x-Gw",
+ .lazy = true,
+ },
+ },
+ .paths = .{
+ "build.zig", "build.zig.zon",
+ "src/", "doc/",
+ "deps/", "HACKING",
+ "INSTALL", "README.md",
+ "LICENCE.md", "AUTHORS.md",
+ "SECURITY.md",
+ },
+}
diff --git a/cmake/COPYING-CMAKE-SCRIPTS b/cmake/COPYING-CMAKE-SCRIPTS
new file mode 100644
index 0000000..53b6b71
--- /dev/null
+++ b/cmake/COPYING-CMAKE-SCRIPTS
@@ -0,0 +1,22 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/cmake/FindEditline.cmake b/cmake/FindEditline.cmake
new file mode 100644
index 0000000..4784e05
--- /dev/null
+++ b/cmake/FindEditline.cmake
@@ -0,0 +1,15 @@
+# Modified from FindReadline.cmake (PH Feb 2012)
+
+find_path(EDITLINE_INCLUDE_DIR readline.h PATH_SUFFIXES editline edit/readline)
+mark_as_advanced(EDITLINE_INCLUDE_DIR)
+
+find_library(EDITLINE_LIBRARY NAMES edit)
+mark_as_advanced(EDITLINE_LIBRARY)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Editline DEFAULT_MSG EDITLINE_LIBRARY EDITLINE_INCLUDE_DIR)
+
+if(Editline_FOUND)
+ set(EDITLINE_LIBRARIES "${EDITLINE_LIBRARY}")
+ set(EDITLINE_INCLUDE_DIRS "${EDITLINE_INCLUDE_DIR}")
+endif()
diff --git a/cmake/FindReadline.cmake b/cmake/FindReadline.cmake
new file mode 100644
index 0000000..e55fbcf
--- /dev/null
+++ b/cmake/FindReadline.cmake
@@ -0,0 +1,67 @@
+# from http://websvn.kde.org/trunk/KDE/kdeedu/cmake/modules/FindReadline.cmake
+# http://websvn.kde.org/trunk/KDE/kdeedu/cmake/modules/COPYING-CMAKE-SCRIPTS
+# --> BSD licensed
+#
+# GNU Readline library finder
+
+find_path(READLINE_INCLUDE_DIR readline/readline.h PATH_SUFFIXES include)
+mark_as_advanced(READLINE_INCLUDE_DIR)
+
+find_library(READLINE_LIBRARY NAMES readline)
+mark_as_advanced(READLINE_LIBRARY)
+
+if(READLINE_INCLUDE_DIR AND READLINE_LIBRARY)
+ # Check if we need to link to ncurses as well
+
+ include(CheckSymbolExists)
+ include(CMakePushCheckState)
+
+ set(first_run FALSE)
+ if(NOT DEFINED HAVE_READLINE_FUNC)
+ set(first_run TRUE)
+ endif()
+
+ cmake_push_check_state(RESET)
+ set(CMAKE_REQUIRED_LIBRARIES "${READLINE_LIBRARY}")
+ set(CMAKE_REQUIRED_INCLUDES "${READLINE_INCLUDE_DIR}")
+ check_symbol_exists("readline" "stdio.h;readline/readline.h" HAVE_READLINE_FUNC)
+
+ if(NOT HAVE_READLINE_FUNC)
+ foreach(
+ lib
+ IN
+ ITEMS tinfo curses ncurses ncursesw termcap
+ )
+ find_library(NCURSES_LIBRARY_${lib} NAMES ${lib})
+ mark_as_advanced(NCURSES_LIBRARY_${lib})
+ if(NCURSES_LIBRARY_${lib})
+ cmake_reset_check_state()
+ set(CMAKE_REQUIRED_LIBRARIES "${READLINE_LIBRARY}" "${NCURSES_LIBRARY_${lib}}")
+ set(CMAKE_REQUIRED_INCLUDES "${READLINE_INCLUDE_DIR}")
+ check_symbol_exists("readline" "stdio.h;readline/readline.h" HAVE_READLINE_FUNC_${lib})
+
+ if(HAVE_READLINE_FUNC_${lib})
+ if(first_run)
+ message(STATUS "Looking for readline - readline needs ${lib}")
+ endif()
+ set(NCURSES_LIBRARY "${NCURSES_LIBRARY_${lib}}" CACHE FILEPATH "Path to the ncurses library")
+ mark_as_advanced(NCURSES_LIBRARY)
+ break()
+ endif()
+ endif()
+ endforeach()
+ endif()
+
+ cmake_pop_check_state()
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Readline DEFAULT_MSG READLINE_LIBRARY READLINE_INCLUDE_DIR)
+
+if(Readline_FOUND)
+ set(READLINE_LIBRARIES "${READLINE_LIBRARY}")
+ if(DEFINED NCURSES_LIBRARY)
+ list(APPEND READLINE_LIBRARIES "${NCURSES_LIBRARY}")
+ endif()
+ set(READLINE_INCLUDE_DIRS "${READLINE_INCLUDE_DIR}")
+endif()
diff --git a/cmake/PCRE2CheckVscript.cmake b/cmake/PCRE2CheckVscript.cmake
new file mode 100644
index 0000000..eeda4c0
--- /dev/null
+++ b/cmake/PCRE2CheckVscript.cmake
@@ -0,0 +1,141 @@
+# Similarly to Autoconf's ax_check_vscript.m4, check whether the linker supports
+# version scripts (GNU ld) or map files (Sun linker).
+# Sets the "have_var" to TRUE or FALSE depending on the detected support; and if
+# support is detected then sets "flag_var" to the appropriate flag to pass to
+# the linker (namely, --version-script or -M).
+
+# Helper function: try to compile a shared library with a given linker flag and
+# version script. This properly tests version script support by building a
+# shared library rather than an executable, avoiding issues with
+# executable-specific symbols (e.g. FreeBSD's crt1.o symbols, Solaris linker
+# symbols in values-Xc.o).
+function(_pcre2_try_vscript_shared_lib link_flag map_file result_var)
+ if(DEFINED ${result_var})
+ return()
+ endif()
+
+ message(STATUS "Performing Test ${result_var}")
+
+ set(${result_var} FALSE PARENT_SCOPE)
+
+ set(try_dir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeScratch/CheckVscript")
+ file(REMOVE_RECURSE "${try_dir}")
+ file(MAKE_DIRECTORY "${try_dir}")
+
+ # Write a minimal C source with exported symbols
+ file(WRITE "${try_dir}/test_vscript.c" "
+int hidethis(void) { return 0; }
+int exposethis(void) { return hidethis(); }
+")
+
+ # Write a CMakeLists.txt that builds a shared library with the version script
+ file(WRITE "${try_dir}/CMakeLists.txt" "
+cmake_minimum_required(VERSION 3.15)
+project(test_vscript C)
+add_library(test_vscript SHARED test_vscript.c)
+target_link_options(test_vscript PRIVATE \"-Wl,${link_flag},${map_file}\")
+")
+
+ try_compile(
+ compile_result
+ "${try_dir}/build" # BINARY_DIR
+ "${try_dir}" # SOURCE_DIR
+ test_vscript # Project name
+ OUTPUT_VARIABLE compile_output
+ )
+
+ if(compile_result)
+ set(${result_var} TRUE PARENT_SCOPE)
+ endif()
+
+ if(${compile_result})
+ set(${result_var} 1 CACHE INTERNAL "Test ${result_var}")
+ message(STATUS "Performing Test ${result_var} - Success")
+ else()
+ set(${result_var} "" CACHE INTERNAL "Test ${result_var}")
+ message(STATUS "Performing Test ${result_var} - Failed")
+ endif()
+endfunction()
+
+function(pcre2_check_vscript have_var flag_var no_star_var)
+ set(${have_var} FALSE PARENT_SCOPE)
+ set(${flag_var} "" PARENT_SCOPE)
+ set(${no_star_var} FALSE PARENT_SCOPE)
+
+ if(MSVC)
+ return()
+ endif()
+
+ set(first_run FALSE)
+ if(NOT DEFINED HAVE_VSCRIPT_GNU)
+ set(first_run TRUE)
+ message(STATUS "Detecting linker version script support")
+ endif()
+
+ # Write test version script files
+ file(WRITE "${PROJECT_BINARY_DIR}/test-map-file.sym" "PCRE2_10.00 { global: exposethis; local: *; };")
+ file(WRITE "${PROJECT_BINARY_DIR}/test-map-file-broken.sym" "PCRE2_10.00 { global: exposethis; local: *; }; {")
+ file(WRITE "${PROJECT_BINARY_DIR}/test-map-file-no-star.sym" "PCRE2_10.00 { global: exposethis; local: hidethis; };")
+
+ set(HAVE_VSCRIPT FALSE)
+
+ # Test GNU ld --version-script flag
+ _pcre2_try_vscript_shared_lib("--version-script" "${PROJECT_BINARY_DIR}/test-map-file.sym" HAVE_VSCRIPT_GNU)
+
+ if(HAVE_VSCRIPT_GNU)
+ set(VSCRIPT_FLAG --version-script)
+ set(HAVE_VSCRIPT TRUE)
+ else()
+ # Test Sun linker -M flag
+ _pcre2_try_vscript_shared_lib("-M" "${PROJECT_BINARY_DIR}/test-map-file.sym" HAVE_VSCRIPT_SUN)
+
+ if(HAVE_VSCRIPT_SUN)
+ set(VSCRIPT_FLAG -M)
+ set(HAVE_VSCRIPT TRUE)
+ endif()
+ endif()
+
+ if(HAVE_VSCRIPT)
+ # Perform the same logic as ax_check_vscript.m4, to test whether the linker
+ # silently ignores (and overwrites) linker scripts it doesn't understand.
+ _pcre2_try_vscript_shared_lib("${VSCRIPT_FLAG}" "${PROJECT_BINARY_DIR}/test-map-file-broken.sym" HAVE_VSCRIPT_BROKEN)
+
+ if(HAVE_VSCRIPT_BROKEN)
+ set(HAVE_VSCRIPT FALSE)
+ endif()
+ endif()
+
+ if(first_run)
+ if(HAVE_VSCRIPT)
+ message(STATUS "Detecting linker version script support - yes (${VSCRIPT_FLAG})")
+ elseif(HAVE_VSCRIPT_BROKEN)
+ message(STATUS "Detecting linker version script support - no (linker overwrites unknown scripts)")
+ else()
+ message(STATUS "Detecting linker version script support - none detected")
+ endif()
+ endif()
+
+ if(HAVE_VSCRIPT)
+ if(first_run)
+ message(STATUS "Detecting if version scripts work without wildcard")
+ endif()
+
+ # Test that the linker works without requiring a wildcard to hide platform-specific
+ # symbols (_init, _fini, etc.).
+ _pcre2_try_vscript_shared_lib("${VSCRIPT_FLAG}" "${PROJECT_BINARY_DIR}/test-map-file-no-star.sym" HAVE_VSCRIPT_NO_STAR)
+
+ if(first_run)
+ message(STATUS "Detecting if version scripts work without wildcard - ${HAVE_VSCRIPT_NO_STAR}")
+ endif()
+ endif()
+
+ file(REMOVE "${PROJECT_BINARY_DIR}/test-map-file.sym")
+ file(REMOVE "${PROJECT_BINARY_DIR}/test-map-file-broken.sym")
+ file(REMOVE "${PROJECT_BINARY_DIR}/test-map-file-no-star.sym")
+
+ if(HAVE_VSCRIPT)
+ set(${have_var} TRUE PARENT_SCOPE)
+ set(${flag_var} "${VSCRIPT_FLAG}" PARENT_SCOPE)
+ set(${no_star_var} "${HAVE_VSCRIPT_NO_STAR}" PARENT_SCOPE)
+ endif()
+endfunction()
diff --git a/cmake/PCRE2UseSystemExtensions.cmake b/cmake/PCRE2UseSystemExtensions.cmake
new file mode 100644
index 0000000..a70a5f7
--- /dev/null
+++ b/cmake/PCRE2UseSystemExtensions.cmake
@@ -0,0 +1,89 @@
+# This CMake module is supposed to give similar results to the
+# AC_USE_SYSTEM_EXTENSIONS Autoconf macro, which turns on a load of
+# system feature-check macros, including _ALL_SOURCE, _GNU_SOURCE,
+# _NETBSD_SOURCE, and many more.
+#
+# Because PCRE2 uses so few OS features, we don't seem to actually need to
+# enable many of these. Modern platforms with CMake users generally enable
+# all the basic POSIX features by default.
+#
+# So far, we know that we require:
+# - _ALL_SOURCE on IBM systems (z/OS, probably AIX) in order to call
+# getrlimit() in pcre2test.
+# - _GNU_SOURCE on Linux in order to call mkostemp() in some (non-default)
+# configurations of the JIT.
+#
+# Autoconf enables this unconditionally. However, our CMake script potentially
+# supports *more* platforms than Autoconf, so we use a feature check.
+
+function(pcre2_use_system_extensions)
+ if(WIN32)
+ return()
+ endif()
+
+ set(first_run FALSE)
+ set(found_macro FALSE)
+ if(NOT DEFINED HAVE_GETRLIMIT_NAKED)
+ set(first_run TRUE)
+ message(STATUS "Detecting platform feature test macros")
+ endif()
+
+ include(CheckSymbolExists)
+ include(CheckCSourceCompiles)
+ include(CMakePushCheckState)
+
+ cmake_push_check_state(RESET)
+ set(
+ _pcre2_test_src
+ [=[
+ #include
+ #include
+
+ int main(void) {
+ struct rlimit rlim;
+ getrlimit(RLIMIT_STACK, &rlim);
+ return 0;
+ }
+ ]=]
+ )
+ set(CMAKE_REQUIRED_QUIET TRUE)
+ check_c_source_compiles("${_pcre2_test_src}" HAVE_GETRLIMIT_NAKED)
+
+ if(NOT HAVE_GETRLIMIT_NAKED)
+ # Try again with _ALL_SOURCE
+ set(CMAKE_REQUIRED_DEFINITIONS "-D_ALL_SOURCE")
+ check_c_source_compiles("${_pcre2_test_src}" HAVE_GETRLIMIT_ALLSOURCE)
+ unset(CMAKE_REQUIRED_DEFINITIONS)
+
+ if(HAVE_GETRLIMIT_ALLSOURCE)
+ add_compile_definitions(_ALL_SOURCE)
+ set(found_macro TRUE)
+ if(first_run)
+ message(STATUS "Detecting platform feature test macros - _ALL_SOURCE")
+ endif()
+ endif()
+ endif()
+
+ check_symbol_exists(mkostemp stdlib.h HAVE_MKOSTEMP_NAKED)
+
+ if(NOT HAVE_MKOSTEMP_NAKED)
+ # Try again with _GNU_SOURCE
+ set(CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE")
+ check_symbol_exists(mkostemp stdlib.h HAVE_MKOSTEMP_GNUSOURCE)
+ unset(CMAKE_REQUIRED_DEFINITIONS)
+
+ if(HAVE_MKOSTEMP_GNUSOURCE)
+ add_compile_definitions(_GNU_SOURCE)
+ set(found_macro TRUE)
+ if(first_run)
+ message(STATUS "Detecting platform feature test macros - _GNU_SOURCE")
+ endif()
+ endif()
+ endif()
+
+ if(first_run AND NOT found_macro)
+ message(STATUS "Detecting platform feature test macros - none")
+ endif()
+
+ cmake_pop_check_state()
+endfunction()
diff --git a/cmake/PCRE2WarningAsError.cmake b/cmake/PCRE2WarningAsError.cmake
new file mode 100644
index 0000000..78b76a5
--- /dev/null
+++ b/cmake/PCRE2WarningAsError.cmake
@@ -0,0 +1,35 @@
+# This file can be removed once the minimum CMake version is increased to 3.24
+# or higher. Calls to pcre2_warning_as_error can be changed to the built in
+# CMAKE_C_COMPILE_OPTIONS_WARNING_AS_ERROR.
+
+function(pcre2_warning_as_error out_var)
+ set(${out_var} "" PARENT_SCOPE)
+
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24)
+ # Since CMake 3.24, we should use the CMAKE_C_COMPILE_OPTIONS_WARNING_AS_ERROR
+ # variable for greatest compiler compatibility.
+ if(DEFINED CMAKE_C_COMPILE_OPTIONS_WARNING_AS_ERROR)
+ set(${out_var} "${CMAKE_C_COMPILE_OPTIONS_WARNING_AS_ERROR}" PARENT_SCOPE)
+ endif()
+ else()
+ # The fallback probes for support, trying a few common flags.
+
+ if(NOT MSVC)
+ include(CheckCCompilerFlag)
+ include(CMakePushCheckState)
+
+ cmake_push_check_state(RESET)
+ check_c_compiler_flag("-Werror" HAVE_WERROR)
+ if(HAVE_WERROR)
+ set(${out_var} "-Werror" PARENT_SCOPE)
+ else()
+ check_c_compiler_flag("-errwarn=%all" HAVE_ERRWARN_ALL)
+ if(HAVE_ERRWARN_ALL)
+ set(${out_var} "-errwarn=%all" PARENT_SCOPE)
+ endif()
+ endif()
+
+ cmake_pop_check_state()
+ endif()
+ endif()
+endfunction()
diff --git a/cmake/pcre2-config.cmake.in b/cmake/pcre2-config.cmake.in
new file mode 100644
index 0000000..bda4841
--- /dev/null
+++ b/cmake/pcre2-config.cmake.in
@@ -0,0 +1,90 @@
+# pcre2-config.cmake
+# ----------------
+#
+# Finds the PCRE2 library, specify the starting search path in PCRE2_ROOT.
+#
+# Static vs. shared
+# -----------------
+# To force using the static library instead of the shared one, one needs
+# to set the variable PCRE2_USE_STATIC_LIBS to ON before calling find_package.
+# If the variable is not set, the static library will be used if only that has
+# been built, otherwise the shared library will be used.
+#
+# The following components are supported: 8BIT, 16BIT, 32BIT and POSIX.
+# They used to be required but not anymore; all available targets will
+# be defined regardless of the requested components.
+# Example:
+# set(PCRE2_USE_STATIC_LIBS ON)
+# find_package(PCRE2 CONFIG)
+#
+# This will define the following variables:
+#
+# PCRE2_FOUND - True if the system has the PCRE2 library.
+# PCRE2_VERSION - The version of the PCRE2 library which was found.
+#
+# and the following imported targets:
+#
+# PCRE2::8BIT - The 8 bit PCRE2 library.
+# PCRE2::16BIT - The 16 bit PCRE2 library.
+# PCRE2::32BIT - The 32 bit PCRE2 library.
+# PCRE2::POSIX - The POSIX PCRE2 library.
+
+@PACKAGE_INIT@
+
+include(CMakeFindDependencyMacro)
+if("@REQUIRE_PTHREAD@") # REQUIRE_PTHREAD
+ find_dependency(Threads)
+endif()
+
+include("${CMAKE_CURRENT_LIST_DIR}/pcre2-targets.cmake")
+
+# Set version
+set(PCRE2_VERSION "@PCRE2_MAJOR@.@PCRE2_MINOR@.0")
+
+# Chooses the linkage of the library to expose in the
+# unsuffixed edition of the target.
+macro(_pcre2_add_component_target component target)
+ # If the static library exists and either PCRE2_USE_STATIC_LIBS
+ # is defined, or the dynamic library does not exist, use the static library.
+ if(NOT TARGET PCRE2::${component})
+ if(TARGET pcre2::pcre2-${target}-static AND (PCRE2_USE_STATIC_LIBS OR NOT TARGET pcre2::pcre2-${target}-shared))
+ add_library(PCRE2::${component} ALIAS pcre2::pcre2-${target}-static)
+ set(PCRE2_${component}_FOUND TRUE)
+ # Otherwise use the dynamic library if it exists.
+ elseif(TARGET pcre2::pcre2-${target}-shared AND NOT PCRE2_USE_STATIC_LIBS)
+ add_library(PCRE2::${component} ALIAS pcre2::pcre2-${target}-shared)
+ set(PCRE2_${component}_FOUND TRUE)
+ endif()
+ if(PCRE2_${component}_FOUND)
+ get_target_property(PCRE2_${component}_LIBRARY PCRE2::${component} IMPORTED_LOCATION)
+ set(PCRE2_LIBRARIES ${PCRE2_LIBRARIES} ${PCRE2_${component}_LIBRARY})
+ endif()
+ endif()
+endmacro()
+_pcre2_add_component_target(8BIT 8)
+_pcre2_add_component_target(16BIT 16)
+_pcre2_add_component_target(32BIT 32)
+_pcre2_add_component_target(POSIX posix)
+
+# When POSIX component has been specified make sure that also 8BIT component is specified.
+set(PCRE2_8BIT_COMPONENT FALSE)
+set(PCRE2_POSIX_COMPONENT FALSE)
+foreach(component ${PCRE2_FIND_COMPONENTS})
+ if(component STREQUAL "8BIT")
+ set(PCRE2_8BIT_COMPONENT TRUE)
+ elseif(component STREQUAL "POSIX")
+ set(PCRE2_POSIX_COMPONENT TRUE)
+ endif()
+endforeach()
+
+if(PCRE2_POSIX_COMPONENT AND NOT PCRE2_8BIT_COMPONENT)
+ message(
+ FATAL_ERROR
+ "The component POSIX is specified while the 8BIT one is not. This is not allowed. Please, also specify the 8BIT component."
+ )
+endif()
+unset(PCRE2_8BIT_COMPONENT)
+unset(PCRE2_POSIX_COMPONENT)
+
+# Check for required components.
+check_required_components("PCRE2")
diff --git a/compile b/compile
new file mode 100755
index 0000000..df363c8
--- /dev/null
+++ b/compile
@@ -0,0 +1,348 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand '-c -o'.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1999-2021 Free Software Foundation, Inc.
+# Written by Tom Tromey .
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to or send patches to
+# .
+
+nl='
+'
+
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent tools from complaining about whitespace usage.
+IFS=" "" $nl"
+
+file_conv=
+
+# func_file_conv build_file lazy
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts. If the determined conversion
+# type is listed in (the comma separated) LAZY, no conversion will
+# take place.
+func_file_conv ()
+{
+ file=$1
+ case $file in
+ / | /[!/]*) # absolute file, and not a UNC file
+ if test -z "$file_conv"; then
+ # lazily determine how to convert abs files
+ case `uname -s` in
+ MINGW*)
+ file_conv=mingw
+ ;;
+ CYGWIN* | MSYS*)
+ file_conv=cygwin
+ ;;
+ *)
+ file_conv=wine
+ ;;
+ esac
+ fi
+ case $file_conv/,$2, in
+ *,$file_conv,*)
+ ;;
+ mingw/*)
+ file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+ ;;
+ cygwin/* | msys/*)
+ file=`cygpath -m "$file" || echo "$file"`
+ ;;
+ wine/*)
+ file=`winepath -w "$file" || echo "$file"`
+ ;;
+ esac
+ ;;
+ esac
+}
+
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+ func_file_conv "$1"
+ if test -z "$lib_path"; then
+ lib_path=$file
+ else
+ lib_path="$lib_path;$file"
+ fi
+ linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+ lib=$1
+ found=no
+ save_IFS=$IFS
+ IFS=';'
+ for dir in $lib_path $LIB
+ do
+ IFS=$save_IFS
+ if $shared && test -f "$dir/$lib.dll.lib"; then
+ found=yes
+ lib=$dir/$lib.dll.lib
+ break
+ fi
+ if test -f "$dir/$lib.lib"; then
+ found=yes
+ lib=$dir/$lib.lib
+ break
+ fi
+ if test -f "$dir/lib$lib.a"; then
+ found=yes
+ lib=$dir/lib$lib.a
+ break
+ fi
+ done
+ IFS=$save_IFS
+
+ if test "$found" != yes; then
+ lib=$lib.lib
+ fi
+}
+
+# func_cl_wrapper cl arg...
+# Adjust compile command to suit cl
+func_cl_wrapper ()
+{
+ # Assume a capable shell
+ lib_path=
+ shared=:
+ linker_opts=
+ for arg
+ do
+ if test -n "$eat"; then
+ eat=
+ else
+ case $1 in
+ -o)
+ # configure might choose to run compile as 'compile cc -o foo foo.c'.
+ eat=1
+ case $2 in
+ *.o | *.[oO][bB][jJ])
+ func_file_conv "$2"
+ set x "$@" -Fo"$file"
+ shift
+ ;;
+ *)
+ func_file_conv "$2"
+ set x "$@" -Fe"$file"
+ shift
+ ;;
+ esac
+ ;;
+ -I)
+ eat=1
+ func_file_conv "$2" mingw
+ set x "$@" -I"$file"
+ shift
+ ;;
+ -I*)
+ func_file_conv "${1#-I}" mingw
+ set x "$@" -I"$file"
+ shift
+ ;;
+ -l)
+ eat=1
+ func_cl_dashl "$2"
+ set x "$@" "$lib"
+ shift
+ ;;
+ -l*)
+ func_cl_dashl "${1#-l}"
+ set x "$@" "$lib"
+ shift
+ ;;
+ -L)
+ eat=1
+ func_cl_dashL "$2"
+ ;;
+ -L*)
+ func_cl_dashL "${1#-L}"
+ ;;
+ -static)
+ shared=false
+ ;;
+ -Wl,*)
+ arg=${1#-Wl,}
+ save_ifs="$IFS"; IFS=','
+ for flag in $arg; do
+ IFS="$save_ifs"
+ linker_opts="$linker_opts $flag"
+ done
+ IFS="$save_ifs"
+ ;;
+ -Xlinker)
+ eat=1
+ linker_opts="$linker_opts $2"
+ ;;
+ -*)
+ set x "$@" "$1"
+ shift
+ ;;
+ *.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
+ func_file_conv "$1"
+ set x "$@" -Tp"$file"
+ shift
+ ;;
+ *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
+ func_file_conv "$1" mingw
+ set x "$@" "$file"
+ shift
+ ;;
+ *)
+ set x "$@" "$1"
+ shift
+ ;;
+ esac
+ fi
+ shift
+ done
+ if test -n "$linker_opts"; then
+ linker_opts="-link$linker_opts"
+ fi
+ exec "$@" $linker_opts
+ exit 1
+}
+
+eat=
+
+case $1 in
+ '')
+ echo "$0: No command. Try '$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand '-c -o'.
+Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file 'INSTALL'.
+
+Report bugs to .
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "compile $scriptversion"
+ exit $?
+ ;;
+ cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
+ icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
+ func_cl_wrapper "$@" # Doesn't return...
+ ;;
+esac
+
+ofile=
+cfile=
+
+for arg
+do
+ if test -n "$eat"; then
+ eat=
+ else
+ case $1 in
+ -o)
+ # configure might choose to run compile as 'compile cc -o foo foo.c'.
+ # So we strip '-o arg' only if arg is an object.
+ eat=1
+ case $2 in
+ *.o | *.obj)
+ ofile=$2
+ ;;
+ *)
+ set x "$@" -o "$2"
+ shift
+ ;;
+ esac
+ ;;
+ *.c)
+ cfile=$1
+ set x "$@" "$1"
+ shift
+ ;;
+ *)
+ set x "$@" "$1"
+ shift
+ ;;
+ esac
+ fi
+ shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+ # If no '-o' option was seen then we might have been invoked from a
+ # pattern rule where we don't need one. That is ok -- this is a
+ # normal compilation that the losing compiler can handle. If no
+ # '.c' file was seen then we are probably linking. That is also
+ # ok.
+ exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use '[/\\:.-]' here to ensure that we don't use the same name
+# that we are using for the .o file. Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
+while true; do
+ if mkdir "$lockdir" >/dev/null 2>&1; then
+ break
+ fi
+ sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+ test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+ test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/config.guess b/config.guess
new file mode 100755
index 0000000..7f76b62
--- /dev/null
+++ b/config.guess
@@ -0,0 +1,1754 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright 1992-2022 Free Software Foundation, Inc.
+
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2022-01-09'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see .
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
+#
+# Please send patches to .
+
+
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX. However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Options:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to ."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2022 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+# Just in case it came from the environment.
+GUESS=
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+tmp=
+# shellcheck disable=SC2172
+trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
+
+set_cc_for_build() {
+ # prevent multiple calls if $tmp is already set
+ test "$tmp" && return 0
+ : "${TMPDIR=/tmp}"
+ # shellcheck disable=SC2039,SC3028
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
+ dummy=$tmp/dummy
+ case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
+ ,,) echo "int x;" > "$dummy.c"
+ for driver in cc gcc c89 c99 ; do
+ if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
+ CC_FOR_BUILD=$driver
+ break
+ fi
+ done
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+ esac
+}
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if test -f /.attbin/uname ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case $UNAME_SYSTEM in
+Linux|GNU|GNU/*)
+ LIBC=unknown
+
+ set_cc_for_build
+ cat <<-EOF > "$dummy.c"
+ #include
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #elif defined(__GLIBC__)
+ LIBC=gnu
+ #else
+ #include
+ /* First heuristic to detect musl libc. */
+ #ifdef __DEFINED_va_list
+ LIBC=musl
+ #endif
+ #endif
+ EOF
+ cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ eval "$cc_set_libc"
+
+ # Second heuristic to detect musl libc.
+ if [ "$LIBC" = unknown ] &&
+ command -v ldd >/dev/null &&
+ ldd --version 2>&1 | grep -q ^musl; then
+ LIBC=musl
+ fi
+
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ if [ "$LIBC" = unknown ]; then
+ LIBC=gnu
+ fi
+ ;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \
+ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
+ echo unknown)`
+ case $UNAME_MACHINE_ARCH in
+ aarch64eb) machine=aarch64_be-unknown ;;
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ earmv*)
+ arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine=${arch}${endian}-unknown
+ ;;
+ *) machine=$UNAME_MACHINE_ARCH-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently (or will in the future) and ABI.
+ case $UNAME_MACHINE_ARCH in
+ earm*)
+ os=netbsdelf
+ ;;
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ELF__
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # Determine ABI tags.
+ case $UNAME_MACHINE_ARCH in
+ earm*)
+ expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+ abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case $UNAME_VERSION in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ GUESS=$machine-${os}${release}${abi-}
+ ;;
+ *:Bitrig:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE
+ ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE
+ ;;
+ *:SecBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE
+ ;;
+ *:LibertyBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE
+ ;;
+ *:MidnightBSD:*:*)
+ GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE
+ ;;
+ *:ekkoBSD:*:*)
+ GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE
+ ;;
+ *:SolidBSD:*:*)
+ GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE
+ ;;
+ *:OS108:*:*)
+ GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE
+ ;;
+ macppc:MirBSD:*:*)
+ GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE
+ ;;
+ *:MirBSD:*:*)
+ GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE
+ ;;
+ *:Sortix:*:*)
+ GUESS=$UNAME_MACHINE-unknown-sortix
+ ;;
+ *:Twizzler:*:*)
+ GUESS=$UNAME_MACHINE-unknown-twizzler
+ ;;
+ *:Redox:*:*)
+ GUESS=$UNAME_MACHINE-unknown-redox
+ ;;
+ mips:OSF1:*.*)
+ GUESS=mips-dec-osf1
+ ;;
+ alpha:OSF1:*:*)
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ trap '' 0
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case $ALPHA_CPU_TYPE in
+ "EV4 (21064)")
+ UNAME_MACHINE=alpha ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE=alpha ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE=alpha ;;
+ "EV5 (21164)")
+ UNAME_MACHINE=alphaev5 ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE=alphaev56 ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE=alphapca56 ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE=alphapca57 ;;
+ "EV6 (21264)")
+ UNAME_MACHINE=alphaev6 ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE=alphaev67 ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE=alphaev69 ;;
+ "EV7 (21364)")
+ UNAME_MACHINE=alphaev7 ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE=alphaev79 ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ GUESS=$UNAME_MACHINE-dec-osf$OSF_REL
+ ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ GUESS=m68k-unknown-sysv4
+ ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ GUESS=$UNAME_MACHINE-unknown-amigaos
+ ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ GUESS=$UNAME_MACHINE-unknown-morphos
+ ;;
+ *:OS/390:*:*)
+ GUESS=i370-ibm-openedition
+ ;;
+ *:z/VM:*:*)
+ GUESS=s390-ibm-zvmoe
+ ;;
+ *:OS400:*:*)
+ GUESS=powerpc-ibm-os400
+ ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ GUESS=arm-acorn-riscix$UNAME_RELEASE
+ ;;
+ arm*:riscos:*:*|arm*:RISCOS:*:*)
+ GUESS=arm-unknown-riscos
+ ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ GUESS=hppa1.1-hitachi-hiuxmpp
+ ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ case `(/bin/universe) 2>/dev/null` in
+ att) GUESS=pyramid-pyramid-sysv3 ;;
+ *) GUESS=pyramid-pyramid-bsd ;;
+ esac
+ ;;
+ NILE*:*:*:dcosx)
+ GUESS=pyramid-pyramid-svr4
+ ;;
+ DRS?6000:unix:4.0:6*)
+ GUESS=sparc-icl-nx6
+ ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) GUESS=sparc-icl-nx7 ;;
+ esac
+ ;;
+ s390x:SunOS:*:*)
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL
+ ;;
+ sun4H:SunOS:5.*:*)
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-hal-solaris2$SUN_REL
+ ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-sun-solaris2$SUN_REL
+ ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ GUESS=i386-pc-auroraux$UNAME_RELEASE
+ ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ set_cc_for_build
+ SUN_ARCH=i386
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH=x86_64
+ fi
+ fi
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=$SUN_ARCH-pc-solaris2$SUN_REL
+ ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=sparc-sun-solaris3$SUN_REL
+ ;;
+ sun4*:SunOS:*:*)
+ case `/usr/bin/arch -k` in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
+ GUESS=sparc-sun-sunos$SUN_REL
+ ;;
+ sun3*:SunOS:*:*)
+ GUESS=m68k-sun-sunos$UNAME_RELEASE
+ ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
+ case `/bin/arch` in
+ sun3)
+ GUESS=m68k-sun-sunos$UNAME_RELEASE
+ ;;
+ sun4)
+ GUESS=sparc-sun-sunos$UNAME_RELEASE
+ ;;
+ esac
+ ;;
+ aushp:SunOS:*:*)
+ GUESS=sparc-auspex-sunos$UNAME_RELEASE
+ ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ GUESS=m68k-atari-mint$UNAME_RELEASE
+ ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ GUESS=m68k-milan-mint$UNAME_RELEASE
+ ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ GUESS=m68k-hades-mint$UNAME_RELEASE
+ ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ GUESS=m68k-unknown-mint$UNAME_RELEASE
+ ;;
+ m68k:machten:*:*)
+ GUESS=m68k-apple-machten$UNAME_RELEASE
+ ;;
+ powerpc:machten:*:*)
+ GUESS=powerpc-apple-machten$UNAME_RELEASE
+ ;;
+ RISC*:Mach:*:*)
+ GUESS=mips-dec-mach_bsd4.3
+ ;;
+ RISC*:ULTRIX:*:*)
+ GUESS=mips-dec-ultrix$UNAME_RELEASE
+ ;;
+ VAX*:ULTRIX*:*:*)
+ GUESS=vax-dec-ultrix$UNAME_RELEASE
+ ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ GUESS=clipper-intergraph-clix$UNAME_RELEASE
+ ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
+#ifdef __cplusplus
+#include /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
+ dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ GUESS=mips-mips-riscos$UNAME_RELEASE
+ ;;
+ Motorola:PowerMAX_OS:*:*)
+ GUESS=powerpc-motorola-powermax
+ ;;
+ Motorola:*:4.3:PL8-*)
+ GUESS=powerpc-harris-powermax
+ ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ GUESS=powerpc-harris-powermax
+ ;;
+ Night_Hawk:Power_UNIX:*:*)
+ GUESS=powerpc-harris-powerunix
+ ;;
+ m88k:CX/UX:7*:*)
+ GUESS=m88k-harris-cxux7
+ ;;
+ m88k:*:4*:R4*)
+ GUESS=m88k-motorola-sysv4
+ ;;
+ m88k:*:3*:R3*)
+ GUESS=m88k-motorola-sysv3
+ ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
+ then
+ if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
+ test "$TARGET_BINARY_INTERFACE"x = x
+ then
+ GUESS=m88k-dg-dgux$UNAME_RELEASE
+ else
+ GUESS=m88k-dg-dguxbcs$UNAME_RELEASE
+ fi
+ else
+ GUESS=i586-dg-dgux$UNAME_RELEASE
+ fi
+ ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ GUESS=m88k-dolphin-sysv3
+ ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ GUESS=m88k-motorola-sysv3
+ ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ GUESS=m88k-tektronix-sysv3
+ ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ GUESS=m68k-tektronix-bsd
+ ;;
+ *:IRIX*:*:*)
+ IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'`
+ GUESS=mips-sgi-irix$IRIX_REL
+ ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ GUESS=i386-ibm-aix
+ ;;
+ ia64:AIX:*:*)
+ if test -x /usr/bin/oslevel ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
+ fi
+ GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV
+ ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
+ #include
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
+ then
+ GUESS=$SYSTEM_NAME
+ else
+ GUESS=rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ GUESS=rs6000-ibm-aix3.2.4
+ else
+ GUESS=rs6000-ibm-aix3.2
+ fi
+ ;;
+ *:AIX:*:[4567])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if test -x /usr/bin/lslpp ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+ else
+ IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
+ fi
+ GUESS=$IBM_ARCH-ibm-aix$IBM_REV
+ ;;
+ *:AIX:*:*)
+ GUESS=rs6000-ibm-aix
+ ;;
+ ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
+ GUESS=romp-ibm-bsd4.4
+ ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to
+ ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ GUESS=rs6000-bull-bosx
+ ;;
+ DPX/2?00:B.O.S.:*:*)
+ GUESS=m68k-bull-sysv3
+ ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ GUESS=m68k-hp-bsd
+ ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ GUESS=m68k-hp-bsd4.4
+ ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+ case $UNAME_MACHINE in
+ 9000/31?) HP_ARCH=m68000 ;;
+ 9000/[34]??) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if test -x /usr/bin/getconf; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case $sc_cpu_version in
+ 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case $sc_kernel_bits in
+ 32) HP_ARCH=hppa2.0n ;;
+ 64) HP_ARCH=hppa2.0w ;;
+ '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if test "$HP_ARCH" = ""; then
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
+
+ #define _HPUX_SOURCE
+ #include
+ #include
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if test "$HP_ARCH" = hppa2.0w
+ then
+ set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
+ then
+ HP_ARCH=hppa2.0w
+ else
+ HP_ARCH=hppa64
+ fi
+ fi
+ GUESS=$HP_ARCH-hp-hpux$HPUX_REV
+ ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
+ GUESS=ia64-hp-hpux$HPUX_REV
+ ;;
+ 3050*:HI-UX:*:*)
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
+ #include
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ GUESS=unknown-hitachi-hiuxwe2
+ ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
+ GUESS=hppa1.1-hp-bsd
+ ;;
+ 9000/8??:4.3bsd:*:*)
+ GUESS=hppa1.0-hp-bsd
+ ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ GUESS=hppa1.0-hp-mpeix
+ ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
+ GUESS=hppa1.1-hp-osf
+ ;;
+ hp8??:OSF1:*:*)
+ GUESS=hppa1.0-hp-osf
+ ;;
+ i*86:OSF1:*:*)
+ if test -x /usr/sbin/sysversion ; then
+ GUESS=$UNAME_MACHINE-unknown-osf1mk
+ else
+ GUESS=$UNAME_MACHINE-unknown-osf1
+ fi
+ ;;
+ parisc*:Lites*:*:*)
+ GUESS=hppa1.1-hp-lites
+ ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ GUESS=c1-convex-bsd
+ ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ GUESS=c34-convex-bsd
+ ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ GUESS=c38-convex-bsd
+ ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ GUESS=c4-convex-bsd
+ ;;
+ CRAY*Y-MP:*:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=ymp-cray-unicos$CRAY_REL
+ ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=t90-cray-unicos$CRAY_REL
+ ;;
+ CRAY*T3E:*:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=alphaev5-cray-unicosmk$CRAY_REL
+ ;;
+ CRAY*SV1:*:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=sv1-cray-unicos$CRAY_REL
+ ;;
+ *:UNICOS/mp:*:*)
+ CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
+ GUESS=craynv-cray-unicosmp$CRAY_REL
+ ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
+ GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+ ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+ GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
+ ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE
+ ;;
+ sparc*:BSD/OS:*:*)
+ GUESS=sparc-unknown-bsdi$UNAME_RELEASE
+ ;;
+ *:BSD/OS:*:*)
+ GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE
+ ;;
+ arm:FreeBSD:*:*)
+ UNAME_PROCESSOR=`uname -p`
+ set_cc_for_build
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi
+ else
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf
+ fi
+ ;;
+ *:FreeBSD:*:*)
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ case $UNAME_PROCESSOR in
+ amd64)
+ UNAME_PROCESSOR=x86_64 ;;
+ i386)
+ UNAME_PROCESSOR=i586 ;;
+ esac
+ FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL
+ ;;
+ i*:CYGWIN*:*)
+ GUESS=$UNAME_MACHINE-pc-cygwin
+ ;;
+ *:MINGW64*:*)
+ GUESS=$UNAME_MACHINE-pc-mingw64
+ ;;
+ *:MINGW*:*)
+ GUESS=$UNAME_MACHINE-pc-mingw32
+ ;;
+ *:MSYS*:*)
+ GUESS=$UNAME_MACHINE-pc-msys
+ ;;
+ i*:PW*:*)
+ GUESS=$UNAME_MACHINE-pc-pw32
+ ;;
+ *:SerenityOS:*:*)
+ GUESS=$UNAME_MACHINE-pc-serenity
+ ;;
+ *:Interix*:*)
+ case $UNAME_MACHINE in
+ x86)
+ GUESS=i586-pc-interix$UNAME_RELEASE
+ ;;
+ authenticamd | genuineintel | EM64T)
+ GUESS=x86_64-unknown-interix$UNAME_RELEASE
+ ;;
+ IA64)
+ GUESS=ia64-unknown-interix$UNAME_RELEASE
+ ;;
+ esac ;;
+ i*:UWIN*:*)
+ GUESS=$UNAME_MACHINE-pc-uwin
+ ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ GUESS=x86_64-pc-cygwin
+ ;;
+ prep*:SunOS:5.*:*)
+ SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
+ GUESS=powerpcle-unknown-solaris2$SUN_REL
+ ;;
+ *:GNU:*:*)
+ # the GNU system
+ GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'`
+ GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'`
+ GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL
+ ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"`
+ GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
+ ;;
+ *:Minix:*:*)
+ GUESS=$UNAME_MACHINE-unknown-minix
+ ;;
+ aarch64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ aarch64_be:Linux:*:*)
+ UNAME_MACHINE=aarch64_be
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ arm*:Linux:*:*)
+ set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ else
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi
+ else
+ GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf
+ fi
+ fi
+ ;;
+ avr32*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ cris:Linux:*:*)
+ GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+ ;;
+ crisv32:Linux:*:*)
+ GUESS=$UNAME_MACHINE-axis-linux-$LIBC
+ ;;
+ e2k:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ frv:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ hexagon:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ i*86:Linux:*:*)
+ GUESS=$UNAME_MACHINE-pc-linux-$LIBC
+ ;;
+ ia64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ k1om:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ m32r*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ m68*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ set_cc_for_build
+ IS_GLIBC=0
+ test x"${LIBC}" = xgnu && IS_GLIBC=1
+ sed 's/^ //' << EOF > "$dummy.c"
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #undef mips64
+ #undef mips64el
+ #if ${IS_GLIBC} && defined(_ABI64)
+ LIBCABI=gnuabi64
+ #else
+ #if ${IS_GLIBC} && defined(_ABIN32)
+ LIBCABI=gnuabin32
+ #else
+ LIBCABI=${LIBC}
+ #endif
+ #endif
+
+ #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+ CPU=mipsisa64r6
+ #else
+ #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+ CPU=mipsisa32r6
+ #else
+ #if defined(__mips64)
+ CPU=mips64
+ #else
+ CPU=mips
+ #endif
+ #endif
+ #endif
+
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ MIPS_ENDIAN=el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ MIPS_ENDIAN=
+ #else
+ MIPS_ENDIAN=
+ #endif
+ #endif
+EOF
+ cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`
+ eval "$cc_set_vars"
+ test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
+ ;;
+ mips64el:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ openrisc*:Linux:*:*)
+ GUESS=or1k-unknown-linux-$LIBC
+ ;;
+ or32:Linux:*:* | or1k*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ padre:Linux:*:*)
+ GUESS=sparc-unknown-linux-$LIBC
+ ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ GUESS=hppa64-unknown-linux-$LIBC
+ ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;;
+ PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;;
+ *) GUESS=hppa-unknown-linux-$LIBC ;;
+ esac
+ ;;
+ ppc64:Linux:*:*)
+ GUESS=powerpc64-unknown-linux-$LIBC
+ ;;
+ ppc:Linux:*:*)
+ GUESS=powerpc-unknown-linux-$LIBC
+ ;;
+ ppc64le:Linux:*:*)
+ GUESS=powerpc64le-unknown-linux-$LIBC
+ ;;
+ ppcle:Linux:*:*)
+ GUESS=powerpcle-unknown-linux-$LIBC
+ ;;
+ riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ GUESS=$UNAME_MACHINE-ibm-linux-$LIBC
+ ;;
+ sh64*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ sh*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ tile*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ vax:Linux:*:*)
+ GUESS=$UNAME_MACHINE-dec-linux-$LIBC
+ ;;
+ x86_64:Linux:*:*)
+ set_cc_for_build
+ LIBCABI=$LIBC
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_X32 >/dev/null
+ then
+ LIBCABI=${LIBC}x32
+ fi
+ fi
+ GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI
+ ;;
+ xtensa*:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ GUESS=i386-sequent-sysv4
+ ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
+ ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ GUESS=$UNAME_MACHINE-pc-os2-emx
+ ;;
+ i*86:XTS-300:*:STOP)
+ GUESS=$UNAME_MACHINE-unknown-stop
+ ;;
+ i*86:atheos:*:*)
+ GUESS=$UNAME_MACHINE-unknown-atheos
+ ;;
+ i*86:syllable:*:*)
+ GUESS=$UNAME_MACHINE-pc-syllable
+ ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+ GUESS=i386-unknown-lynxos$UNAME_RELEASE
+ ;;
+ i*86:*DOS:*:*)
+ GUESS=$UNAME_MACHINE-pc-msdosdjgpp
+ ;;
+ i*86:*:4.*:*)
+ UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL
+ else
+ GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL
+ fi
+ ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL
+ else
+ GUESS=$UNAME_MACHINE-pc-sysv32
+ fi
+ ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configure will decide that
+ # this is a cross-build.
+ GUESS=i586-pc-msdosdjgpp
+ ;;
+ Intel:Mach:3*:*)
+ GUESS=i386-pc-mach3
+ ;;
+ paragon:*:*:*)
+ GUESS=i860-intel-osf1
+ ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4
+ fi
+ ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ GUESS=m68010-convergent-sysv
+ ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ GUESS=m68k-convergent-sysv
+ ;;
+ M680?0:D-NIX:5.3:*)
+ GUESS=m68k-diab-dnix
+ ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ GUESS=m68k-unknown-lynxos$UNAME_RELEASE
+ ;;
+ mc68030:UNIX_System_V:4.*:*)
+ GUESS=m68k-atari-sysv4
+ ;;
+ TSUNAMI:LynxOS:2.*:*)
+ GUESS=sparc-unknown-lynxos$UNAME_RELEASE
+ ;;
+ rs6000:LynxOS:2.*:*)
+ GUESS=rs6000-unknown-lynxos$UNAME_RELEASE
+ ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+ GUESS=powerpc-unknown-lynxos$UNAME_RELEASE
+ ;;
+ SM[BE]S:UNIX_SV:*:*)
+ GUESS=mips-dde-sysv$UNAME_RELEASE
+ ;;
+ RM*:ReliantUNIX-*:*:*)
+ GUESS=mips-sni-sysv4
+ ;;
+ RM*:SINIX-*:*:*)
+ GUESS=mips-sni-sysv4
+ ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ GUESS=$UNAME_MACHINE-sni-sysv4
+ else
+ GUESS=ns32k-sni-sysv
+ fi
+ ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says
+ GUESS=i586-unisys-sysv4
+ ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes .
+ # How about differentiating between stratus architectures? -djm
+ GUESS=hppa1.1-stratus-sysv4
+ ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ GUESS=i860-stratus-sysv4
+ ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ GUESS=$UNAME_MACHINE-stratus-vos
+ ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ GUESS=hppa1.1-stratus-vos
+ ;;
+ mc68*:A/UX:*:*)
+ GUESS=m68k-apple-aux$UNAME_RELEASE
+ ;;
+ news*:NEWS-OS:6*:*)
+ GUESS=mips-sony-newsos6
+ ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if test -d /usr/nec; then
+ GUESS=mips-nec-sysv$UNAME_RELEASE
+ else
+ GUESS=mips-unknown-sysv$UNAME_RELEASE
+ fi
+ ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ GUESS=powerpc-be-beos
+ ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ GUESS=powerpc-apple-beos
+ ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ GUESS=i586-pc-beos
+ ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ GUESS=i586-pc-haiku
+ ;;
+ x86_64:Haiku:*:*)
+ GUESS=x86_64-unknown-haiku
+ ;;
+ SX-4:SUPER-UX:*:*)
+ GUESS=sx4-nec-superux$UNAME_RELEASE
+ ;;
+ SX-5:SUPER-UX:*:*)
+ GUESS=sx5-nec-superux$UNAME_RELEASE
+ ;;
+ SX-6:SUPER-UX:*:*)
+ GUESS=sx6-nec-superux$UNAME_RELEASE
+ ;;
+ SX-7:SUPER-UX:*:*)
+ GUESS=sx7-nec-superux$UNAME_RELEASE
+ ;;
+ SX-8:SUPER-UX:*:*)
+ GUESS=sx8-nec-superux$UNAME_RELEASE
+ ;;
+ SX-8R:SUPER-UX:*:*)
+ GUESS=sx8r-nec-superux$UNAME_RELEASE
+ ;;
+ SX-ACE:SUPER-UX:*:*)
+ GUESS=sxace-nec-superux$UNAME_RELEASE
+ ;;
+ Power*:Rhapsody:*:*)
+ GUESS=powerpc-apple-rhapsody$UNAME_RELEASE
+ ;;
+ *:Rhapsody:*:*)
+ GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE
+ ;;
+ arm64:Darwin:*:*)
+ GUESS=aarch64-apple-darwin$UNAME_RELEASE
+ ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p`
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ if command -v xcode-select > /dev/null 2> /dev/null && \
+ ! xcode-select --print-path > /dev/null 2> /dev/null ; then
+ # Avoid executing cc if there is no toolchain installed as
+ # cc will be a stub that puts up a graphical alert
+ # prompting the user to install developer tools.
+ CC_FOR_BUILD=no_compiler_found
+ else
+ set_cc_for_build
+ fi
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+ if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_PPC >/dev/null
+ then
+ UNAME_PROCESSOR=powerpc
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # uname -m returns i386 or x86_64
+ UNAME_PROCESSOR=$UNAME_MACHINE
+ fi
+ GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE
+ ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = x86; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE
+ ;;
+ *:QNX:*:4*)
+ GUESS=i386-pc-qnx
+ ;;
+ NEO-*:NONSTOP_KERNEL:*:*)
+ GUESS=neo-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSE-*:NONSTOP_KERNEL:*:*)
+ GUESS=nse-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSR-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsr-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSV-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsv-tandem-nsk$UNAME_RELEASE
+ ;;
+ NSX-*:NONSTOP_KERNEL:*:*)
+ GUESS=nsx-tandem-nsk$UNAME_RELEASE
+ ;;
+ *:NonStop-UX:*:*)
+ GUESS=mips-compaq-nonstopux
+ ;;
+ BS2000:POSIX*:*:*)
+ GUESS=bs2000-siemens-sysv
+ ;;
+ DS/*:UNIX_System_V:*:*)
+ GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE
+ ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "${cputype-}" = 386; then
+ UNAME_MACHINE=i386
+ elif test "x${cputype-}" != x; then
+ UNAME_MACHINE=$cputype
+ fi
+ GUESS=$UNAME_MACHINE-unknown-plan9
+ ;;
+ *:TOPS-10:*:*)
+ GUESS=pdp10-unknown-tops10
+ ;;
+ *:TENEX:*:*)
+ GUESS=pdp10-unknown-tenex
+ ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ GUESS=pdp10-dec-tops20
+ ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ GUESS=pdp10-xkl-tops20
+ ;;
+ *:TOPS-20:*:*)
+ GUESS=pdp10-unknown-tops20
+ ;;
+ *:ITS:*:*)
+ GUESS=pdp10-unknown-its
+ ;;
+ SEI:*:*:SEIUX)
+ GUESS=mips-sei-seiux$UNAME_RELEASE
+ ;;
+ *:DragonFly:*:*)
+ DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
+ GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL
+ ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case $UNAME_MACHINE in
+ A*) GUESS=alpha-dec-vms ;;
+ I*) GUESS=ia64-dec-vms ;;
+ V*) GUESS=vax-dec-vms ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ GUESS=i386-pc-xenix
+ ;;
+ i*86:skyos:*:*)
+ SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`
+ GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL
+ ;;
+ i*86:rdos:*:*)
+ GUESS=$UNAME_MACHINE-pc-rdos
+ ;;
+ i*86:Fiwix:*:*)
+ GUESS=$UNAME_MACHINE-pc-fiwix
+ ;;
+ *:AROS:*:*)
+ GUESS=$UNAME_MACHINE-unknown-aros
+ ;;
+ x86_64:VMkernel:*:*)
+ GUESS=$UNAME_MACHINE-unknown-esx
+ ;;
+ amd64:Isilon\ OneFS:*:*)
+ GUESS=x86_64-unknown-onefs
+ ;;
+ *:Unleashed:*:*)
+ GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
+ ;;
+esac
+
+# Do we have a guess based on uname results?
+if test "x$GUESS" != x; then
+ echo "$GUESS"
+ exit
+fi
+
+# No uname command or uname output not recognized.
+set_cc_for_build
+cat > "$dummy.c" <
+#include
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#include
+#if defined(_SIZE_T_) || defined(SIGLOST)
+#include
+#endif
+#endif
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+#include
+#if defined (BSD)
+#if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+#else
+#if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#else
+ printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#endif
+#else
+ printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#else
+#if defined(_SIZE_T_) || defined(SIGLOST)
+ struct utsname un;
+ uname (&un);
+ printf ("vax-dec-ultrix%s\n", un.release); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#if defined(_SIZE_T_) || defined(SIGLOST)
+ struct utsname *un;
+ uname (&un);
+ printf ("mips-dec-ultrix%s\n", un.release); exit (0);
+#else
+ printf ("mips-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
+
+echo "$0: unable to guess system type" >&2
+
+case $UNAME_MACHINE:$UNAME_SYSTEM in
+ mips:Linux | mips64:Linux)
+ # If we got here on MIPS GNU/Linux, output extra information.
+ cat >&2 <&2 <&2 </dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = "$UNAME_MACHINE"
+UNAME_RELEASE = "$UNAME_RELEASE"
+UNAME_SYSTEM = "$UNAME_SYSTEM"
+UNAME_VERSION = "$UNAME_VERSION"
+EOF
+fi
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.sub b/config.sub
new file mode 100755
index 0000000..dba16e8
--- /dev/null
+++ b/config.sub
@@ -0,0 +1,1890 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright 1992-2022 Free Software Foundation, Inc.
+
+# shellcheck disable=SC2006,SC2268 # see below for rationale
+
+timestamp='2022-01-03'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see .
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches to .
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+# The "shellcheck disable" line above the timestamp inhibits complaints
+# about features and limitations of the classic Bourne shell that were
+# superseded or lifted in POSIX. However, this script identifies a wide
+# variety of pre-POSIX systems that do not have POSIX shells at all, and
+# even some reasonably current systems (Solaris 10 as case-in-point) still
+# have a pre-POSIX /bin/sh.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
+
+Canonicalize a configuration name.
+
+Options:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to ."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2022 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo "$1"
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Split fields of configuration type
+# shellcheck disable=SC2162
+saved_IFS=$IFS
+IFS="-" read field1 field2 field3 field4 <&2
+ exit 1
+ ;;
+ *-*-*-*)
+ basic_machine=$field1-$field2
+ basic_os=$field3-$field4
+ ;;
+ *-*-*)
+ # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
+ # parts
+ maybe_os=$field2-$field3
+ case $maybe_os in
+ nto-qnx* | linux-* | uclinux-uclibc* \
+ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
+ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
+ | storm-chaos* | os2-emx* | rtmk-nova*)
+ basic_machine=$field1
+ basic_os=$maybe_os
+ ;;
+ android-linux)
+ basic_machine=$field1-unknown
+ basic_os=linux-android
+ ;;
+ *)
+ basic_machine=$field1-$field2
+ basic_os=$field3
+ ;;
+ esac
+ ;;
+ *-*)
+ # A lone config we happen to match not fitting any pattern
+ case $field1-$field2 in
+ decstation-3100)
+ basic_machine=mips-dec
+ basic_os=
+ ;;
+ *-*)
+ # Second component is usually, but not always the OS
+ case $field2 in
+ # Prevent following clause from handling this valid os
+ sun*os*)
+ basic_machine=$field1
+ basic_os=$field2
+ ;;
+ zephyr*)
+ basic_machine=$field1-unknown
+ basic_os=$field2
+ ;;
+ # Manufacturers
+ dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
+ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
+ | unicom* | ibm* | next | hp | isi* | apollo | altos* \
+ | convergent* | ncr* | news | 32* | 3600* | 3100* \
+ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
+ | ultra | tti* | harris | dolphin | highlevel | gould \
+ | cbm | ns | masscomp | apple | axis | knuth | cray \
+ | microblaze* | sim | cisco \
+ | oki | wec | wrs | winbond)
+ basic_machine=$field1-$field2
+ basic_os=
+ ;;
+ *)
+ basic_machine=$field1
+ basic_os=$field2
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ *)
+ # Convert single-component short-hands not valid as part of
+ # multi-component configurations.
+ case $field1 in
+ 386bsd)
+ basic_machine=i386-pc
+ basic_os=bsd
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ basic_os=scout
+ ;;
+ alliant)
+ basic_machine=fx80-alliant
+ basic_os=
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ basic_os=
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ basic_os=bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ basic_os=sysv
+ ;;
+ amiga)
+ basic_machine=m68k-unknown
+ basic_os=
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ basic_os=amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ basic_os=sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ basic_os=sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ basic_os=bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ basic_os=aros
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ basic_os=aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ basic_os=dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ basic_os=linux
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ basic_os=cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ basic_os=bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ basic_os=bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ basic_os=bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ basic_os=bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ basic_os=bsd
+ ;;
+ cray)
+ basic_machine=j90-cray
+ basic_os=unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ basic_os=
+ ;;
+ da30)
+ basic_machine=m68k-da30
+ basic_os=
+ ;;
+ decstation | pmax | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ basic_os=
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ basic_os=sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ basic_os=dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ basic_os=msdosdjgpp
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ basic_os=ebmon
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ basic_os=ose
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ basic_os=sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ basic_os=go32
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ basic_os=hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ basic_os=xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ basic_os=hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ basic_os=sysv3
+ ;;
+ hp300 | hp300hpux)
+ basic_machine=m68k-hp
+ basic_os=hpux
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ basic_os=bsd
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ basic_os=osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ basic_os=proelf
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ basic_os=mach
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ basic_os=sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ basic_os=linux
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ basic_os=sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ basic_os=sysv
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ basic_os=mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ basic_os=mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ basic_os=mingw32ce
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ basic_os=coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ basic_os=morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ basic_os=moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ basic_os=msdos
+ ;;
+ msys)
+ basic_machine=i686-pc
+ basic_os=msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ basic_os=mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ basic_os=nacl
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ basic_os=sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-pc
+ basic_os=netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ basic_os=linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ basic_os=newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ basic_os=newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ basic_os=sysv
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ basic_os=cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ basic_os=cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ basic_os=nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ basic_os=mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ basic_os=nonstopux
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ basic_os=os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ basic_os=ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ basic_os=os68k
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ basic_os=osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ basic_os=linux
+ ;;
+ psp)
+ basic_machine=mipsallegrexel-sony
+ basic_os=psp
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ basic_os=pw32
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ basic_os=rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ basic_os=rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ basic_os=coff
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ sei)
+ basic_machine=mips-sei
+ basic_os=seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ basic_os=
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ basic_os=sysv2
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ basic_os=
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ basic_os=sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ basic_os=
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ basic_os=sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ basic_os=sunos4
+ ;;
+ sun3)
+ basic_machine=m68k-sun
+ basic_os=
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ basic_os=sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ basic_os=sunos4
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ basic_os=
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ basic_os=sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ basic_os=sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ basic_os=solaris2
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ basic_os=
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ basic_os=unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ basic_os=dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ basic_os=unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ basic_os=unicos
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ basic_os=tops20
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ basic_os=tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ basic_os=sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ basic_os=none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ basic_os=sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ basic_os=vms
+ ;;
+ vsta)
+ basic_machine=i386-pc
+ basic_os=vsta
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ basic_os=vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ basic_os=vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ basic_os=vxworks
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ basic_os=mingw32
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ basic_os=unicos
+ ;;
+ *)
+ basic_machine=$1
+ basic_os=
+ ;;
+ esac
+ ;;
+esac
+
+# Decode 1-component or ad-hoc basic machines
+case $basic_machine in
+ # Here we handle the default manufacturer of certain CPU types. It is in
+ # some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ cpu=hppa1.1
+ vendor=winbond
+ ;;
+ op50n)
+ cpu=hppa1.1
+ vendor=oki
+ ;;
+ op60c)
+ cpu=hppa1.1
+ vendor=oki
+ ;;
+ ibm*)
+ cpu=i370
+ vendor=ibm
+ ;;
+ orion105)
+ cpu=clipper
+ vendor=highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ cpu=m68k
+ vendor=apple
+ ;;
+ pmac | pmac-mpw)
+ cpu=powerpc
+ vendor=apple
+ ;;
+
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ cpu=m68000
+ vendor=att
+ ;;
+ 3b*)
+ cpu=we32k
+ vendor=att
+ ;;
+ bluegene*)
+ cpu=powerpc
+ vendor=ibm
+ basic_os=cnk
+ ;;
+ decsystem10* | dec10*)
+ cpu=pdp10
+ vendor=dec
+ basic_os=tops10
+ ;;
+ decsystem20* | dec20*)
+ cpu=pdp10
+ vendor=dec
+ basic_os=tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ cpu=m68k
+ vendor=motorola
+ ;;
+ dpx2*)
+ cpu=m68k
+ vendor=bull
+ basic_os=sysv3
+ ;;
+ encore | umax | mmax)
+ cpu=ns32k
+ vendor=encore
+ ;;
+ elxsi)
+ cpu=elxsi
+ vendor=elxsi
+ basic_os=${basic_os:-bsd}
+ ;;
+ fx2800)
+ cpu=i860
+ vendor=alliant
+ ;;
+ genix)
+ cpu=ns32k
+ vendor=ns
+ ;;
+ h3050r* | hiux*)
+ cpu=hppa1.1
+ vendor=hitachi
+ basic_os=hiuxwe2
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ cpu=hppa1.0
+ vendor=hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ cpu=m68000
+ vendor=hp
+ ;;
+ hp9k3[2-9][0-9])
+ cpu=m68k
+ vendor=hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ cpu=hppa1.0
+ vendor=hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ cpu=hppa1.1
+ vendor=hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ cpu=hppa1.0
+ vendor=hp
+ ;;
+ i*86v32)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv32
+ ;;
+ i*86v4*)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv4
+ ;;
+ i*86v)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv
+ ;;
+ i*86sol2)
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=solaris2
+ ;;
+ j90 | j90-cray)
+ cpu=j90
+ vendor=cray
+ basic_os=${basic_os:-unicos}
+ ;;
+ iris | iris4d)
+ cpu=mips
+ vendor=sgi
+ case $basic_os in
+ irix*)
+ ;;
+ *)
+ basic_os=irix4
+ ;;
+ esac
+ ;;
+ miniframe)
+ cpu=m68000
+ vendor=convergent
+ ;;
+ *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ cpu=m68k
+ vendor=atari
+ basic_os=mint
+ ;;
+ news-3600 | risc-news)
+ cpu=mips
+ vendor=sony
+ basic_os=newsos
+ ;;
+ next | m*-next)
+ cpu=m68k
+ vendor=next
+ case $basic_os in
+ openstep*)
+ ;;
+ nextstep*)
+ ;;
+ ns2*)
+ basic_os=nextstep2
+ ;;
+ *)
+ basic_os=nextstep3
+ ;;
+ esac
+ ;;
+ np1)
+ cpu=np1
+ vendor=gould
+ ;;
+ op50n-* | op60c-*)
+ cpu=hppa1.1
+ vendor=oki
+ basic_os=proelf
+ ;;
+ pa-hitachi)
+ cpu=hppa1.1
+ vendor=hitachi
+ basic_os=hiuxwe2
+ ;;
+ pbd)
+ cpu=sparc
+ vendor=tti
+ ;;
+ pbb)
+ cpu=m68k
+ vendor=tti
+ ;;
+ pc532)
+ cpu=ns32k
+ vendor=pc532
+ ;;
+ pn)
+ cpu=pn
+ vendor=gould
+ ;;
+ power)
+ cpu=power
+ vendor=ibm
+ ;;
+ ps2)
+ cpu=i386
+ vendor=ibm
+ ;;
+ rm[46]00)
+ cpu=mips
+ vendor=siemens
+ ;;
+ rtpc | rtpc-*)
+ cpu=romp
+ vendor=ibm
+ ;;
+ sde)
+ cpu=mipsisa32
+ vendor=sde
+ basic_os=${basic_os:-elf}
+ ;;
+ simso-wrs)
+ cpu=sparclite
+ vendor=wrs
+ basic_os=vxworks
+ ;;
+ tower | tower-32)
+ cpu=m68k
+ vendor=ncr
+ ;;
+ vpp*|vx|vx-*)
+ cpu=f301
+ vendor=fujitsu
+ ;;
+ w65)
+ cpu=w65
+ vendor=wdc
+ ;;
+ w89k-*)
+ cpu=hppa1.1
+ vendor=winbond
+ basic_os=proelf
+ ;;
+ none)
+ cpu=none
+ vendor=none
+ ;;
+ leon|leon[3-9])
+ cpu=sparc
+ vendor=$basic_machine
+ ;;
+ leon-*|leon[3-9]-*)
+ cpu=sparc
+ vendor=`echo "$basic_machine" | sed 's/-.*//'`
+ ;;
+
+ *-*)
+ # shellcheck disable=SC2162
+ saved_IFS=$IFS
+ IFS="-" read cpu vendor <&2
+ exit 1
+ ;;
+ esac
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $vendor in
+ digital*)
+ vendor=dec
+ ;;
+ commodore*)
+ vendor=cbm
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if test x$basic_os != x
+then
+
+# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
+# set os.
+case $basic_os in
+ gnu/linux*)
+ kernel=linux
+ os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
+ ;;
+ os2-emx)
+ kernel=os2
+ os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
+ ;;
+ nto-qnx*)
+ kernel=nto
+ os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
+ ;;
+ *-*)
+ # shellcheck disable=SC2162
+ saved_IFS=$IFS
+ IFS="-" read kernel os <&2
+ exit 1
+ ;;
+esac
+
+# As a final step for OS-related things, validate the OS-kernel combination
+# (given a valid OS), if there is a kernel.
+case $kernel-$os in
+ linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
+ | linux-musl* | linux-relibc* | linux-uclibc* )
+ ;;
+ uclinux-uclibc* )
+ ;;
+ -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* )
+ # These are just libc implementations, not actual OSes, and thus
+ # require a kernel.
+ echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
+ exit 1
+ ;;
+ kfreebsd*-gnu* | kopensolaris*-gnu*)
+ ;;
+ vxworks-simlinux | vxworks-simwindows | vxworks-spe)
+ ;;
+ nto-qnx*)
+ ;;
+ os2-emx)
+ ;;
+ *-eabi* | *-gnueabi*)
+ ;;
+ -*)
+ # Blank kernel with real OS is always fine.
+ ;;
+ *-*)
+ echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+case $vendor in
+ unknown)
+ case $cpu-$os in
+ *-riscix*)
+ vendor=acorn
+ ;;
+ *-sunos*)
+ vendor=sun
+ ;;
+ *-cnk* | *-aix*)
+ vendor=ibm
+ ;;
+ *-beos*)
+ vendor=be
+ ;;
+ *-hpux*)
+ vendor=hp
+ ;;
+ *-mpeix*)
+ vendor=hp
+ ;;
+ *-hiux*)
+ vendor=hitachi
+ ;;
+ *-unos*)
+ vendor=crds
+ ;;
+ *-dgux*)
+ vendor=dg
+ ;;
+ *-luna*)
+ vendor=omron
+ ;;
+ *-genix*)
+ vendor=ns
+ ;;
+ *-clix*)
+ vendor=intergraph
+ ;;
+ *-mvs* | *-opened*)
+ vendor=ibm
+ ;;
+ *-os400*)
+ vendor=ibm
+ ;;
+ s390-* | s390x-*)
+ vendor=ibm
+ ;;
+ *-ptx*)
+ vendor=sequent
+ ;;
+ *-tpf*)
+ vendor=ibm
+ ;;
+ *-vxsim* | *-vxworks* | *-windiss*)
+ vendor=wrs
+ ;;
+ *-aux*)
+ vendor=apple
+ ;;
+ *-hms*)
+ vendor=hitachi
+ ;;
+ *-mpw* | *-macos*)
+ vendor=apple
+ ;;
+ *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
+ vendor=atari
+ ;;
+ *-vos*)
+ vendor=stratus
+ ;;
+ esac
+ ;;
+esac
+
+echo "$cpu-$vendor-${kernel:+$kernel-}$os"
+exit
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100755
index 0000000..f0deee0
--- /dev/null
+++ b/configure
@@ -0,0 +1,21415 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.71 for PCRE2 10.48.
+#
+#
+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+# Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else $as_nop
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
+as_nl='
+'
+export as_nl
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
+
+# The user is always right.
+if ${PATH_SEPARATOR+false} :; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="as_nop=:
+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else \$as_nop
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
+
+else \$as_nop
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+
+ test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
+ ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+ ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+ PATH=/empty FPATH=/empty; export PATH FPATH
+ test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
+ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null
+then :
+ as_have_required=yes
+else $as_nop
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
+
+else $as_nop
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi
+fi
+
+
+ if test "x$CONFIG_SHELL" != x
+then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno
+then :
+ printf "%s\n" "$0: This script requires a shell more modern than all"
+ printf "%s\n" "$0: the shells that I found on your system."
+ if test ${ZSH_VERSION+y} ; then
+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else $as_nop
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else $as_nop
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ printf "%s\n" "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+
+test -n "$DJDIR" || exec 7<&0 &1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='PCRE2'
+PACKAGE_TARNAME='pcre2'
+PACKAGE_VERSION='10.48'
+PACKAGE_STRING='PCRE2 10.48'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="src/pcre2.h.in"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include
+#ifdef HAVE_STDIO_H
+# include
+#endif
+#ifdef HAVE_STDLIB_H
+# include
+#endif
+#ifdef HAVE_STRING_H
+# include
+#endif
+#ifdef HAVE_INTTYPES_H
+# include
+#endif
+#ifdef HAVE_STDINT_H
+# include
+#endif
+#ifdef HAVE_STRINGS_H
+# include
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include
+#endif
+#ifdef HAVE_UNISTD_H
+# include
+#endif"
+
+ac_header_c_list=
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+PCRE2_EXTRA_LOCAL_SYMS
+LIB_POSTFIX
+CET_CFLAGS
+WITH_GCOV_FALSE
+WITH_GCOV_TRUE
+GCOV_LIBS
+GCOV_CXXFLAGS
+GCOV_CFLAGS
+GENHTML
+LCOV
+SHTOOL
+VALGRIND_LIBS
+VALGRIND_CFLAGS
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
+LIBBZ2
+LIBZ
+DISTCHECK_CONFIGURE_FLAGS
+EXTRA_LIBPCRE2_POSIX_LDFLAGS
+EXTRA_LIBPCRE2_32_LDFLAGS
+EXTRA_LIBPCRE2_16_LDFLAGS
+EXTRA_LIBPCRE2_8_LDFLAGS
+PTHREAD_CFLAGS
+PTHREAD_LIBS
+PTHREAD_CXX
+PTHREAD_CC
+ax_pthread_config
+CPP
+PCRE2POSIX_CFLAG
+PCRE2_STATIC_CFLAG
+LIBREADLINE
+WITH_DIFF_FUZZ_SUPPORT_FALSE
+WITH_DIFF_FUZZ_SUPPORT_TRUE
+WITH_FUZZ_SUPPORT_FALSE
+WITH_FUZZ_SUPPORT_TRUE
+WITH_VALGRIND_FALSE
+WITH_VALGRIND_TRUE
+WITH_EBCDIC_NL25_FALSE
+WITH_EBCDIC_NL25_TRUE
+WITH_EBCDIC_FALSE
+WITH_EBCDIC_TRUE
+WITH_UNICODE_FALSE
+WITH_UNICODE_TRUE
+WITH_JIT_FALSE
+WITH_JIT_TRUE
+WITH_REBUILD_CHARTABLES_FALSE
+WITH_REBUILD_CHARTABLES_TRUE
+WITH_PCRE2_32_FALSE
+WITH_PCRE2_32_TRUE
+WITH_PCRE2_16_FALSE
+WITH_PCRE2_16_TRUE
+WITH_PCRE2_8_FALSE
+WITH_PCRE2_8_TRUE
+enable_pcre2_32
+enable_pcre2_16
+enable_pcre2_8
+PCRE2_DATE
+PCRE2_PRERELEASE
+PCRE2_MINOR
+PCRE2_MAJOR
+HAVE_VISIBILITY
+VISIBILITY_CFLAGS
+LT_SYS_LIBRARY_PATH
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+MANIFEST_TOOL
+RANLIB
+FILECMD
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+EGREP
+GREP
+SED
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+LIBTOOL
+OBJDUMP
+DLLTOOL
+AS
+LN_S
+ac_ct_AR
+AR
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+am__nodep
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
+CSCOPE
+ETAGS
+CTAGS
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL
+am__quote'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_silent_rules
+enable_maintainer_mode
+enable_dependency_tracking
+enable_shared
+enable_static
+with_pic
+enable_fast_install
+with_aix_soname
+with_gnu_ld
+with_sysroot
+enable_libtool_lock
+enable_largefile
+enable_symvers
+enable_pcre8
+enable_pcre16
+enable_pcre32
+enable_pcre2_8
+enable_pcre2_16
+enable_pcre2_32
+enable_debug
+enable_jit
+enable_jit_sealloc
+enable_pcre2grep_jit
+enable_pcre2grep_callout
+enable_pcre2grep_callout_fork
+enable_rebuild_chartables
+enable_unicode
+enable_newline_is_cr
+enable_newline_is_lf
+enable_newline_is_crlf
+enable_newline_is_anycrlf
+enable_newline_is_any
+enable_newline_is_nul
+enable_bsr_anycrlf
+enable_never_backslash_C
+enable_ebcdic
+enable_ebcdic_nl25
+enable_ebcdic_ignoring_compiler
+enable_pcre2grep_libz
+enable_pcre2grep_libbz2
+with_pcre2grep_bufsize
+with_pcre2grep_max_bufsize
+enable_pcre2test_libedit
+enable_pcre2test_libreadline
+with_link_size
+with_max_varlookbehind
+with_parens_nest_limit
+with_heap_limit
+with_match_limit
+with_match_limit_depth
+with_match_limit_recursion
+enable_valgrind
+enable_coverage
+enable_fuzz_support
+enable_diff_fuzz_support
+enable_stack_for_recursion
+enable_percent_zt
+enable_Werror
+enable_errwarn
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+LT_SYS_LIBRARY_PATH
+CPP
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
+VALGRIND_CFLAGS
+VALGRIND_LIBS
+LCOV
+GENHTML'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir runstatedir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures PCRE2 10.48 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/pcre2]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of PCRE2 10.48:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-silent-rules less verbose build output (undo: "make V=1")
+ --disable-silent-rules verbose build output (undo: "make V=0")
+ --enable-maintainer-mode
+ enable make rules and dependencies not useful (and
+ sometimes confusing) to the casual installer
+ --enable-dependency-tracking
+ do not reject slow dependency extractors
+ --disable-dependency-tracking
+ speeds up one-time build
+ --enable-shared[=PKGS] build shared libraries [default=yes]
+ --enable-static[=PKGS] build static libraries [default=yes]
+ --enable-fast-install[=PKGS]
+ optimize for fast installation [default=yes]
+ --disable-libtool-lock avoid locking (might break parallel builds)
+ --disable-largefile omit support for large files
+ --disable-symvers disable library symbol versioning [default=auto]
+
+ --disable-pcre2-8 disable 8 bit character support
+ --enable-pcre2-16 enable 16 bit character support
+ --enable-pcre2-32 enable 32 bit character support
+ --enable-debug enable debugging code
+ --enable-jit enable Just-In-Time compiling support
+ --enable-jit-sealloc enable SELinux compatible execmem allocator in JIT
+ (experimental)
+ --disable-pcre2grep-jit disable JIT support in pcre2grep
+ --disable-pcre2grep-callout
+ disable callout script support in pcre2grep
+ --disable-pcre2grep-callout-fork
+ disable callout script fork support in pcre2grep
+ --enable-rebuild-chartables
+ rebuild character tables in current locale
+ --disable-unicode disable Unicode support
+ --enable-newline-is-cr use CR as newline character
+ --enable-newline-is-lf use LF as newline character (default)
+ --enable-newline-is-crlf
+ use CRLF as newline sequence
+ --enable-newline-is-anycrlf
+ use CR, LF, or CRLF as newline sequence
+ --enable-newline-is-any use any valid Unicode newline sequence
+ --enable-newline-is-nul use NUL (binary zero) as newline character
+ --enable-bsr-anycrlf \R matches only CR, LF, CRLF by default
+ --enable-never-backslash-C
+ use of \C causes an error
+ --enable-ebcdic assume EBCDIC coding rather than ASCII; incompatible
+ with --enable-unicode; use only in (uncommon) EBCDIC
+ environments
+ --enable-ebcdic-nl25 set EBCDIC code for NL to 0x25 instead of 0x15; it
+ implies --enable-ebcdic
+ --enable-ebcdic-ignoring-compiler
+ force EBCDIC 1047 using numeric literals rather than
+ C character literals; it implies --enable-ebcdic
+ --enable-pcre2grep-libz link pcre2grep with libz to handle .gz files
+ --enable-pcre2grep-libbz2
+ link pcre2grep with libbz2 to handle .bz2 files
+ --enable-pcre2test-libedit
+ link pcre2test with libedit
+ --enable-pcre2test-libreadline
+ link pcre2test with libreadline
+ --enable-valgrind enable valgrind support
+ --enable-coverage enable code coverage reports using gcov
+ --enable-fuzz-support enable fuzzer support
+ --enable-diff-fuzz-support
+ enable differential fuzzer support
+ --disable-percent-zt disable the use of z and t formatting modifiers
+ --enable-Werror Add -Werror to CFLAGS (GCC/Clang style); if -Werror
+ is passed to ./configure via CFLAGS it interferes
+ with feature detection
+ --enable-errwarn Add -errwarn=%all to CFLAGS (Sun cc style)
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use
+ both]
+ --with-aix-soname=aix|svr4|both
+ shared library versioning (aka "SONAME") variant to
+ provide on AIX, [default=aix].
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]
+ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the
+ compiler's sysroot if not specified).
+ --with-pcre2grep-bufsize=N
+ pcre2grep initial buffer size (default=20480,
+ minimum=8192)
+ --with-pcre2grep-max-bufsize=N
+ pcre2grep maximum buffer size (default=1048576,
+ minimum=8192)
+ --with-link-size=N internal link size (2, 3, or 4 allowed; default=2)
+ --with-max-varlookbehind=N
+ maximum length of variable lookbehind (default=255)
+ --with-parens-nest-limit=N
+ nested parentheses limit (default=250)
+ --with-heap-limit=N default limit on heap memory (kibibytes,
+ default=20000000)
+ --with-match-limit=N default limit on internal looping (default=10000000)
+ --with-match-limit-depth=N
+ default limit on match tree depth
+ (default=MATCH_LIMIT)
+
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L if you have libraries in a
+ nonstandard directory
+ LIBS libraries to pass to the linker, e.g. -l
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if
+ you have headers in a nonstandard directory
+ LT_SYS_LIBRARY_PATH
+ User-defined run-time library search path.
+ CPP C preprocessor
+ PKG_CONFIG path to pkg-config utility
+ PKG_CONFIG_PATH
+ directories to add to pkg-config's search path
+ PKG_CONFIG_LIBDIR
+ path overriding pkg-config's built-in search path
+ VALGRIND_CFLAGS
+ C compiler flags for VALGRIND, overriding pkg-config
+ VALGRIND_LIBS
+ linker flags for VALGRIND, overriding pkg-config
+ LCOV the ltp lcov program
+ GENHTML the ltp genhtml program
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for configure.gnu first; this name is used for a wrapper for
+ # Metaconfig's "Configure" on case-insensitive file systems.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+PCRE2 configure 10.48
+generated by GNU Autoconf 2.71
+
+Copyright (C) 2021 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest.beam
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext
+then :
+ ac_retval=0
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$3=yes"
+else $as_nop
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_find_intX_t LINENO BITS VAR
+# -----------------------------------
+# Finds a signed integer type with width BITS, setting cache variable VAR
+# accordingly.
+ac_fn_c_find_intX_t ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5
+printf %s "checking for int$2_t... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ eval "$3=no"
+ # Order is important - never check a type that is potentially smaller
+ # than half of the expected target width.
+ for ac_type in int$2_t 'int' 'long int' \
+ 'long long int' 'short int' 'signed char'; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+ enum { N = $2 / 2 - 1 };
+int
+main (void)
+{
+static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+ enum { N = $2 / 2 - 1 };
+int
+main (void)
+{
+static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1)
+ < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))];
+test_array [0] = 0;
+return test_array [0];
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else $as_nop
+ case $ac_type in #(
+ int$2_t) :
+ eval "$3=yes" ;; #(
+ *) :
+ eval "$3=\$ac_type" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ if eval test \"x\$"$3"\" = x"no"
+then :
+
+else $as_nop
+ break
+fi
+ done
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_find_intX_t
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }
+then :
+ ac_retval=0
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case declares $2.
+ For example, HP-UX 11i declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below. */
+
+#include
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main (void)
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval "$3=yes"
+else $as_nop
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else $as_nop
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }
+then :
+ ac_retval=0
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+ac_configure_args_raw=
+for ac_arg
+do
+ case $ac_arg in
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+ *$as_nl*)
+ ac_safe_unquote= ;;
+ *)
+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
+ ac_unsafe_a="$ac_unsafe_z#~"
+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by PCRE2 $as_me 10.48, which was
+generated by GNU Autoconf 2.71. Invocation command line was
+
+ $ $0$ac_configure_args_raw
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ printf "%s\n" "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Sanitize IFS.
+ IFS=" "" $as_nl"
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ printf "%s\n" "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ printf "%s\n" "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ printf "%s\n" "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ printf "%s\n" "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ printf "%s\n" "$as_me: caught signal $ac_signal"
+ printf "%s\n" "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+printf "%s\n" "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
+
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+if test -n "$CONFIG_SITE"; then
+ ac_site_files="$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
+else
+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+fi
+
+for ac_site_file in $ac_site_files
+do
+ case $ac_site_file in #(
+ */*) :
+ ;; #(
+ *) :
+ ac_site_file=./$ac_site_file ;;
+esac
+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Test code for whether the C compiler supports C89 (global declarations)
+ac_c_conftest_c89_globals='
+/* Does the compiler advertise C89 conformance?
+ Do not test the value of __STDC__, because some compilers set it to 0
+ while being otherwise adequately conformant. */
+#if !defined __STDC__
+# error "Compiler does not advertise C89 conformance"
+#endif
+
+#include
+#include
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */
+struct buf { int x; };
+struct buf * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not \xHH hex character constants.
+ These do not provoke an error unfortunately, instead are silently treated
+ as an "x". The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously \x00 != x always comes out true, for an
+ array size at least. It is necessary to write \x00 == 0 to get something
+ that is true only with -std. */
+int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) '\''x'\''
+int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
+ int, int);'
+
+# Test code for whether the C compiler supports C89 (body of main).
+ac_c_conftest_c89_main='
+ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
+'
+
+# Test code for whether the C compiler supports C99 (global declarations)
+ac_c_conftest_c99_globals='
+// Does the compiler advertise C99 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# error "Compiler does not advertise C99 conformance"
+#endif
+
+#include
+extern int puts (const char *);
+extern int printf (const char *, ...);
+extern int dprintf (int, const char *, ...);
+extern void *malloc (size_t);
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+// dprintf is used instead of fprintf to avoid needing to declare
+// FILE and stderr.
+#define debug(...) dprintf (2, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ #error "your preprocessor is broken"
+#endif
+#if BIG_OK
+#else
+ #error "your preprocessor is broken"
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static bool
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str = "";
+ int number = 0;
+ float fnumber = 0;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case '\''s'\'': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case '\''d'\'': // int
+ number = va_arg (args_copy, int);
+ break;
+ case '\''f'\'': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+
+ return *str && number && fnumber;
+}
+'
+
+# Test code for whether the C compiler supports C99 (body of main).
+ac_c_conftest_c99_main='
+ // Check bool.
+ _Bool success = false;
+ success |= (argc != 0);
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[0] = argv[0][0];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
+ || dynamic_array[ni.number - 1] != 543);
+'
+
+# Test code for whether the C compiler supports C11 (global declarations)
+ac_c_conftest_c11_globals='
+// Does the compiler advertise C11 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif
+
+// Check _Alignas.
+char _Alignas (double) aligned_as_double;
+char _Alignas (0) no_special_alignment;
+extern char aligned_as_int;
+char _Alignas (0) _Alignas (int) aligned_as_int;
+
+// Check _Alignof.
+enum
+{
+ int_alignment = _Alignof (int),
+ int_array_alignment = _Alignof (int[100]),
+ char_alignment = _Alignof (char)
+};
+_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
+
+// Check _Noreturn.
+int _Noreturn does_not_return (void) { for (;;) continue; }
+
+// Check _Static_assert.
+struct test_static_assert
+{
+ int x;
+ _Static_assert (sizeof (int) <= sizeof (long int),
+ "_Static_assert does not work in struct");
+ long int y;
+};
+
+// Check UTF-8 literals.
+#define u8 syntax error!
+char const utf8_literal[] = u8"happens to be ASCII" "another string";
+
+// Check duplicate typedefs.
+typedef long *long_ptr;
+typedef long int *long_ptr;
+typedef long_ptr long_ptr;
+
+// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
+struct anonymous
+{
+ union {
+ struct { int i; int j; };
+ struct { int k; long int l; } w;
+ };
+ int m;
+} v1;
+'
+
+# Test code for whether the C compiler supports C11 (body of main).
+ac_c_conftest_c11_main='
+ _Static_assert ((offsetof (struct anonymous, i)
+ == offsetof (struct anonymous, w.k)),
+ "Anonymous union alignment botch");
+ v1.i = 2;
+ v1.w.k = 5;
+ ok |= v1.i != 5;
+'
+
+# Test code for whether the C compiler supports C11 (complete).
+ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+${ac_c_conftest_c11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ ${ac_c_conftest_c11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C99 (complete).
+ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C89 (complete).
+ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ return ok;
+}
+"
+
+as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
+as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
+as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
+as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
+as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
+as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
+as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
+as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
+as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
+as_fn_append ac_header_c_list " wchar.h wchar_h HAVE_WCHAR_H"
+as_fn_append ac_header_c_list " minix/config.h minix_config_h HAVE_MINIX_CONFIG_H"
+
+# Auxiliary files required by this configure script.
+ac_aux_files="config.guess config.sub ltmain.sh ar-lib compile missing install-sh"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.."
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
+ ac_aux_dir_found=yes
+ ac_install_sh=
+ for ac_aux in $ac_aux_files
+ do
+ # As a special case, if "install-sh" is required, that requirement
+ # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+ # and $ac_install_sh is set appropriately for whichever one is found.
+ if test x"$ac_aux" = x"install-sh"
+ then
+ if test -f "${as_dir}install-sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
+ ac_install_sh="${as_dir}install-sh -c"
+ elif test -f "${as_dir}install.sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
+ ac_install_sh="${as_dir}install.sh -c"
+ elif test -f "${as_dir}shtool"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
+ ac_install_sh="${as_dir}shtool install -c"
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+ else
+ break
+ fi
+ fi
+ else
+ if test -f "${as_dir}${ac_aux}"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+ else
+ break
+ fi
+ fi
+ fi
+ done
+ if test "$ac_aux_dir_found" = yes; then
+ ac_aux_dir="$as_dir"
+ break
+ fi
+ ac_first_candidate=false
+
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+ ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+ ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+ ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+ and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+am__api_version='1.16'
+
+
+
+ # Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+printf %s "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test ${ac_cv_path_install+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ # Account for fact that we put trailing slashes in our PATH walk.
+case $as_dir in #((
+ ./ | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test ${ac_cv_path_install+y}; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+printf "%s\n" "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+printf %s "checking whether build environment is sane... " >&6; }
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[\\\"\#\$\&\'\`$am_lf]*)
+ as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+ *[\\\"\#\$\&\'\`$am_lf\ \ ]*)
+ as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ am_has_slept=no
+ for am_try in 1 2; do
+ echo "timestamp, slept: $am_has_slept" > conftest.file
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ as_fn_error $? "ls -t appears to fail. Make sure there is not a broken
+ alias in your environment" "$LINENO" 5
+ fi
+ if test "$2" = conftest.file || test $am_try -eq 2; then
+ break
+ fi
+ # Just in case.
+ sleep 1
+ am_has_slept=yes
+ done
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+ ( sleep 1 ) &
+ am_sleep_pid=$!
+fi
+
+rm -f conftest.file
+
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"`
+
+
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+
+
+ if test x"${MISSING+set}" != xset; then
+ MISSING="\${SHELL} '$am_aux_dir/missing'"
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+ am_missing_run="$MISSING "
+else
+ am_missing_run=
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
+printf "%s\n" "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip". However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_STRIP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+printf "%s\n" "$STRIP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_STRIP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+printf "%s\n" "$ac_ct_STRIP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5
+printf %s "checking for a race-free mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+ if test ${ac_cv_path_mkdir+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in mkdir gmkdir; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue
+ case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #(
+ 'mkdir ('*'coreutils) '* | \
+ 'BusyBox '* | \
+ 'mkdir (fileutils) '4.1*)
+ ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext
+ break 3;;
+ esac
+ done
+ done
+ done
+IFS=$as_save_IFS
+
+fi
+
+ test -d ./--version && rmdir ./--version
+ if test ${ac_cv_path_mkdir+y}; then
+ MKDIR_P="$ac_cv_path_mkdir -p"
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for MKDIR_P within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ MKDIR_P="$ac_install_sh -d"
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+printf "%s\n" "$MKDIR_P" >&6; }
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_AWK+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AWK="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+printf "%s\n" "$AWK" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval test \${ac_cv_prog_make_${ac_make}_set+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ SET_MAKE=
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# Check whether --enable-silent-rules was given.
+if test ${enable_silent_rules+y}
+then :
+ enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+ yes) AM_DEFAULT_VERBOSITY=0;;
+ no) AM_DEFAULT_VERBOSITY=1;;
+ *) AM_DEFAULT_VERBOSITY=1;;
+esac
+am_make=${MAKE-make}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+printf %s "checking whether $am_make supports nested variables... " >&6; }
+if test ${am_cv_make_support_nested_variables+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if printf "%s\n" 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+printf "%s\n" "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ am__isrc=' -I$(srcdir)'
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='pcre2'
+ VERSION='10.48'
+
+
+printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
+
+
+printf "%s\n" "#define VERSION \"$VERSION\"" >>confdefs.h
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# For better backward compatibility. To be removed once Automake 1.9.x
+# dies out for good. For more background, see:
+#
+#
+mkdir_p='$(MKDIR_P)'
+
+# We need awk for the "check" target (and possibly the TAP driver). The
+# system "awk" is bad on some platforms.
+# Always define AMTAR for backward compatibility. Yes, it's still used
+# in the wild :-( We should find a proper way to deprecate it ...
+AMTAR='$${TAR-tar}'
+
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar pax cpio none'
+
+am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+
+
+
+
+
+# Variables for tags utilities; see am/tags.am
+if test -z "$CTAGS"; then
+ CTAGS=ctags
+fi
+
+if test -z "$ETAGS"; then
+ ETAGS=etags
+fi
+
+if test -z "$CSCOPE"; then
+ CSCOPE=cscope
+fi
+
+
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes. So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+ cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present. This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard:
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message. This
+can help us improve future automake versions.
+
+END
+ if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+ echo 'Configuration will proceed anyway, since you have set the' >&2
+ echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+ echo >&2
+ else
+ cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: .
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+ as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
+ fi
+fi
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+printf %s "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+ # Check whether --enable-maintainer-mode was given.
+if test ${enable_maintainer_mode+y}
+then :
+ enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else $as_nop
+ USE_MAINTAINER_MODE=no
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+printf "%s\n" "$USE_MAINTAINER_MODE" >&6; }
+ if test $USE_MAINTAINER_MODE = yes; then
+ MAINTAINER_MODE_TRUE=
+ MAINTAINER_MODE_FALSE='#'
+else
+ MAINTAINER_MODE_TRUE='#'
+ MAINTAINER_MODE_FALSE=
+fi
+
+ MAINT=$MAINTAINER_MODE_TRUE
+
+
+# Check whether --enable-silent-rules was given.
+if test ${enable_silent_rules+y}
+then :
+ enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+ yes) AM_DEFAULT_VERBOSITY=0;;
+ no) AM_DEFAULT_VERBOSITY=1;;
+ *) AM_DEFAULT_VERBOSITY=0;;
+esac
+am_make=${MAKE-make}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+printf %s "checking whether $am_make supports nested variables... " >&6; }
+if test ${am_cv_make_support_nested_variables+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if printf "%s\n" 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+printf "%s\n" "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+ac_config_headers="$ac_config_headers src/config.h"
+
+
+# This was added at the suggestion of libtoolize (03-Jan-10)
+
+
+# The default CFLAGS in Autoconf are "-g -O2" for gcc and just "-g" for any
+# other compiler. There doesn't seem to be a standard way of getting rid of the
+# -g (which I don't think is needed for a production library). This fudge seems
+# to achieve the necessary. First, we remember the externally set values of
+# CFLAGS. Then call the AC_PROG_CC macro to find the compiler - if CFLAGS is
+# not set, it will be set to Autoconf's defaults. Afterwards, if the original
+# values were not set, remove the -g from the Autoconf defaults.
+
+remember_set_CFLAGS="$CFLAGS"
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+fi
+
+
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion -version; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+printf %s "checking whether the C compiler works... " >&6; }
+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else $as_nop
+ ac_file=''
+fi
+if test -z "$ac_file"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+printf %s "checking for C compiler default output file name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+printf "%s\n" "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+printf %s "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+printf "%s\n" "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+int
+main (void)
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+printf %s "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+printf "%s\n" "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+printf %s "checking for suffix of object files... " >&6; }
+if test ${ac_cv_objext+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+printf "%s\n" "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_compiler_gnu=yes
+else $as_nop
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+y}
+ac_save_CFLAGS=$CFLAGS
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_g=yes
+else $as_nop
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else $as_nop
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c11=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
+
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+ CC="$CC $ac_cv_prog_cc_c11"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+ ac_prog_cc_stdc=c11
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
+
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c99" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+ CC="$CC $ac_cv_prog_cc_c99"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+ ac_prog_cc_stdc=c99
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c89_program
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
+
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c89" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+ CC="$CC $ac_cv_prog_cc_c89"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+ ac_prog_cc_stdc=c89
+fi
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+printf %s "checking whether $CC understands -c and -o together... " >&6; }
+if test ${am_cv_prog_cc_c_o+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ # Make sure it works both with $CC and with simple cc.
+ # Following AC_PROG_CC_C_O, we do the test twice because some
+ # compilers refuse to overwrite an existing .o file with -o,
+ # though they will create one.
+ am_cv_prog_cc_c_o=yes
+ for am_i in 1 2; do
+ if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+ ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } \
+ && test -f conftest2.$ac_objext; then
+ : OK
+ else
+ am_cv_prog_cc_c_o=no
+ break
+ fi
+ done
+ rm -f core conftest*
+ unset am_i
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+printf "%s\n" "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
+printf %s "checking whether ${MAKE-make} supports the include directive... " >&6; }
+cat > confinc.mk << 'END'
+am__doit:
+ @echo this is the am__doit target >confinc.out
+.PHONY: am__doit
+END
+am__include="#"
+am__quote=
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+ { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
+ (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ case $?:`cat confinc.out 2>/dev/null` in #(
+ '0:this is the am__doit target') :
+ case $s in #(
+ BSD) :
+ am__include='.include' am__quote='"' ;; #(
+ *) :
+ am__include='include' am__quote='' ;;
+esac ;; #(
+ *) :
+ ;;
+esac
+ if test "$am__include" != "#"; then
+ _am_result="yes ($s style)"
+ break
+ fi
+done
+rm -f confinc.* confmf.*
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
+printf "%s\n" "${_am_result}" >&6; }
+
+# Check whether --enable-dependency-tracking was given.
+if test ${enable_dependency_tracking+y}
+then :
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+ am__nodep='_no'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+
+depcc="$CC" am_compiler_list=
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+printf %s "checking dependency style of $depcc... " >&6; }
+if test ${am_cv_CC_dependencies_compiler_type+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+
+
+ac_header= ac_cache=
+for ac_item in $ac_header_c_list
+do
+ if test $ac_cache; then
+ ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
+ if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
+ printf "%s\n" "#define $ac_item 1" >> confdefs.h
+ fi
+ ac_header= ac_cache=
+ elif test $ac_header; then
+ ac_cache=$ac_item
+ else
+ ac_header=$ac_item
+ fi
+done
+
+
+
+
+
+
+
+
+if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
+then :
+
+printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
+printf %s "checking whether it is safe to define __EXTENSIONS__... " >&6; }
+if test ${ac_cv_safe_to_define___extensions__+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+# define __EXTENSIONS__ 1
+ $ac_includes_default
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_safe_to_define___extensions__=yes
+else $as_nop
+ ac_cv_safe_to_define___extensions__=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
+printf "%s\n" "$ac_cv_safe_to_define___extensions__" >&6; }
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether _XOPEN_SOURCE should be defined" >&5
+printf %s "checking whether _XOPEN_SOURCE should be defined... " >&6; }
+if test ${ac_cv_should_define__xopen_source+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_should_define__xopen_source=no
+ if test $ac_cv_header_wchar_h = yes
+then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include
+ mbstate_t x;
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #define _XOPEN_SOURCE 500
+ #include
+ mbstate_t x;
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_should_define__xopen_source=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_should_define__xopen_source" >&5
+printf "%s\n" "$ac_cv_should_define__xopen_source" >&6; }
+
+ printf "%s\n" "#define _ALL_SOURCE 1" >>confdefs.h
+
+ printf "%s\n" "#define _DARWIN_C_SOURCE 1" >>confdefs.h
+
+ printf "%s\n" "#define _GNU_SOURCE 1" >>confdefs.h
+
+ printf "%s\n" "#define _HPUX_ALT_XOPEN_SOCKET_API 1" >>confdefs.h
+
+ printf "%s\n" "#define _NETBSD_SOURCE 1" >>confdefs.h
+
+ printf "%s\n" "#define _OPENBSD_SOURCE 1" >>confdefs.h
+
+ printf "%s\n" "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_IEC_60559_BFP_EXT__ 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_IEC_60559_DFP_EXT__ 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_IEC_60559_TYPES_EXT__ 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_LIB_EXT2__ 1" >>confdefs.h
+
+ printf "%s\n" "#define __STDC_WANT_MATH_SPEC_FUNCS__ 1" >>confdefs.h
+
+ printf "%s\n" "#define _TANDEM_SOURCE 1" >>confdefs.h
+
+ if test $ac_cv_header_minix_config_h = yes
+then :
+ MINIX=yes
+ printf "%s\n" "#define _MINIX 1" >>confdefs.h
+
+ printf "%s\n" "#define _POSIX_SOURCE 1" >>confdefs.h
+
+ printf "%s\n" "#define _POSIX_1_SOURCE 2" >>confdefs.h
+
+else $as_nop
+ MINIX=
+fi
+ if test $ac_cv_safe_to_define___extensions__ = yes
+then :
+ printf "%s\n" "#define __EXTENSIONS__ 1" >>confdefs.h
+
+fi
+ if test $ac_cv_should_define__xopen_source = yes
+then :
+ printf "%s\n" "#define _XOPEN_SOURCE 500" >>confdefs.h
+
+fi
+
+
+if test "x$remember_set_CFLAGS" = "x"
+then
+ if test "$CFLAGS" = "-g -O2"
+ then
+ CFLAGS="-O2"
+ elif test "$CFLAGS" = "-g"
+ then
+ CFLAGS=""
+ fi
+fi
+
+# This is a new thing required to stop a warning from automake 1.12
+
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in ar lib "link -lib"
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_AR+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+printf "%s\n" "$AR" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$AR" && break
+ done
+fi
+if test -z "$AR"; then
+ ac_ct_AR=$AR
+ for ac_prog in ar lib "link -lib"
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_AR+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+printf "%s\n" "$ac_ct_AR" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_AR" && break
+done
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+fi
+
+: ${AR=ar}
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5
+printf %s "checking the archiver ($AR) interface... " >&6; }
+if test ${am_cv_ar_interface+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ am_cv_ar_interface=ar
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int some_variable = 0;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
+ (eval $am_ar_try) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=ar
+ else
+ am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
+ (eval $am_ar_try) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=lib
+ else
+ am_cv_ar_interface=unknown
+ fi
+ fi
+ rm -f conftest.lib libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5
+printf "%s\n" "$am_cv_ar_interface" >&6; }
+
+case $am_cv_ar_interface in
+ar)
+ ;;
+lib)
+ # Microsoft lib, so override with the ar-lib wrapper script.
+ # FIXME: It is wrong to rewrite AR.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__AR in this case,
+ # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something
+ # similar.
+ AR="$am_aux_dir/ar-lib $AR"
+ ;;
+unknown)
+ as_fn_error $? "could not determine $AR interface" "$LINENO" 5
+ ;;
+esac
+
+
+# Check for a 64-bit integer type
+ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t"
+case $ac_cv_c_int64_t in #(
+ no|yes) ;; #(
+ *)
+
+printf "%s\n" "#define int64_t $ac_cv_c_int64_t" >>confdefs.h
+;;
+esac
+
+
+# Check for xlc which has some special (broken/non-standard) behaviour on z/OS.
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OS/390 (z/OS)" >&5
+printf %s "checking for OS/390 (z/OS)... " >&6; }
+if test ${pcre2_cv_os390+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "`uname`" = "OS/390"; then
+ pcre2_cv_os390=yes
+ else
+ pcre2_cv_os390=no
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pcre2_cv_os390" >&5
+printf "%s\n" "$pcre2_cv_os390" >&6; }
+ if test "$pcre2_cv_os390" = "yes"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports -qhaltonmsg=CCN3296" >&5
+printf %s "checking whether the compiler supports -qhaltonmsg=CCN3296... " >&6; }
+if test ${pcre2_cv_xlc_qhaltonmsg_support+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -qhaltonmsg=CCN3296"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ pcre2_cv_xlc_qhaltonmsg_support=yes
+else $as_nop
+ pcre2_cv_xlc_qhaltonmsg_support=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pcre2_cv_xlc_qhaltonmsg_support" >&5
+printf "%s\n" "$pcre2_cv_xlc_qhaltonmsg_support" >&6; }
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether non-existent headers fail the compile" >&5
+printf %s "checking whether non-existent headers fail the compile... " >&6; }
+if test ${pcre2_cv_xlc_nonexistent_fatal+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ pcre2_cv_xlc_nonexistent_fatal=no
+else $as_nop
+ pcre2_cv_xlc_nonexistent_fatal=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pcre2_cv_xlc_nonexistent_fatal" >&5
+printf "%s\n" "$pcre2_cv_xlc_nonexistent_fatal" >&6; }
+
+ if test "$pcre2_cv_xlc_nonexistent_fatal" = "no" && test "$pcre2_cv_xlc_qhaltonmsg_support" = "yes"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -qhaltonmsg=CCN3296 fixes the non-existent-header issue" >&5
+printf %s "checking whether -qhaltonmsg=CCN3296 fixes the non-existent-header issue... " >&6; }
+if test ${pcre2_cv_xlc_qhaltonmsg_fixes+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -qhaltonmsg=CCN3296"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ pcre2_cv_xlc_qhaltonmsg_fixes=no
+else $as_nop
+ pcre2_cv_xlc_qhaltonmsg_fixes=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pcre2_cv_xlc_qhaltonmsg_fixes" >&5
+printf "%s\n" "$pcre2_cv_xlc_qhaltonmsg_fixes" >&6; }
+
+ if test "$pcre2_cv_xlc_qhaltonmsg_fixes" = "no"; then
+ as_fn_error $? "-qhaltonmsg=CCN3296 not effective on non-existent headers" "$LINENO" 5
+ fi
+
+ CFLAGS="$CFLAGS -qhaltonmsg=CCN3296"
+ fi
+
+ fi
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+printf %s "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+printf "%s\n" "no, using $LN_S" >&6; }
+fi
+
+
+# As well as LT_INIT, we use LT_OUTPUT so that PCRE2_CHECK_VSCRIPT can invoke
+# libtool to test version scripts correctly.
+case `pwd` in
+ *\ * | *\ *)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+printf "%s\n" "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.4.7'
+macro_revision='2.4.7'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain=$ac_aux_dir/ltmain.sh
+
+
+
+ # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+printf %s "checking how to print strings... " >&6; }
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='printf %s\n'
+else
+ # Use this function as a fallback that always works.
+ func_fallback_echo ()
+ {
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+ }
+ ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+ $ECHO ""
+}
+
+case $ECHO in
+ printf*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+printf "%s\n" "printf" >&6; } ;;
+ print*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+printf "%s\n" "print -r" >&6; } ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+printf "%s\n" "cat" >&6; } ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+printf %s "checking for a sed that does not truncate output... " >&6; }
+if test ${ac_cv_path_SED+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+ for ac_i in 1 2 3 4 5 6 7; do
+ ac_script="$ac_script$as_nl$ac_script"
+ done
+ echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+ { ac_script=; unset ac_script;}
+ if test -z "$SED"; then
+ ac_path_SED_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in sed gsed
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_SED="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_SED" || continue
+# Check for GNU ac_path_SED and select it if it is found.
+ # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+ ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" '' >> "conftest.nl"
+ "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_SED_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_SED="$ac_path_SED"
+ ac_path_SED_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_SED_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_SED"; then
+ as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
+ fi
+else
+ ac_cv_path_SED=$SED
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+printf "%s\n" "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+ rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+printf %s "checking for grep that handles long lines and -e... " >&6; }
+if test ${ac_cv_path_GREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in grep ggrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+printf "%s\n" "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+printf %s "checking for egrep... " >&6; }
+if test ${ac_cv_path_EGREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in egrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+printf "%s\n" "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+printf %s "checking for fgrep... " >&6; }
+if test ${ac_cv_path_FGREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+ then ac_cv_path_FGREP="$GREP -F"
+ else
+ if test -z "$FGREP"; then
+ ac_path_FGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in fgrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_FGREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_FGREP" || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+ # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'FGREP' >> "conftest.nl"
+ "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_FGREP="$ac_path_FGREP"
+ ac_path_FGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_FGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_FGREP"; then
+ as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_FGREP=$FGREP
+fi
+
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+printf "%s\n" "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test ${with_gnu_ld+y}
+then :
+ withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
+else $as_nop
+ with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test yes = "$GCC"; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+printf %s "checking for ld used by $CC... " >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return, which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD=$ac_prog
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test yes = "$with_gnu_ld"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+printf %s "checking for GNU ld... " >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+printf %s "checking for non-GNU ld... " >&6; }
+fi
+if test ${lt_cv_path_LD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -z "$LD"; then
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD=$ac_dir/$ac_prog
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 &5
+printf "%s\n" "$LD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+printf %s "checking if the linker ($LD) is GNU ld... " >&6; }
+if test ${lt_cv_prog_gnu_ld+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 &5
+printf "%s\n" "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+printf %s "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if test ${lt_cv_path_NM+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM=$NM
+else
+ lt_nm_to_check=${ac_tool_prefix}nm
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm=$ac_dir/$lt_tmp_nm
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the 'sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
+ case $build_os in
+ mingw*) lt_bad_file=conftest.nm/nofile ;;
+ *) lt_bad_file=/dev/null ;;
+ esac
+ case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
+ *$lt_bad_file* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break 2
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break 2
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS=$lt_save_ifs
+ done
+ : ${lt_cv_path_NM=no}
+fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+printf "%s\n" "$lt_cv_path_NM" >&6; }
+if test no != "$lt_cv_path_NM"; then
+ NM=$lt_cv_path_NM
+else
+ # Didn't find any BSD compatible name lister, look for dumpbin.
+ if test -n "$DUMPBIN"; then :
+ # Let the user override the test.
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in dumpbin "link -dump"
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DUMPBIN+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$DUMPBIN"; then
+ ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+printf "%s\n" "$DUMPBIN" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$DUMPBIN" && break
+ done
+fi
+if test -z "$DUMPBIN"; then
+ ac_ct_DUMPBIN=$DUMPBIN
+ for ac_prog in dumpbin "link -dump"
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DUMPBIN+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_DUMPBIN"; then
+ ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+printf "%s\n" "$ac_ct_DUMPBIN" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_DUMPBIN" && break
+done
+
+ if test "x$ac_ct_DUMPBIN" = x; then
+ DUMPBIN=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DUMPBIN=$ac_ct_DUMPBIN
+ fi
+fi
+
+ case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
+ *COFF*)
+ DUMPBIN="$DUMPBIN -symbols -headers"
+ ;;
+ *)
+ DUMPBIN=:
+ ;;
+ esac
+ fi
+
+ if test : != "$DUMPBIN"; then
+ NM=$DUMPBIN
+ fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+printf %s "checking the name lister ($NM) interface... " >&6; }
+if test ${lt_cv_nm_interface+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_nm_interface="BSD nm"
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
+ (eval "$ac_compile" 2>conftest.err)
+ cat conftest.err >&5
+ (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+ cat conftest.err >&5
+ (eval echo "\"\$as_me:$LINENO: output\"" >&5)
+ cat conftest.out >&5
+ if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+ lt_cv_nm_interface="MS dumpbin"
+ fi
+ rm -f conftest*
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+printf "%s\n" "$lt_cv_nm_interface" >&6; }
+
+# find the maximum length of command line arguments
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+printf %s "checking the maximum length of command line arguments... " >&6; }
+if test ${lt_cv_sys_max_cmd_len+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ i=0
+ teststring=ABCD
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw* | cegcc*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ mint*)
+ # On MiNT this can take a long time and run out of memory.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ os2*)
+ # The test takes a long time on OS/2.
+ lt_cv_sys_max_cmd_len=8192
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[ ]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+ if test -n "$lt_cv_sys_max_cmd_len" && \
+ test undefined != "$lt_cv_sys_max_cmd_len"; then
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ else
+ # Make teststring a little bigger before we do anything with it.
+ # a 1K string should be a reasonable start.
+ for i in 1 2 3 4 5 6 7 8; do
+ teststring=$teststring$teststring
+ done
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ while { test X`env echo "$teststring$teststring" 2>/dev/null` \
+ = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+ test 17 != "$i" # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ # Only check the string length outside the loop.
+ lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on
+ # massive amounts of additional arguments before passing them to the
+ # linker. It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ fi
+ ;;
+ esac
+
+fi
+
+if test -n "$lt_cv_sys_max_cmd_len"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+printf "%s\n" "$lt_cv_sys_max_cmd_len" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5
+printf "%s\n" "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ lt_unset=unset
+else
+ lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ lt_SP2NL='tr \040 \012'
+ lt_NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ lt_SP2NL='tr \100 \n'
+ lt_NL2SP='tr \r\n \100\100'
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5
+printf %s "checking how to convert $build file names to $host format... " >&6; }
+if test ${lt_cv_to_host_file_cmd+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ case $host in
+ *-*-mingw* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+ ;;
+ *-*-cygwin* )
+ lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+ ;;
+ * ) # otherwise, assume *nix
+ lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+ ;;
+ esac
+ ;;
+ *-*-cygwin* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+ ;;
+ *-*-cygwin* )
+ lt_cv_to_host_file_cmd=func_convert_file_noop
+ ;;
+ * ) # otherwise, assume *nix
+ lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+ ;;
+ esac
+ ;;
+ * ) # unhandled hosts (and "normal" native builds)
+ lt_cv_to_host_file_cmd=func_convert_file_noop
+ ;;
+esac
+
+fi
+
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5
+printf "%s\n" "$lt_cv_to_host_file_cmd" >&6; }
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5
+printf %s "checking how to convert $build file names to toolchain format... " >&6; }
+if test ${lt_cv_to_tool_file_cmd+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ #assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+ *-*-mingw* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+ ;;
+ esac
+ ;;
+esac
+
+fi
+
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5
+printf "%s\n" "$lt_cv_to_tool_file_cmd" >&6; }
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+printf %s "checking for $LD option to reload object files... " >&6; }
+if test ${lt_cv_ld_reload_flag+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_ld_reload_flag='-r'
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+printf "%s\n" "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ if test yes != "$GCC"; then
+ reload_cmds=false
+ fi
+ ;;
+ darwin*)
+ if test yes = "$GCC"; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}file", so it can be a program name with args.
+set dummy ${ac_tool_prefix}file; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_FILECMD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$FILECMD"; then
+ ac_cv_prog_FILECMD="$FILECMD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_FILECMD="${ac_tool_prefix}file"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+FILECMD=$ac_cv_prog_FILECMD
+if test -n "$FILECMD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FILECMD" >&5
+printf "%s\n" "$FILECMD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_FILECMD"; then
+ ac_ct_FILECMD=$FILECMD
+ # Extract the first word of "file", so it can be a program name with args.
+set dummy file; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_FILECMD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_FILECMD"; then
+ ac_cv_prog_ac_ct_FILECMD="$ac_ct_FILECMD" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_FILECMD="file"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_FILECMD=$ac_cv_prog_ac_ct_FILECMD
+if test -n "$ac_ct_FILECMD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_FILECMD" >&5
+printf "%s\n" "$ac_ct_FILECMD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_FILECMD" = x; then
+ FILECMD=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ FILECMD=$ac_ct_FILECMD
+ fi
+else
+ FILECMD="$ac_cv_prog_FILECMD"
+fi
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_OBJDUMP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$OBJDUMP"; then
+ ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+printf "%s\n" "$OBJDUMP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+ ac_ct_OBJDUMP=$OBJDUMP
+ # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_OBJDUMP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_OBJDUMP"; then
+ ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OBJDUMP="objdump"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+printf "%s\n" "$ac_ct_OBJDUMP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_OBJDUMP" = x; then
+ OBJDUMP="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OBJDUMP=$ac_ct_OBJDUMP
+ fi
+else
+ OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+printf %s "checking how to recognize dependent libraries... " >&6; }
+if test ${lt_cv_deplibs_check_method+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# 'unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# that responds to the $file_magic_cmd with a given extended regex.
+# If you have 'file' or equivalent on your system and you're not sure
+# whether 'pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[45]*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='$FILECMD -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump',
+ # unless we find 'file', for example because we are cross-compiling.
+ if ( file / ) >/dev/null 2>&1; then
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ else
+ # Keep this pattern in sync with the one in func_win32_libid.
+ lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ fi
+ ;;
+
+cegcc*)
+ # use the weaker test based on 'objdump'. See mingw*.
+ lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | dragonfly* | midnightbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=$FILECMD
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+haiku*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=$FILECMD
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix[3-9]*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=$FILECMD
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+*nto* | *qnx*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+openbsd* | bitrig*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+rdos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+tpf*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+os2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+printf "%s\n" "$lt_cv_deplibs_check_method" >&6; }
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+ case $host_os in
+ mingw* | pw32*)
+ if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+ want_nocaseglob=yes
+ else
+ file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"`
+ fi
+ ;;
+ esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DLLTOOL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$DLLTOOL"; then
+ ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
+printf "%s\n" "$DLLTOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DLLTOOL"; then
+ ac_ct_DLLTOOL=$DLLTOOL
+ # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DLLTOOL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_DLLTOOL"; then
+ ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
+printf "%s\n" "$ac_ct_DLLTOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_DLLTOOL" = x; then
+ DLLTOOL="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DLLTOOL=$ac_ct_DLLTOOL
+ fi
+else
+ DLLTOOL="$ac_cv_prog_DLLTOOL"
+fi
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5
+printf %s "checking how to associate runtime and link libraries... " >&6; }
+if test ${lt_cv_sharedlib_from_linklib_cmd+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+ # two different shell functions defined in ltmain.sh;
+ # decide which one to use based on capabilities of $DLLTOOL
+ case `$DLLTOOL --help 2>&1` in
+ *--identify-strict*)
+ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+ ;;
+ *)
+ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+ ;;
+ esac
+ ;;
+*)
+ # fallback: assume linklib IS sharedlib
+ lt_cv_sharedlib_from_linklib_cmd=$ECHO
+ ;;
+esac
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5
+printf "%s\n" "$lt_cv_sharedlib_from_linklib_cmd" >&6; }
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in ar
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_AR+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+printf "%s\n" "$AR" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$AR" && break
+ done
+fi
+if test -z "$AR"; then
+ ac_ct_AR=$AR
+ for ac_prog in ar
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_AR+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+printf "%s\n" "$ac_ct_AR" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_AR" && break
+done
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+fi
+
+: ${AR=ar}
+
+
+
+
+
+
+# Use ARFLAGS variable as AR's operation code to sync the variable naming with
+# Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
+# higher priority because thats what people were doing historically (setting
+# ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS
+# variable obsoleted/removed.
+
+test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
+lt_ar_flags=$AR_FLAGS
+
+
+
+
+
+
+# Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override
+# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5
+printf %s "checking for archiver @FILE support... " >&6; }
+if test ${lt_cv_ar_at_file+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_ar_at_file=no
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ echo conftest.$ac_objext > conftest.lst
+ lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+ (eval $lt_ar_try) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test 0 -eq "$ac_status"; then
+ # Ensure the archiver fails upon bogus file names.
+ rm -f conftest.$ac_objext libconftest.a
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+ (eval $lt_ar_try) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test 0 -ne "$ac_status"; then
+ lt_cv_ar_at_file=@
+ fi
+ fi
+ rm -f conftest.* libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5
+printf "%s\n" "$lt_cv_ar_at_file" >&6; }
+
+if test no = "$lt_cv_ar_at_file"; then
+ archiver_list_spec=
+else
+ archiver_list_spec=$lt_cv_ar_at_file
+fi
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_STRIP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+printf "%s\n" "$STRIP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_STRIP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+printf "%s\n" "$ac_ct_STRIP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+printf "%s\n" "$RANLIB" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+printf "%s\n" "$ac_ct_RANLIB" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ bitrig* | openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+ darwin*)
+ lock_old_archive_extraction=yes ;;
+ *)
+ lock_old_archive_extraction=no ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+printf %s "checking command to parse $NM output from $compiler object... " >&6; }
+if test ${lt_cv_sys_global_symbol_pipe+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[BCDT]'
+ ;;
+cygwin* | mingw* | pw32* | cegcc*)
+ symcode='[ABCDGISTW]'
+ ;;
+hpux*)
+ if test ia64 = "$host_cpu"; then
+ symcode='[ABCDEGRST]'
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[BCDEGRST]'
+ ;;
+osf*)
+ symcode='[BCDEGQRST]'
+ ;;
+solaris*)
+ symcode='[BDRT]'
+ ;;
+sco3.2v5*)
+ symcode='[DT]'
+ ;;
+sysv4.2uw2*)
+ symcode='[DT]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[ABDT]'
+ ;;
+sysv4)
+ symcode='[DFNSTU]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[ABCDGIRSTW]' ;;
+esac
+
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Gets list of data symbols to import.
+ lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
+ # Adjust the below global symbol transforms to fixup imported variables.
+ lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+ lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'"
+ lt_c_name_lib_hook="\
+ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\
+ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'"
+else
+ # Disable hooks by default.
+ lt_cv_sys_global_symbol_to_import=
+ lt_cdecl_hook=
+ lt_c_name_hook=
+ lt_c_name_lib_hook=
+fi
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
+$lt_cdecl_hook\
+" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
+$lt_c_name_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'"
+
+# Transform an extracted symbol line into symbol name with lib prefix and
+# symbol address.
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
+$lt_c_name_lib_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Fake it for dumpbin and say T for any non-static function,
+ # D for any global variable and I for any imported variable.
+ # Also find C++ and __fastcall symbols from MSVC++ or ICC,
+ # which start with @ or ?.
+ lt_cv_sys_global_symbol_pipe="$AWK '"\
+" {last_section=section; section=\$ 3};"\
+" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
+" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
+" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
+" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
+" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
+" ' prfx=^$ac_symprfx"
+ else
+ lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+ fi
+ lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5
+ if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+ if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
+#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+/* DATA imports from DLLs on WIN32 can't be const, because runtime
+ relocations are performed -- see ld's documentation on pseudo-relocs. */
+# define LT_DLSYM_CONST
+#elif defined __osf__
+/* This system does not cope well with relocations in const data. */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+ cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols. */
+LT_DLSYM_CONST struct {
+ const char *name;
+ void *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+ { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+ $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+ cat <<\_LT_EOF >> conftest.$ac_ext
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_globsym_save_LIBS=$LIBS
+ lt_globsym_save_CFLAGS=$CFLAGS
+ LIBS=conftstm.$ac_objext
+ CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s conftest$ac_exeext; then
+ pipe_works=yes
+ fi
+ LIBS=$lt_globsym_save_LIBS
+ CFLAGS=$lt_globsym_save_CFLAGS
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+ fi
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ fi
+ rm -rf conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test yes = "$pipe_works"; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+printf "%s\n" "failed" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+printf "%s\n" "ok" >&6; }
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
+ nm_file_list_spec='@'
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
+printf %s "checking for sysroot... " >&6; }
+
+# Check whether --with-sysroot was given.
+if test ${with_sysroot+y}
+then :
+ withval=$with_sysroot;
+else $as_nop
+ with_sysroot=no
+fi
+
+
+lt_sysroot=
+case $with_sysroot in #(
+ yes)
+ if test yes = "$GCC"; then
+ lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+ fi
+ ;; #(
+ /*)
+ lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
+ ;; #(
+ no|'')
+ ;; #(
+ *)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5
+printf "%s\n" "$with_sysroot" >&6; }
+ as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5
+ ;;
+esac
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5
+printf "%s\n" "${lt_sysroot:-no}" >&6; }
+
+
+
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5
+printf %s "checking for a working dd... " >&6; }
+if test ${ac_cv_path_lt_DD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+: ${lt_DD:=$DD}
+if test -z "$lt_DD"; then
+ ac_path_lt_DD_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in dd
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_lt_DD="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_lt_DD" || continue
+if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
+fi
+ $ac_path_lt_DD_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_lt_DD"; then
+ :
+ fi
+else
+ ac_cv_path_lt_DD=$lt_DD
+fi
+
+rm -f conftest.i conftest2.i conftest.out
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5
+printf "%s\n" "$ac_cv_path_lt_DD" >&6; }
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5
+printf %s "checking how to truncate binary pipes... " >&6; }
+if test ${lt_cv_truncate_bin+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+lt_cv_truncate_bin=
+if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
+fi
+rm -f conftest.i conftest2.i conftest.out
+test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5
+printf "%s\n" "$lt_cv_truncate_bin" >&6; }
+
+
+
+
+
+
+
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+ for cc_temp in $*""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+ done
+ func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+
+# Check whether --enable-libtool-lock was given.
+if test ${enable_libtool_lock+y}
+then :
+ enableval=$enable_libtool_lock;
+fi
+
+test no = "$enable_libtool_lock" || enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out what ABI is being produced by ac_compile, and set mode
+ # options accordingly.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `$FILECMD conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE=32
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE=64
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ if test yes = "$lt_cv_prog_gnu_ld"; then
+ case `$FILECMD conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `$FILECMD conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+mips64*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ emul=elf
+ case `$FILECMD conftest.$ac_objext` in
+ *32-bit*)
+ emul="${emul}32"
+ ;;
+ *64-bit*)
+ emul="${emul}64"
+ ;;
+ esac
+ case `$FILECMD conftest.$ac_objext` in
+ *MSB*)
+ emul="${emul}btsmip"
+ ;;
+ *LSB*)
+ emul="${emul}ltsmip"
+ ;;
+ esac
+ case `$FILECMD conftest.$ac_objext` in
+ *N32*)
+ emul="${emul}n32"
+ ;;
+ esac
+ LD="${LD-ld} -m $emul"
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly. Note that the listed cases only cover the
+ # situations where additional linker options are needed (such as when
+ # doing 32-bit compilation for a host where ld defaults to 64-bit, or
+ # vice versa); the common cases where no linker options are needed do
+ # not appear in the list.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `$FILECMD conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_i386_fbsd"
+ ;;
+ x86_64-*linux*)
+ case `$FILECMD conftest.o` in
+ *x86-64*)
+ LD="${LD-ld} -m elf32_x86_64"
+ ;;
+ *)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ esac
+ ;;
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_x86_64_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*|s390*-*tpf*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS -belf"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+printf %s "checking whether the C compiler needs -belf... " >&6; }
+if test ${lt_cv_cc_needs_belf+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ lt_cv_cc_needs_belf=yes
+else $as_nop
+ lt_cv_cc_needs_belf=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+printf "%s\n" "$lt_cv_cc_needs_belf" >&6; }
+ if test yes != "$lt_cv_cc_needs_belf"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS=$SAVE_CFLAGS
+ fi
+ ;;
+*-*solaris*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `$FILECMD conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*)
+ case $host in
+ i?86-*-solaris*|x86_64-*-solaris*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ sparc*-*-solaris*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ # GNU ld 2.21 introduced _sol2 emulations. Use them if available.
+ if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+ LD=${LD-ld}_sol2
+ fi
+ ;;
+ *)
+ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+ LD="${LD-ld} -64"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+esac
+
+need_locks=$enable_libtool_lock
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args.
+set dummy ${ac_tool_prefix}mt; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_MANIFEST_TOOL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$MANIFEST_TOOL"; then
+ ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
+if test -n "$MANIFEST_TOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
+printf "%s\n" "$MANIFEST_TOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_MANIFEST_TOOL"; then
+ ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL
+ # Extract the first word of "mt", so it can be a program name with args.
+set dummy mt; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_MANIFEST_TOOL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_MANIFEST_TOOL"; then
+ ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
+if test -n "$ac_ct_MANIFEST_TOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5
+printf "%s\n" "$ac_ct_MANIFEST_TOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_MANIFEST_TOOL" = x; then
+ MANIFEST_TOOL=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
+ fi
+else
+ MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
+fi
+
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5
+printf %s "checking if $MANIFEST_TOOL is a manifest tool... " >&6; }
+if test ${lt_cv_path_mainfest_tool+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_path_mainfest_tool=no
+ echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5
+ $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+ cat conftest.err >&5
+ if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+ lt_cv_path_mainfest_tool=yes
+ fi
+ rm -f conftest*
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5
+printf "%s\n" "$lt_cv_path_mainfest_tool" >&6; }
+if test yes != "$lt_cv_path_mainfest_tool"; then
+ MANIFEST_TOOL=:
+fi
+
+
+
+
+
+
+ case $host_os in
+ rhapsody* | darwin*)
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DSYMUTIL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$DSYMUTIL"; then
+ ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+printf "%s\n" "$DSYMUTIL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+ ac_ct_DSYMUTIL=$DSYMUTIL
+ # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DSYMUTIL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_DSYMUTIL"; then
+ ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+printf "%s\n" "$ac_ct_DSYMUTIL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_DSYMUTIL" = x; then
+ DSYMUTIL=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DSYMUTIL=$ac_ct_DSYMUTIL
+ fi
+else
+ DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_NMEDIT+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$NMEDIT"; then
+ ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+printf "%s\n" "$NMEDIT" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+ ac_ct_NMEDIT=$NMEDIT
+ # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_NMEDIT+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_NMEDIT"; then
+ ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_NMEDIT="nmedit"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+printf "%s\n" "$ac_ct_NMEDIT" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_NMEDIT" = x; then
+ NMEDIT=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ NMEDIT=$ac_ct_NMEDIT
+ fi
+else
+ NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_LIPO+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$LIPO"; then
+ ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+printf "%s\n" "$LIPO" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+ ac_ct_LIPO=$LIPO
+ # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_LIPO+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_LIPO"; then
+ ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_LIPO="lipo"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+printf "%s\n" "$ac_ct_LIPO" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_LIPO" = x; then
+ LIPO=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ LIPO=$ac_ct_LIPO
+ fi
+else
+ LIPO="$ac_cv_prog_LIPO"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_OTOOL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$OTOOL"; then
+ ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+printf "%s\n" "$OTOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+ ac_ct_OTOOL=$OTOOL
+ # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_OTOOL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_OTOOL"; then
+ ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OTOOL="otool"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+printf "%s\n" "$ac_ct_OTOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_OTOOL" = x; then
+ OTOOL=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OTOOL=$ac_ct_OTOOL
+ fi
+else
+ OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_OTOOL64+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$OTOOL64"; then
+ ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+printf "%s\n" "$OTOOL64" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+ ac_ct_OTOOL64=$OTOOL64
+ # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_OTOOL64+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_OTOOL64"; then
+ ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OTOOL64="otool64"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+printf "%s\n" "$ac_ct_OTOOL64" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_OTOOL64" = x; then
+ OTOOL64=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OTOOL64=$ac_ct_OTOOL64
+ fi
+else
+ OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+printf %s "checking for -single_module linker flag... " >&6; }
+if test ${lt_cv_apple_cc_single_mod+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_apple_cc_single_mod=no
+ if test -z "$LT_MULTI_MODULE"; then
+ # By default we will add the -single_module flag. You can override
+ # by either setting the environment variable LT_MULTI_MODULE
+ # non-empty at configure time, or by adding -multi_module to the
+ # link flags.
+ rm -rf libconftest.dylib*
+ echo "int foo(void){return 1;}" > conftest.c
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+ _lt_result=$?
+ # If there is a non-empty error log, and "single_module"
+ # appears in it, assume the flag caused a linker warning
+ if test -s conftest.err && $GREP single_module conftest.err; then
+ cat conftest.err >&5
+ # Otherwise, if the output was created with a 0 exit code from
+ # the compiler, it worked.
+ elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
+ lt_cv_apple_cc_single_mod=yes
+ else
+ cat conftest.err >&5
+ fi
+ rm -rf libconftest.dylib*
+ rm -f conftest.*
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+printf "%s\n" "$lt_cv_apple_cc_single_mod" >&6; }
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+printf %s "checking for -exported_symbols_list linker flag... " >&6; }
+if test ${lt_cv_ld_exported_symbols_list+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_ld_exported_symbols_list=no
+ save_LDFLAGS=$LDFLAGS
+ echo "_main" > conftest.sym
+ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ lt_cv_ld_exported_symbols_list=yes
+else $as_nop
+ lt_cv_ld_exported_symbols_list=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$save_LDFLAGS
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+printf "%s\n" "$lt_cv_ld_exported_symbols_list" >&6; }
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
+printf %s "checking for -force_load linker flag... " >&6; }
+if test ${lt_cv_ld_force_load+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_ld_force_load=no
+ cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
+ $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
+ echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5
+ $AR $AR_FLAGS libconftest.a conftest.o 2>&5
+ echo "$RANLIB libconftest.a" >&5
+ $RANLIB libconftest.a 2>&5
+ cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
+ $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+ _lt_result=$?
+ if test -s conftest.err && $GREP force_load conftest.err; then
+ cat conftest.err >&5
+ elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
+ lt_cv_ld_force_load=yes
+ else
+ cat conftest.err >&5
+ fi
+ rm -f conftest.err libconftest.a conftest conftest.c
+ rm -rf conftest.dSYM
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
+printf "%s\n" "$lt_cv_ld_force_load" >&6; }
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
+ darwin1.*)
+ _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+ darwin*)
+ case $MACOSX_DEPLOYMENT_TARGET,$host in
+ 10.[012],*|,*powerpc*-darwin[5-8]*)
+ _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+ *)
+ _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+ esac
+ ;;
+ esac
+ if test yes = "$lt_cv_apple_cc_single_mod"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test yes = "$lt_cv_ld_exported_symbols_list"; then
+ _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
+ else
+ _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
+ fi
+ if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
+ _lt_dsymutil='~$DSYMUTIL $lib || :'
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ esac
+
+# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+# string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+# string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+# "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+# VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+ case x$2 in
+ x)
+ ;;
+ *:)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+ ;;
+ x:*)
+ eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ *::*)
+ eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+ eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+ ;;
+ *)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ esac
+}
+
+ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h
+
+fi
+
+
+
+
+
+# Set options
+enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
+set dummy ${ac_tool_prefix}as; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_AS+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$AS"; then
+ ac_cv_prog_AS="$AS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AS="${ac_tool_prefix}as"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AS=$ac_cv_prog_AS
+if test -n "$AS"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AS" >&5
+printf "%s\n" "$AS" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AS"; then
+ ac_ct_AS=$AS
+ # Extract the first word of "as", so it can be a program name with args.
+set dummy as; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_AS+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_AS"; then
+ ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AS="as"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AS=$ac_cv_prog_ac_ct_AS
+if test -n "$ac_ct_AS"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5
+printf "%s\n" "$ac_ct_AS" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_AS" = x; then
+ AS="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AS=$ac_ct_AS
+ fi
+else
+ AS="$ac_cv_prog_AS"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_DLLTOOL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$DLLTOOL"; then
+ ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
+printf "%s\n" "$DLLTOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DLLTOOL"; then
+ ac_ct_DLLTOOL=$DLLTOOL
+ # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_DLLTOOL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_DLLTOOL"; then
+ ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
+printf "%s\n" "$ac_ct_DLLTOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_DLLTOOL" = x; then
+ DLLTOOL="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DLLTOOL=$ac_ct_DLLTOOL
+ fi
+else
+ DLLTOOL="$ac_cv_prog_DLLTOOL"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_OBJDUMP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$OBJDUMP"; then
+ ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+printf "%s\n" "$OBJDUMP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+ ac_ct_OBJDUMP=$OBJDUMP
+ # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_OBJDUMP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_OBJDUMP"; then
+ ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OBJDUMP="objdump"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+printf "%s\n" "$ac_ct_OBJDUMP" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_OBJDUMP" = x; then
+ OBJDUMP="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OBJDUMP=$ac_ct_OBJDUMP
+ fi
+else
+ OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+ ;;
+esac
+
+test -z "$AS" && AS=as
+
+
+
+
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+
+
+
+
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+
+ enable_dlopen=no
+
+
+
+ # Check whether --enable-shared was given.
+if test ${enable_shared+y}
+then :
+ enableval=$enable_shared; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac
+else $as_nop
+ enable_shared=yes
+fi
+
+
+
+
+
+
+
+
+
+ # Check whether --enable-static was given.
+if test ${enable_static+y}
+then :
+ enableval=$enable_static; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac
+else $as_nop
+ enable_static=yes
+fi
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test ${with_pic+y}
+then :
+ withval=$with_pic; lt_p=${PACKAGE-default}
+ case $withval in
+ yes|no) pic_mode=$withval ;;
+ *)
+ pic_mode=default
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for lt_pkg in $withval; do
+ IFS=$lt_save_ifs
+ if test "X$lt_pkg" = "X$lt_p"; then
+ pic_mode=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac
+else $as_nop
+ pic_mode=default
+fi
+
+
+
+
+
+
+
+
+ # Check whether --enable-fast-install was given.
+if test ${enable_fast_install+y}
+then :
+ enableval=$enable_fast_install; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac
+else $as_nop
+ enable_fast_install=yes
+fi
+
+
+
+
+
+
+
+
+ shared_archive_member_spec=
+case $host,$enable_shared in
+power*-*-aix[5-9]*,yes)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5
+printf %s "checking which variant of shared library versioning to provide... " >&6; }
+
+# Check whether --with-aix-soname was given.
+if test ${with_aix_soname+y}
+then :
+ withval=$with_aix_soname; case $withval in
+ aix|svr4|both)
+ ;;
+ *)
+ as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5
+ ;;
+ esac
+ lt_cv_with_aix_soname=$with_aix_soname
+else $as_nop
+ if test ${lt_cv_with_aix_soname+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_with_aix_soname=aix
+fi
+
+ with_aix_soname=$lt_cv_with_aix_soname
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5
+printf "%s\n" "$with_aix_soname" >&6; }
+ if test aix != "$with_aix_soname"; then
+ # For the AIX way of multilib, we name the shared archive member
+ # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
+ # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
+ # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
+ # the AIX toolchain works better with OBJECT_MODE set (default 32).
+ if test 64 = "${OBJECT_MODE-32}"; then
+ shared_archive_member_spec=shr_64
+ else
+ shared_archive_member_spec=shr
+ fi
+ fi
+ ;;
+*)
+ with_aix_soname=aix
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS=$ltmain
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+printf %s "checking for objdir... " >&6; }
+if test ${lt_cv_objdir+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+printf "%s\n" "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+printf "%s\n" "#define LT_OBJDIR \"$lt_cv_objdir/\"" >>confdefs.h
+
+
+
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test set != "${COLLECT_NAMES+set}"; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a '.a' archive for static linking (except MSVC and
+# ICC, which need '.lib').
+libext=a
+
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+old_CC=$CC
+old_CFLAGS=$CFLAGS
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+func_cc_basename $compiler
+cc_basename=$func_cc_basename_result
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+printf %s "checking for ${ac_tool_prefix}file... " >&6; }
+if test ${lt_cv_path_MAGIC_CMD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD=$MAGIC_CMD
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/${ac_tool_prefix}file"; then
+ lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS=$lt_save_ifs
+ MAGIC_CMD=$lt_save_MAGIC_CMD
+ ;;
+esac
+fi
+
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+printf "%s\n" "$MAGIC_CMD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+printf %s "checking for file... " >&6; }
+if test ${lt_cv_path_MAGIC_CMD+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD=$MAGIC_CMD
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/file"; then
+ lt_cv_path_MAGIC_CMD=$ac_dir/"file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS=$lt_save_ifs
+ MAGIC_CMD=$lt_save_MAGIC_CMD
+ ;;
+esac
+fi
+
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+printf "%s\n" "$MAGIC_CMD" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ else
+ MAGIC_CMD=:
+ fi
+fi
+
+ fi
+ ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC=$CC
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test yes = "$GCC"; then
+ case $cc_basename in
+ nvcc*)
+ lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
+ *)
+ lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
+ esac
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+printf %s "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if test ${lt_cv_prog_compiler_rtti_exceptions+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $RM conftest*
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+printf "%s\n" "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then
+ lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+
+
+
+
+
+ lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+
+ if test yes = "$GCC"; then
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_static='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the '-m68020' flag to GCC prevents building anything better,
+ # like '-m68040'.
+ lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ case $host_os in
+ os2*)
+ lt_prog_compiler_static='$wl-static'
+ ;;
+ esac
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ ;;
+
+ haiku*)
+ # PIC is the default for Haiku.
+ # The "-static" flag exists, but is broken.
+ lt_prog_compiler_static=
+ ;;
+
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ ;;
+
+ interix[3-9]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared=no
+ enable_shared=no
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ lt_prog_compiler_pic='-fPIC -shared'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic=-Kconform_pic
+ fi
+ ;;
+
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+
+ case $cc_basename in
+ nvcc*) # Cuda Compiler Driver 2.2
+ lt_prog_compiler_wl='-Xlinker '
+ if test -n "$lt_prog_compiler_pic"; then
+ lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic"
+ fi
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl='-Wl,'
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ else
+ lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ case $cc_basename in
+ nagfor*)
+ # NAG Fortran compiler
+ lt_prog_compiler_wl='-Wl,-Wl,,'
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ esac
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ case $host_os in
+ os2*)
+ lt_prog_compiler_static='$wl-static'
+ ;;
+ esac
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static='$wl-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ case $cc_basename in
+ # old Intel for x86_64, which still supported -KPIC.
+ ecc*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ # flang / f18. f95 an alias for gfortran or flang on Debian
+ flang* | f18* | f95*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ # icc used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ icc* | ifort*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ # Lahey Fortran 8.1.
+ lf95*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='--shared'
+ lt_prog_compiler_static='--static'
+ ;;
+ nagfor*)
+ # NAG Fortran compiler
+ lt_prog_compiler_wl='-Wl,-Wl,,'
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fpic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+ xl* | bgxl* | bgf* | mpixl*)
+ # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-qpic'
+ lt_prog_compiler_static='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | $SED 5q` in
+ *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
+ # Sun Fortran 8.3 passes all unrecognized flags to the linker
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ lt_prog_compiler_wl=''
+ ;;
+ *Sun\ F* | *Sun*Fortran*)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ lt_prog_compiler_wl='-Qoption ld '
+ ;;
+ *Sun\ C*)
+ # Sun C 5.9
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ lt_prog_compiler_wl='-Wl,'
+ ;;
+ *Intel*\ [CF]*Compiler*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ *Portland\ Group*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fpic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ lt_prog_compiler_pic='-fPIC -shared'
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ rdos*)
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+ lt_prog_compiler_wl='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl='-Qoption ld '
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic='-Kconform_pic'
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_can_build_shared=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic='-pic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared=no
+ ;;
+ esac
+ fi
+
+case $host_os in
+ # For platforms that do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic=
+ ;;
+ *)
+ lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+ ;;
+esac
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+printf %s "checking for $compiler option to produce PIC... " >&6; }
+if test ${lt_cv_prog_compiler_pic+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_prog_compiler_pic=$lt_prog_compiler_pic
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
+printf "%s\n" "$lt_cv_prog_compiler_pic" >&6; }
+lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+printf %s "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if test ${lt_cv_prog_compiler_pic_works+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_prog_compiler_pic_works=no
+ ac_outfile=conftest.$ac_objext
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_pic_works=yes
+ fi
+ fi
+ $RM conftest*
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+printf "%s\n" "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_pic_works"; then
+ case $lt_prog_compiler_pic in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+ esac
+else
+ lt_prog_compiler_pic=
+ lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+printf %s "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if test ${lt_cv_prog_compiler_static_works+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_prog_compiler_static_works=no
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_static_works=yes
+ fi
+ else
+ lt_cv_prog_compiler_static_works=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS=$save_LDFLAGS
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+printf "%s\n" "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_static_works"; then
+ :
+else
+ lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test ${lt_cv_prog_compiler_c_o+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_prog_compiler_c_o=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+printf %s "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test ${lt_cv_prog_compiler_c_o+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_prog_compiler_c_o=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+printf "%s\n" "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links=nottested
+if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then
+ # do not overwrite the value of need_locks provided by the user
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+printf %s "checking if we can lock with hard links... " >&6; }
+ hard_links=yes
+ $RM conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+printf "%s\n" "$hard_links" >&6; }
+ if test no = "$hard_links"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5
+printf "%s\n" "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+printf %s "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+ runpath_var=
+ allow_undefined_flag=
+ always_export_symbols=no
+ archive_cmds=
+ archive_expsym_cmds=
+ compiler_needs_object=no
+ enable_shared_with_static_runtimes=no
+ export_dynamic_flag_spec=
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ hardcode_automatic=no
+ hardcode_direct=no
+ hardcode_direct_absolute=no
+ hardcode_libdir_flag_spec=
+ hardcode_libdir_separator=
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=unsupported
+ inherit_rpath=no
+ link_all_deplibs=unknown
+ module_cmds=
+ module_expsym_cmds=
+ old_archive_from_new_cmds=
+ old_archive_from_expsyms_cmds=
+ thread_safe_flag_spec=
+ whole_archive_flag_spec=
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ' (' and ')$', so one must not match beginning or
+ # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
+ # as well as any symbol that contains 'd'.
+ exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ # Exclude shared library initialization/finalization symbols.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++ or Intel C++ Compiler.
+ if test yes != "$GCC"; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
+ with_gnu_ld=yes
+ ;;
+ openbsd* | bitrig*)
+ with_gnu_ld=no
+ ;;
+ linux* | k*bsd*-gnu | gnu*)
+ link_all_deplibs=no
+ ;;
+ esac
+
+ ld_shlibs=yes
+
+ # On some targets, GNU ld is compatible enough with the native linker
+ # that we're better off using the native interface for both.
+ lt_use_gnu_ld_interface=no
+ if test yes = "$with_gnu_ld"; then
+ case $host_os in
+ aix*)
+ # The AIX port of GNU ld has always aspired to compatibility
+ # with the native linker. However, as the warning in the GNU ld
+ # block says, versions before 2.19.5* couldn't really create working
+ # shared libraries, regardless of the interface used.
+ case `$LD -v 2>&1` in
+ *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+ *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
+ *\ \(GNU\ Binutils\)\ [3-9]*) ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ fi
+
+ if test yes = "$lt_use_gnu_ld_interface"; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='$wl'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ export_dynamic_flag_spec='$wl--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+ else
+ whole_archive_flag_spec=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
+ *GNU\ gold*) supports_anon_versioning=yes ;;
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix[3-9]*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test ia64 != "$host_cpu"; then
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds=''
+ ;;
+ m68k)
+ archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ esac
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag=unsupported
+ # Joseph Beckenbach says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ export_dynamic_flag_spec='$wl--export-all-symbols'
+ allow_undefined_flag=unsupported
+ always_export_symbols=no
+ enable_shared_with_static_runtimes=yes
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+ exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file, use it as
+ # is; otherwise, prepend EXPORTS...
+ archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ haiku*)
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ link_all_deplibs=yes
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ shrext_cmds=.dll
+ archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ enable_shared_with_static_runtimes=yes
+ file_list_spec='@'
+ ;;
+
+ interix[3-9]*)
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+ export_dynamic_flag_spec='$wl-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+ tmp_diet=no
+ if test linux-dietlibc = "$host_os"; then
+ case $cc_basename in
+ diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
+ esac
+ fi
+ if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+ && test no = "$tmp_diet"
+ then
+ tmp_addflag=' $pic_flag'
+ tmp_sharedflag='-shared'
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ lf95*) # Lahey Fortran 8.1
+ whole_archive_flag_spec=
+ tmp_sharedflag='--shared' ;;
+ nagfor*) # NAGFOR 5.3
+ tmp_sharedflag='-Wl,-shared' ;;
+ xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+ tmp_sharedflag='-qmkshrobj'
+ tmp_addflag= ;;
+ nvcc*) # Cuda Compiler Driver 2.2
+ whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ compiler_needs_object=yes
+ ;;
+ esac
+ case `$CC -V 2>&1 | $SED 5q` in
+ *Sun\ C*) # Sun C 5.9
+ whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ compiler_needs_object=yes
+ tmp_sharedflag='-G' ;;
+ *Sun\ F*) # Sun Fortran 8.3
+ tmp_sharedflag='-G' ;;
+ esac
+ archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+
+ if test yes = "$supports_anon_versioning"; then
+ archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+ fi
+
+ case $cc_basename in
+ tcc*)
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ export_dynamic_flag_spec='-rdynamic'
+ ;;
+ xlf* | bgf* | bgxlf* | mpixlf*)
+ # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+ whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+ if test yes = "$supports_anon_versioning"; then
+ archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ esac
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test no = "$ld_shlibs"; then
+ runpath_var=
+ hardcode_libdir_flag_spec=
+ export_dynamic_flag_spec=
+ whole_archive_flag_spec=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix[4-9]*)
+ if test ia64 = "$host_cpu"; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+ # Without the "-l" option, or with the "-B" option, AIX nm treats
+ # weak defined symbols like other global defined symbols, whereas
+ # GNU nm marks them as "W".
+ # While the 'weak' keyword is ignored in the Export File, we need
+ # it in the Import File for the 'aix-soname' feature, so we have
+ # to replace the "-B" option with "-P" for AIX nm.
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # have runtime linking enabled, and use it for executables.
+ # For shared libraries, we enable/disable runtime linking
+ # depending on the kind of the shared library created -
+ # when "with_aix_soname,aix_use_runtimelinking" is:
+ # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
+ # "aix,yes" lib.so shared, rtl:yes, for executables
+ # lib.a static archive
+ # "both,no" lib.so.V(shr.o) shared, rtl:yes
+ # lib.a(lib.so.V) shared, rtl:no, for executables
+ # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a(lib.so.V) shared, rtl:no
+ # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a static archive
+ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+ for ld_flag in $LDFLAGS; do
+ if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # With aix-soname=svr4, we create the lib.so.V shared archives only,
+ # so we don't have lib.a shared libs to link our executables.
+ # We have to force runtime linking in this case.
+ aix_use_runtimelinking=yes
+ LDFLAGS="$LDFLAGS -Wl,-brtl"
+ fi
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds=''
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+ file_list_spec='$wl-f,'
+ case $with_aix_soname,$aix_use_runtimelinking in
+ aix,*) ;; # traditional, no import file
+ svr4,* | *,yes) # use import file
+ # The Import File defines what to hardcode.
+ hardcode_direct=no
+ hardcode_direct_absolute=no
+ ;;
+ esac
+
+ if test yes = "$GCC"; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`$CC -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag="$shared_flag "'$wl-G'
+ fi
+ # Need to ensure runtime linking is disabled for the traditional
+ # shared library, or the linker may eventually find shared libraries
+ # /with/ Import File - we do not want to mix them.
+ shared_flag_aix='-shared'
+ shared_flag_svr4='-shared $wl-G'
+ else
+ # not using gcc
+ if test ia64 = "$host_cpu"; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag='$wl-G'
+ else
+ shared_flag='$wl-bM:SRE'
+ fi
+ shared_flag_aix='$wl-bM:SRE'
+ shared_flag_svr4='$wl-G'
+ fi
+ fi
+
+ export_dynamic_flag_spec='$wl-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols=yes
+ if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag='-berok'
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ if test set = "${lt_cv_aix_libpath+set}"; then
+ aix_libpath=$lt_cv_aix_libpath
+else
+ if test ${lt_cv_aix_libpath_+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+
+ lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\([^ ]*\) *$/\1/
+ p
+ }
+ }'
+ lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ # Check for a 64-bit object if we didn't find anything.
+ if test -z "$lt_cv_aix_libpath_"; then
+ lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ if test -z "$lt_cv_aix_libpath_"; then
+ lt_cv_aix_libpath_=/usr/lib:/lib
+ fi
+
+fi
+
+ aix_libpath=$lt_cv_aix_libpath_
+fi
+
+ hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+ else
+ if test ia64 = "$host_cpu"; then
+ hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag="-z nodefs"
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ if test set = "${lt_cv_aix_libpath+set}"; then
+ aix_libpath=$lt_cv_aix_libpath
+else
+ if test ${lt_cv_aix_libpath_+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+
+ lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\([^ ]*\) *$/\1/
+ p
+ }
+ }'
+ lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ # Check for a 64-bit object if we didn't find anything.
+ if test -z "$lt_cv_aix_libpath_"; then
+ lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ if test -z "$lt_cv_aix_libpath_"; then
+ lt_cv_aix_libpath_=/usr/lib:/lib
+ fi
+
+fi
+
+ aix_libpath=$lt_cv_aix_libpath_
+fi
+
+ hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag=' $wl-bernotok'
+ allow_undefined_flag=' $wl-berok'
+ if test yes = "$with_gnu_ld"; then
+ # We only use this code for GNU lds that support --whole-archive.
+ whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive'
+ else
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec='$convenience'
+ fi
+ archive_cmds_need_lc=yes
+ archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+ # -brtl affects multiple linker settings, -berok does not and is overridden later
+ compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`'
+ if test svr4 != "$with_aix_soname"; then
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+ fi
+ if test aix != "$with_aix_soname"; then
+ archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+ else
+ # used by -dlpreopen to get the symbols
+ archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
+ fi
+ archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds=''
+ ;;
+ m68k)
+ archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ esac
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++ or Intel C++ Compiler.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ case $cc_basename in
+ cl* | icl*)
+ # Native MSVC or ICC
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ file_list_spec='@'
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+ archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then
+ cp "$export_symbols" "$output_objdir/$soname.def";
+ echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+ else
+ $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+ fi~
+ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+ linknames='
+ # The linker will not automatically build a static lib if we build a DLL.
+ # _LT_TAGVAR(old_archive_from_new_cmds, )='true'
+ enable_shared_with_static_runtimes=yes
+ exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+ # Don't use ranlib
+ old_postinstall_cmds='chmod 644 $oldlib'
+ postlink_cmds='lt_outputfile="@OUTPUT@"~
+ lt_tool_outputfile="@TOOL_OUTPUT@"~
+ case $lt_outputfile in
+ *.exe|*.EXE) ;;
+ *)
+ lt_outputfile=$lt_outputfile.exe
+ lt_tool_outputfile=$lt_tool_outputfile.exe
+ ;;
+ esac~
+ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+ $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+ $RM "$lt_outputfile.manifest";
+ fi'
+ ;;
+ *)
+ # Assume MSVC and ICC wrapper
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_from_new_cmds='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+ enable_shared_with_static_runtimes=yes
+ ;;
+ esac
+ ;;
+
+ darwin* | rhapsody*)
+
+
+ archive_cmds_need_lc=no
+ hardcode_direct=no
+ hardcode_automatic=yes
+ hardcode_shlibpath_var=unsupported
+ if test yes = "$lt_cv_ld_force_load"; then
+ whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+
+ else
+ whole_archive_flag_spec=''
+ fi
+ link_all_deplibs=yes
+ allow_undefined_flag=$_lt_dar_allow_undefined
+ case $cc_basename in
+ ifort*|nagfor*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test yes = "$_lt_dar_can_shared"; then
+ output_verbose_link_cmd=func_echo_all
+ archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
+ module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
+ archive_expsym_cmds="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+ module_expsym_cmds="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+
+ else
+ ld_shlibs=no
+ fi
+
+ ;;
+
+ dgux*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2.*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | dragonfly* | midnightbsd*)
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9*)
+ if test yes = "$GCC"; then
+ archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec='$wl+b $wl$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ export_dynamic_flag_spec='$wl-E'
+ ;;
+
+ hpux10*)
+ if test yes,no = "$GCC,$with_gnu_ld"; then
+ archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test no = "$with_gnu_ld"; then
+ hardcode_libdir_flag_spec='$wl+b $wl$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ export_dynamic_flag_spec='$wl-E'
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test yes,no = "$GCC,$with_gnu_ld"; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+
+ # Older versions of the 11.00 compiler do not understand -b yet
+ # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
+printf %s "checking if $CC understands -b... " >&6; }
+if test ${lt_cv_prog_compiler__b+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_prog_compiler__b=no
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -b"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler__b=yes
+ fi
+ else
+ lt_cv_prog_compiler__b=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS=$save_LDFLAGS
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
+printf "%s\n" "$lt_cv_prog_compiler__b" >&6; }
+
+if test yes = "$lt_cv_prog_compiler__b"; then
+ archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+else
+ archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+fi
+
+ ;;
+ esac
+ fi
+ if test no = "$with_gnu_ld"; then
+ hardcode_libdir_flag_spec='$wl+b $wl$libdir'
+ hardcode_libdir_separator=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ ;;
+ *)
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ export_dynamic_flag_spec='$wl-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test yes = "$GCC"; then
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ # Try to use the -exported_symbol ld option, if it does not
+ # work, assume that -exports_file does not work either and
+ # implicitly export all symbols.
+ # This should be the same for all languages, so no per-tag cache variable.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5
+printf %s "checking whether the $host_os linker accepts -exported_symbol... " >&6; }
+if test ${lt_cv_irix_exported_symbol+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int foo (void) { return 0; }
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ lt_cv_irix_exported_symbol=yes
+else $as_nop
+ lt_cv_irix_exported_symbol=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$save_LDFLAGS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5
+printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; }
+ if test yes = "$lt_cv_irix_exported_symbol"; then
+ archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
+ fi
+ link_all_deplibs=no
+ else
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ hardcode_libdir_separator=:
+ inherit_rpath=yes
+ link_all_deplibs=yes
+ ;;
+
+ linux*)
+ case $cc_basename in
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ ld_shlibs=yes
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ ;;
+ esac
+ ;;
+
+ netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ newsos6)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ hardcode_libdir_separator=:
+ hardcode_shlibpath_var=no
+ ;;
+
+ *nto* | *qnx*)
+ ;;
+
+ openbsd* | bitrig*)
+ if test -f /usr/libexec/ld.so; then
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ hardcode_direct_absolute=yes
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+ export_dynamic_flag_spec='$wl-E'
+ else
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ shrext_cmds=.dll
+ archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ enable_shared_with_static_runtimes=yes
+ file_list_spec='@'
+ ;;
+
+ osf3*)
+ if test yes = "$GCC"; then
+ allow_undefined_flag=' $wl-expect_unresolved $wl\*'
+ archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test yes = "$GCC"; then
+ allow_undefined_flag=' $wl-expect_unresolved $wl\*'
+ archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_separator=:
+ ;;
+
+ solaris*)
+ no_undefined_flag=' -z defs'
+ if test yes = "$GCC"; then
+ wlarc='$wl'
+ archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ else
+ case `$CC -V 2>&1` in
+ *"Compilers 5.0"*)
+ wlarc=''
+ archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+ ;;
+ *)
+ wlarc='$wl'
+ archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ ;;
+ esac
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands '-z linker_flag'. GCC discards it without '$wl',
+ # but is careful enough not to reorder.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ if test yes = "$GCC"; then
+ whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+ else
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+ fi
+ ;;
+ esac
+ link_all_deplibs=yes
+ ;;
+
+ sunos4*)
+ if test sequent = "$host_vendor"; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds='$CC -r -o $output$reload_objs'
+ hardcode_direct=no
+ ;;
+ motorola)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ no_undefined_flag='$wl-z,text'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ runpath_var='LD_RUN_PATH'
+
+ if test yes = "$GCC"; then
+ archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We CANNOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag='$wl-z,text'
+ allow_undefined_flag='$wl-z,nodefs'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='$wl-R,$libdir'
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+ export_dynamic_flag_spec='$wl-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test yes = "$GCC"; then
+ archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+
+ if test sni = "$host_vendor"; then
+ case $host in
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ export_dynamic_flag_spec='$wl-Blargedynsym'
+ ;;
+ esac
+ fi
+ fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+printf "%s\n" "$ld_shlibs" >&6; }
+test no = "$ld_shlibs" && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc=yes
+
+ if test yes,yes = "$GCC,$enable_shared"; then
+ case $archive_cmds in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+printf %s "checking whether -lc should be explicitly linked in... " >&6; }
+if test ${lt_cv_archive_cmds_need_lc+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ $RM conftest*
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl
+ pic_flag=$lt_prog_compiler_pic
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag
+ allow_undefined_flag=
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+ (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ then
+ lt_cv_archive_cmds_need_lc=no
+ else
+ lt_cv_archive_cmds_need_lc=yes
+ fi
+ allow_undefined_flag=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $RM conftest*
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
+printf "%s\n" "$lt_cv_archive_cmds_need_lc" >&6; }
+ archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+printf %s "checking dynamic linker characteristics... " >&6; }
+
+if test yes = "$GCC"; then
+ case $host_os in
+ darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
+ *) lt_awk_arg='/^libraries:/' ;;
+ esac
+ case $host_os in
+ mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;;
+ *) lt_sed_strip_eq='s|=/|/|g' ;;
+ esac
+ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+ case $lt_search_path_spec in
+ *\;*)
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+ ;;
+ *)
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ esac
+ # Ok, now we have the path, separated by spaces, we can step through it
+ # and add multilib dir if necessary...
+ lt_tmp_lt_search_path_spec=
+ lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+ # ...but if some path component already ends with the multilib dir we assume
+ # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
+ case "$lt_multi_os_dir; $lt_search_path_spec " in
+ "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
+ lt_multi_os_dir=
+ ;;
+ esac
+ for lt_sys_path in $lt_search_path_spec; do
+ if test -d "$lt_sys_path$lt_multi_os_dir"; then
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
+ elif test -n "$lt_multi_os_dir"; then
+ test -d "$lt_sys_path" && \
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+ fi
+ done
+ lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS = " "; FS = "/|\n";} {
+ lt_foo = "";
+ lt_count = 0;
+ for (lt_i = NF; lt_i > 0; lt_i--) {
+ if ($lt_i != "" && $lt_i != ".") {
+ if ($lt_i == "..") {
+ lt_count++;
+ } else {
+ if (lt_count == 0) {
+ lt_foo = "/" $lt_i lt_foo;
+ } else {
+ lt_count--;
+ }
+ }
+ }
+ }
+ if (lt_foo != "") { lt_freq[lt_foo]++; }
+ if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+ # AWK program above erroneously prepends '/' to C:/dos/paths
+ # for these hosts.
+ case $host_os in
+ mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+ $SED 's|/\([A-Za-z]:\)|\1|g'` ;;
+ esac
+ sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=.so
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+
+
+case $host_os in
+aix3*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+
+aix[4-9]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 supports IA64
+ library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line '#! .'. This would cause the generated library to
+ # depend on '.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # Using Import Files as archive members, it is possible to support
+ # filename-based versioning of shared library archives on AIX. While
+ # this would work for both with and without runtime linking, it will
+ # prevent static linking of such archives. So we do filename-based
+ # shared library versioning with .so extension only, which is used
+ # when both runtime linking and shared linking is enabled.
+ # Unfortunately, runtime linking may impact performance, so we do
+ # not want this to be the default eventually. Also, we use the
+ # versioned .so libs for executables only if there is the -brtl
+ # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+ # To allow for filename-based versioning support, we need to create
+ # libNAME.so.V as an archive file, containing:
+ # *) an Import File, referring to the versioned filename of the
+ # archive as well as the shared archive member, telling the
+ # bitwidth (32 or 64) of that shared object, and providing the
+ # list of exported symbols of that shared object, eventually
+ # decorated with the 'weak' keyword
+ # *) the shared object with the F_LOADONLY flag set, to really avoid
+ # it being seen by the linker.
+ # At run time we better use the real file rather than another symlink,
+ # but for link time we create the symlink libNAME.so -> libNAME.so.V
+
+ case $with_aix_soname,$aix_use_runtimelinking in
+ # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ aix,yes) # traditional libtool
+ dynamic_linker='AIX unversionable lib.so'
+ # If using run time linking (on AIX 4.2 or later) use lib.so
+ # instead of lib.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ ;;
+ aix,no) # traditional AIX only
+ dynamic_linker='AIX lib.a(lib.so.V)'
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='$libname$release.a $libname.a'
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+ svr4,*) # full svr4 only
+ dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,yes) # both, prefer svr4
+ dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # unpreferred sharedlib libNAME.a needs extra handling
+ postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+ postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,no) # both, prefer aix
+ dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)"
+ library_names_spec='$libname$release.a $libname.a'
+ soname_spec='$libname$release$shared_ext$major'
+ # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+ postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+ postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+ ;;
+ esac
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ case $host_cpu in
+ powerpc)
+ # Since July 2007 AmigaOS4 officially supports .so libraries.
+ # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ ;;
+ m68k)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+ esac
+ ;;
+
+beos*)
+ library_names_spec='$libname$shared_ext'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+ version_type=windows
+ shrext_cmds=.dll
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$cc_basename in
+ yes,*)
+ # gcc
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ ;;
+
+ *,cl* | *,icl*)
+ # Native MSVC or ICC
+ libname_spec='$name'
+ soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+ library_names_spec='$libname.dll.lib'
+
+ case $build_os in
+ mingw*)
+ sys_lib_search_path_spec=
+ lt_save_ifs=$IFS
+ IFS=';'
+ for lt_path in $LIB
+ do
+ IFS=$lt_save_ifs
+ # Let DOS variable expansion print the short 8.3 style file name.
+ lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+ sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+ done
+ IFS=$lt_save_ifs
+ # Convert to MSYS style.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
+ ;;
+ cygwin*)
+ # Convert to unix form, then to dos form, then back to unix form
+ # but this time dos style (no spaces!) so that the unix form looks
+ # like /cygdrive/c/PROGRA~1:/cygdr...
+ sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+ sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+ sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ *)
+ sys_lib_search_path_spec=$LIB
+ if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ # FIXME: find the short name or the path components, as spaces are
+ # common. (e.g. "Program Files" -> "PROGRA~1")
+ ;;
+ esac
+
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+ dynamic_linker='Win32 link.exe'
+ ;;
+
+ *)
+ # Assume MSVC and ICC wrapper
+ library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib'
+ dynamic_linker='Win32 ld.exe'
+ ;;
+ esac
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
+ soname_spec='$libname$release$major$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd* | dragonfly* | midnightbsd*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[23].*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2.*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ *) # from 4.6 on, and DragonFly
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+haiku*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ dynamic_linker="$host_os runtime_loader"
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ if test 32 = "$HPUX_IA64_MODE"; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+ fi
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+ postinstall_cmds='chmod 555 $lib'
+ # or fails outright, so override atomically:
+ install_override_mode=555
+ ;;
+
+interix[3-9]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test yes = "$lt_cv_prog_gnu_ld"; then
+ version_type=linux # correct to gnu/linux during the next big refactor
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='$libname$release$shared_ext$major'
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
+ sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+linux*android*)
+ version_type=none # Android doesn't support versioned libraries.
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext'
+ soname_spec='$libname$release$shared_ext'
+ finish_cmds=
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ dynamic_linker='Android linker'
+ # Don't embed -rpath directories since the linker doesn't support them.
+ hardcode_libdir_flag_spec='-L$libdir'
+ ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+
+ # Some binutils ld are patched to set DT_RUNPATH
+ if test ${lt_cv_shlibpath_overrides_runpath+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ lt_cv_shlibpath_overrides_runpath=no
+ save_LDFLAGS=$LDFLAGS
+ save_libdir=$libdir
+ eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null
+then :
+ lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$save_LDFLAGS
+ libdir=$save_libdir
+
+fi
+
+ shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Ideally, we could use ldconfig to report *all* directores which are
+ # searched for libraries, however this is still not possible. Aside from not
+ # being certain /sbin/ldconfig is available, command
+ # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+ # even though it is searched at run-time. Try to do the best guess by
+ # appending ld.so.conf contents (and includes) to the search path.
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsdelf*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='NetBSD ld.elf_so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+*nto* | *qnx*)
+ version_type=qnx
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='ldqnx.so'
+ ;;
+
+openbsd* | bitrig*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec=/usr/lib
+ need_lib_prefix=no
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ need_version=no
+ else
+ need_version=yes
+ fi
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+os2*)
+ libname_spec='$name'
+ version_type=windows
+ shrext_cmds=.dll
+ need_version=no
+ need_lib_prefix=no
+ # OS/2 can only load a DLL with a base name of 8 characters or less.
+ soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+ v=$($ECHO $release$versuffix | tr -d .-);
+ n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+ $ECHO $n$v`$shared_ext'
+ library_names_spec='${libname}_dll.$libext'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=BEGINLIBPATH
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='$libname$release$shared_ext$major'
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+
+rdos*)
+ dynamic_linker=no
+ ;;
+
+solaris*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test yes = "$with_gnu_ld"; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec; then
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
+ soname_spec='$libname$shared_ext.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=sco
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ if test yes = "$with_gnu_ld"; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+tpf*)
+ # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+uts4*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+printf "%s\n" "$dynamic_linker" >&6; }
+test no = "$dynamic_linker" && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test yes = "$GCC"; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+ sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
+fi
+
+if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+ sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
+fi
+
+# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+
+# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+
+# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+printf %s "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+ test -n "$runpath_var" ||
+ test yes = "$hardcode_automatic"; then
+
+ # We can hardcode non-existent directories.
+ if test no != "$hardcode_direct" &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" &&
+ test no != "$hardcode_minus_L"; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action=unsupported
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+printf "%s\n" "$hardcode_action" >&6; }
+
+if test relink = "$hardcode_action" ||
+ test yes = "$inherit_rpath"; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test yes = "$shlibpath_overrides_runpath" ||
+ test no = "$enable_shared"; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+
+
+
+
+ if test yes != "$enable_dlopen"; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen=load_add_on
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32* | cegcc*)
+ lt_cv_dlopen=LoadLibrary
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen=dlopen
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+printf %s "checking for dlopen in -ldl... " >&6; }
+if test ${ac_cv_lib_dl_dlopen+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+int
+main (void)
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_dl_dlopen=yes
+else $as_nop
+ ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes
+then :
+ lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
+else $as_nop
+
+ lt_cv_dlopen=dyld
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+
+fi
+
+ ;;
+
+ tpf*)
+ # Don't try to run any link tests for TPF. We know it's impossible
+ # because TPF is a cross-compiler, and we know how we open DSOs.
+ lt_cv_dlopen=dlopen
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=no
+ ;;
+
+ *)
+ ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = xyes
+then :
+ lt_cv_dlopen=shl_load
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+printf %s "checking for shl_load in -ldld... " >&6; }
+if test ${ac_cv_lib_dld_shl_load+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char shl_load ();
+int
+main (void)
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_dld_shl_load=yes
+else $as_nop
+ ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = xyes
+then :
+ lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld
+else $as_nop
+ ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = xyes
+then :
+ lt_cv_dlopen=dlopen
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+printf %s "checking for dlopen in -ldl... " >&6; }
+if test ${ac_cv_lib_dl_dlopen+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+int
+main (void)
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_dl_dlopen=yes
+else $as_nop
+ ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+printf "%s\n" "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes
+then :
+ lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+printf %s "checking for dlopen in -lsvld... " >&6; }
+if test ${ac_cv_lib_svld_dlopen+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char dlopen ();
+int
+main (void)
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_svld_dlopen=yes
+else $as_nop
+ ac_cv_lib_svld_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+printf "%s\n" "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = xyes
+then :
+ lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+printf %s "checking for dld_link in -ldld... " >&6; }
+if test ${ac_cv_lib_dld_dld_link+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char dld_link ();
+int
+main (void)
+{
+return dld_link ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_dld_dld_link=yes
+else $as_nop
+ ac_cv_lib_dld_dld_link=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+printf "%s\n" "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = xyes
+then :
+ lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+ ;;
+ esac
+
+ if test no = "$lt_cv_dlopen"; then
+ enable_dlopen=no
+ else
+ enable_dlopen=yes
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS=$CPPFLAGS
+ test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS=$LDFLAGS
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS=$LIBS
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+printf %s "checking whether a program can dlopen itself... " >&6; }
+if test ${lt_cv_dlopen_self+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test yes = "$cross_compiling"; then :
+ lt_cv_dlopen_self=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include
+#endif
+
+#include
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+ correspondingly for the symbols needed. */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else
+ {
+ if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ else puts (dlerror ());
+ }
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}
+_LT_EOF
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+printf "%s\n" "$lt_cv_dlopen_self" >&6; }
+
+ if test yes = "$lt_cv_dlopen_self"; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+printf %s "checking whether a statically linked program can dlopen itself... " >&6; }
+if test ${lt_cv_dlopen_self_static+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test yes = "$cross_compiling"; then :
+ lt_cv_dlopen_self_static=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include
+#endif
+
+#include
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+ correspondingly for the symbols needed. */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else
+ {
+ if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ else puts (dlerror ());
+ }
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}
+_LT_EOF
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self_static=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+printf "%s\n" "$lt_cv_dlopen_self_static" >&6; }
+ fi
+
+ CPPFLAGS=$save_CPPFLAGS
+ LDFLAGS=$save_LDFLAGS
+ LIBS=$save_LIBS
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+printf %s "checking whether stripping libraries is possible... " >&6; }
+if test -z "$STRIP"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+else
+ if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+ old_striplib="$STRIP --strip-debug"
+ striplib="$STRIP --strip-unneeded"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ else
+ case $host_os in
+ darwin*)
+ # FIXME - insert some real tests, host_os isn't really good enough
+ striplib="$STRIP -x"
+ old_striplib="$STRIP -S"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ ;;
+ freebsd*)
+ if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
+ old_striplib="$STRIP --strip-debug"
+ striplib="$STRIP --strip-unneeded"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ fi
+ ;;
+ *)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ ;;
+ esac
+ fi
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+ # Report what library types will actually be built
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+printf %s "checking if libtool supports shared libraries... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+printf "%s\n" "$can_build_shared" >&6; }
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+printf %s "checking whether to build shared libraries... " >&6; }
+ test no = "$can_build_shared" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[4-9]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ fi
+ ;;
+ esac
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+printf "%s\n" "$enable_shared" >&6; }
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+printf %s "checking whether to build static libraries... " >&6; }
+ # Make sure either enable_shared or enable_static is yes.
+ test yes = "$enable_shared" || enable_static=yes
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+printf "%s\n" "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC=$lt_save_CC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ac_config_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+: ${CONFIG_LT=./config.lt}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_LT" >&5
+printf "%s\n" "$as_me: creating $CONFIG_LT" >&6;}
+as_write_fail=0
+cat >"$CONFIG_LT" <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate a libtool stub with the current configuration.
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>"$CONFIG_LT" <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else $as_nop
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
+as_nl='
+'
+export as_nl
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
+
+# The user is always right.
+if ${PATH_SEPARATOR+false} :; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ printf "%s\n" "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else $as_nop
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else $as_nop
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## --------------------------------- ##
+## Main body of "$CONFIG_LT" script. ##
+## --------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x "$CONFIG_LT"
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+lt_cl_silent=false
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+
+lt_cl_help="\
+'$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $0 [OPTIONS]
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+
+Report bugs to ."
+
+lt_cl_version="\
+PCRE2 config.lt 10.48
+configured by $0, generated by GNU Autoconf 2.71.
+
+Copyright (C) 2011 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test 0 != $#
+do
+ case $1 in
+ --version | --v* | -V )
+ echo "$lt_cl_version"; exit 0 ;;
+ --help | --h* | -h )
+ echo "$lt_cl_help"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --quiet | --q* | --silent | --s* | -q )
+ lt_cl_silent=: ;;
+
+ -*) as_fn_error $? "unrecognized option: $1
+Try '$0 --help' for more information." "$LINENO" 5 ;;
+
+ *) as_fn_error $? "unrecognized argument: $1
+Try '$0 --help' for more information." "$LINENO" 5 ;;
+ esac
+ shift
+done
+
+if $lt_cl_silent; then
+ exec 6>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`'
+DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`'
+SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
+host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
+build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
+build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
+SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
+Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
+GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
+EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
+FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
+LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
+NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
+LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
+exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+FILECMD='`$ECHO "$FILECMD" | $SED "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
+want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
+sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
+AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
+STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
+lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
+CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
+compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`'
+nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
+lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
+lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`'
+objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
+libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
+version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
+install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`'
+configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
+striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in AS \
+DLLTOOL \
+OBJDUMP \
+SHELL \
+ECHO \
+PATH_SEPARATOR \
+SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+FILECMD \
+deplibs_check_method \
+file_magic_cmd \
+file_magic_glob \
+want_nocaseglob \
+sharedlib_from_linklib_cmd \
+AR \
+archiver_list_spec \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_import \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+lt_cv_nm_interface \
+nm_file_list_spec \
+lt_cv_truncate_bin \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_pic \
+lt_prog_compiler_wl \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+MANIFEST_TOOL \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_separator \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+install_override_mode \
+finish_eval \
+old_striplib \
+striplib; do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postlink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+configure_time_dlsearch_path \
+configure_time_lt_sys_library_path; do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+ac_aux_dir='$ac_aux_dir'
+
+# See if we are running on zsh, and set the options that allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+fi
+
+
+ PACKAGE='$PACKAGE'
+ VERSION='$VERSION'
+ RM='$RM'
+ ofile='$ofile'
+
+
+
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ofile" >&5
+printf "%s\n" "$as_me: creating $ofile" >&6;}
+
+
+ # See if we are running on zsh, and set the options that allow our
+ # commands through without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+ fi
+
+ cfgfile=${ofile}T
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+ $RM "$cfgfile"
+
+ cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+# Generated automatically by $as_me ($PACKAGE) $VERSION
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit, 1996
+
+# Copyright (C) 2014 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions. There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program or library that is built
+# using GNU Libtool, you may include this file under the same
+# distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=''
+
+# Configured defaults for sys_lib_dlsearch_path munging.
+: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Assembler program.
+AS=$lt_AS
+
+# DLL creation program.
+DLLTOOL=$lt_DLLTOOL
+
+# Object dumper program.
+OBJDUMP=$lt_OBJDUMP
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shared archive member basename,for filename based shared library versioning on AIX.
+shared_archive_member_spec=$shared_archive_member_spec
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# The PATH separator for the build system.
+PATH_SEPARATOR=$lt_PATH_SEPARATOR
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# convert \$build file names to \$host format.
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+
+# convert \$build files to toolchain format.
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+
+# A file(cmd) program that detects file types.
+FILECMD=$lt_FILECMD
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method = "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# How to find potential files when deplibs_check_method = "file_magic".
+file_magic_glob=$lt_file_magic_glob
+
+# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
+want_nocaseglob=$lt_want_nocaseglob
+
+# Command to associate shared and link libraries.
+sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
+
+# The archiver.
+AR=$lt_AR
+
+# Flags to create an archive (by configure).
+lt_ar_flags=$lt_ar_flags
+
+# Flags to create an archive.
+AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"}
+
+# How to feed a file listing to the archiver.
+archiver_list_spec=$lt_archiver_list_spec
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm into a list of symbols to manually relocate.
+global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# The name lister interface.
+nm_interface=$lt_lt_cv_nm_interface
+
+# Specify filename containing input files for \$NM.
+nm_file_list_spec=$lt_nm_file_list_spec
+
+# The root where to search for dependent libraries,and where our libraries should be installed.
+lt_sysroot=$lt_sysroot
+
+# Command to truncate a binary pipe.
+lt_truncate_bin=$lt_lt_cv_truncate_bin
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Manifest tool.
+MANIFEST_TOOL=$lt_MANIFEST_TOOL
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Detected run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path
+
+# Explicit LT_SYS_LIBRARY_PATH set during ./configure time.
+configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \$shlibpath_var if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+ cat <<'_LT_EOF' >> "$cfgfile"
+
+# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+
+# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+# string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+# string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+# "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+# VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+ case x$2 in
+ x)
+ ;;
+ *:)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+ ;;
+ x:*)
+ eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ *::*)
+ eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+ eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+ ;;
+ *)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ esac
+}
+
+
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+ for cc_temp in $*""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+ done
+ func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+
+
+# ### END FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_EOF
+
+ case $host_os in
+ aix3*)
+ cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test set != "${COLLECT_NAMES+set}"; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+_LT_EOF
+ ;;
+ esac
+
+
+
+ltmain=$ac_aux_dir/ltmain.sh
+
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ $SED '$q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" ||
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+
+
+as_fn_exit 0
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure. Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+lt_cl_success=:
+test yes = "$silent" &&
+ lt_config_lt_args="$lt_config_lt_args --quiet"
+exec 5>/dev/null
+$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+exec 5>>config.log
+$lt_cl_success || as_fn_exit 1
+
+
+# Check whether --enable-largefile was given.
+if test ${enable_largefile+y}
+then :
+ enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+printf %s "checking for special C compiler options needed for large files... " >&6; }
+if test ${ac_cv_sys_largefile_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_sys_largefile_CC=no
+ if test "$GCC" != yes; then
+ ac_save_CC=$CC
+ while :; do
+ # IRIX 6.2 and later do not support large files by default,
+ # so use the C compiler's -n32 option if that helps.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ CC="$CC -n32"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_sys_largefile_CC=' -n32'; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ break
+ done
+ CC=$ac_save_CC
+ rm -f conftest.$ac_ext
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+printf "%s\n" "$ac_cv_sys_largefile_CC" >&6; }
+ if test "$ac_cv_sys_largefile_CC" != no; then
+ CC=$CC$ac_cv_sys_largefile_CC
+ fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+printf %s "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if test ${ac_cv_sys_file_offset_bits+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_sys_file_offset_bits=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _FILE_OFFSET_BITS 64
+#include
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_sys_file_offset_bits=64; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_cv_sys_file_offset_bits=unknown
+ break
+done
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+printf "%s\n" "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+ no | unknown) ;;
+ *)
+printf "%s\n" "#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits" >>confdefs.h
+;;
+esac
+rm -rf conftest*
+ if test $ac_cv_sys_file_offset_bits = unknown; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+printf %s "checking for _LARGE_FILES value needed for large files... " >&6; }
+if test ${ac_cv_sys_large_files+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _LARGE_FILES 1
+#include
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 31 << 31) - 1 + ((off_t) 1 << 31 << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_sys_large_files=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_cv_sys_large_files=unknown
+ break
+done
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+printf "%s\n" "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+ no | unknown) ;;
+ *)
+printf "%s\n" "#define _LARGE_FILES $ac_cv_sys_large_files" >>confdefs.h
+;;
+esac
+rm -rf conftest*
+ fi
+fi
+
+
+# Check for GCC visibility feature
+
+
+
+ VISIBILITY_CFLAGS=
+ HAVE_VISIBILITY=0
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the -Werror option is usable" >&5
+printf %s "checking whether the -Werror option is usable... " >&6; }
+ if test ${pcre2_cv_cc_vis_werror+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ pcre2_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror"
+ pcre2_cv_cc_vis_werror=no
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+ #warning e
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else $as_nop
+ pcre2_cv_cc_vis_werror=yes
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS="$pcre2_save_CFLAGS"
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pcre2_cv_cc_vis_werror" >&5
+printf "%s\n" "$pcre2_cv_cc_vis_werror" >&6; }
+ if test -n "$pcre2_cv_cc_vis_werror" && test $pcre2_cv_cc_vis_werror = yes
+ then
+ WORKING_WERROR=1
+ else
+ WORKING_WERROR=0
+ fi
+ if test $pcre2_cv_cc_vis_werror = yes; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GCC compatible visibility declarations" >&5
+printf %s "checking for GCC compatible visibility declarations... " >&6; }
+ if test ${pcre2_cv_cc_visibility+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ pcre2_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void);
+ extern __attribute__((__visibility__("default"))) int exportedfunc (void);
+ void dummyfunc (void) {}
+
+int
+main (void)
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ pcre2_cv_cc_visibility=yes
+else $as_nop
+ pcre2_cv_cc_visibility=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CFLAGS="$pcre2_save_CFLAGS"
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pcre2_cv_cc_visibility" >&5
+printf "%s\n" "$pcre2_cv_cc_visibility" >&6; }
+ fi
+ if test -n "$pcre2_cv_cc_visibility" && test $pcre2_cv_cc_visibility = yes
+ then
+ VISIBILITY_CFLAGS="-fvisibility=hidden"
+ HAVE_VISIBILITY=1
+
+printf "%s\n" "#define PCRE2_EXPORT __attribute__ ((visibility (\"default\")))" >>confdefs.h
+
+ else
+
+printf "%s\n" "#define PCRE2_EXPORT /**/" >>confdefs.h
+
+ fi
+
+
+
+printf "%s\n" "#define HAVE_VISIBILITY $HAVE_VISIBILITY" >>confdefs.h
+
+
+
+# Check for the availability of -Wl,--version-script (or -Wl,-M on Solaris)
+
+
+
+ # Check whether --enable-symvers was given.
+if test ${enable_symvers+y}
+then :
+ enableval=$enable_symvers; want_symvers=$enableval
+else $as_nop
+ want_symvers=yes
+
+fi
+
+
+ if test x$want_symvers = xyes
+then :
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking linker version script flag" >&5
+printf %s "checking linker version script flag... " >&6; }
+if test ${pcre2_cv_check_vscript_flag+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ pcre2_cv_check_vscript_flag=unsupported
+
+
+ rm -rf conftest.vscript
+ mkdir conftest.vscript
+ cat > conftest.vscript/conftest.c <<_ACEOF
+int hidethis(void) { return 0; }
+int exposethis(void) { return hidethis(); }
+_ACEOF
+ echo "PCRE2_10.00 { global: exposethis; local: *; };" > conftest.vscript/conftest.map
+ _pcre2_abs_top_builddir="$ac_pwd"
+ _pcre2_vscript_libtool="$SHELL $_pcre2_abs_top_builddir/libtool"
+ _pcre2_vscript_cc="$CC"
+ _pcre2_vscript_compile_flags="$CFLAGS $CPPFLAGS"
+ _pcre2_vscript_ld_flags="$CFLAGS $LDFLAGS"
+ _pcre2_vscript_script_flag="--version-script"
+ export _pcre2_vscript_libtool
+ export _pcre2_vscript_cc
+ export _pcre2_vscript_compile_flags
+ export _pcre2_vscript_ld_flags
+ export _pcre2_vscript_script_flag
+ if (cd conftest.vscript && \
+ $_pcre2_vscript_libtool --tag=CC --mode=compile $_pcre2_vscript_cc $_pcre2_vscript_compile_flags -c -o conftest.lo conftest.c && \
+ $_pcre2_vscript_libtool --tag=CC --mode=link $_pcre2_vscript_cc $_pcre2_vscript_ld_flags -o libconftest.la conftest.lo -rpath /usr/lib -Wl,$_pcre2_vscript_script_flag,conftest.map) >&5 2>&1
+then :
+ pcre2_cv_check_vscript_flag=--version-script
+fi
+ unset _pcre2_vscript_libtool
+ unset _pcre2_vscript_cc
+ unset _pcre2_vscript_compile_flags
+ unset _pcre2_vscript_ld_flags
+ unset _pcre2_vscript_script_flag
+ rm -rf conftest.vscript
+
+ if test x$pcre2_cv_check_vscript_flag = xunsupported
+then :
+
+
+ rm -rf conftest.vscript
+ mkdir conftest.vscript
+ cat > conftest.vscript/conftest.c <<_ACEOF
+int hidethis(void) { return 0; }
+int exposethis(void) { return hidethis(); }
+_ACEOF
+ echo "PCRE2_10.00 { global: exposethis; local: *; };" > conftest.vscript/conftest.map
+ _pcre2_abs_top_builddir="$ac_pwd"
+ _pcre2_vscript_libtool="$SHELL $_pcre2_abs_top_builddir/libtool"
+ _pcre2_vscript_cc="$CC"
+ _pcre2_vscript_compile_flags="$CFLAGS $CPPFLAGS"
+ _pcre2_vscript_ld_flags="$CFLAGS $LDFLAGS"
+ _pcre2_vscript_script_flag="-M"
+ export _pcre2_vscript_libtool
+ export _pcre2_vscript_cc
+ export _pcre2_vscript_compile_flags
+ export _pcre2_vscript_ld_flags
+ export _pcre2_vscript_script_flag
+ if (cd conftest.vscript && \
+ $_pcre2_vscript_libtool --tag=CC --mode=compile $_pcre2_vscript_cc $_pcre2_vscript_compile_flags -c -o conftest.lo conftest.c && \
+ $_pcre2_vscript_libtool --tag=CC --mode=link $_pcre2_vscript_cc $_pcre2_vscript_ld_flags -o libconftest.la conftest.lo -rpath /usr/lib -Wl,$_pcre2_vscript_script_flag,conftest.map) >&5 2>&1
+then :
+ pcre2_cv_check_vscript_flag=-M
+fi
+ unset _pcre2_vscript_libtool
+ unset _pcre2_vscript_cc
+ unset _pcre2_vscript_compile_flags
+ unset _pcre2_vscript_ld_flags
+ unset _pcre2_vscript_script_flag
+ rm -rf conftest.vscript
+
+
+fi
+
+
+ if test x$pcre2_cv_check_vscript_flag != xunsupported
+then :
+
+
+ rm -rf conftest.vscript
+ mkdir conftest.vscript
+ cat > conftest.vscript/conftest.c <<_ACEOF
+int hidethis(void) { return 0; }
+int exposethis(void) { return hidethis(); }
+_ACEOF
+ echo "PCRE2_10.00 { global: exposethis; local: *; }; {" > conftest.vscript/conftest.map
+ _pcre2_abs_top_builddir="$ac_pwd"
+ _pcre2_vscript_libtool="$SHELL $_pcre2_abs_top_builddir/libtool"
+ _pcre2_vscript_cc="$CC"
+ _pcre2_vscript_compile_flags="$CFLAGS $CPPFLAGS"
+ _pcre2_vscript_ld_flags="$CFLAGS $LDFLAGS"
+ _pcre2_vscript_script_flag="$pcre2_cv_check_vscript_flag"
+ export _pcre2_vscript_libtool
+ export _pcre2_vscript_cc
+ export _pcre2_vscript_compile_flags
+ export _pcre2_vscript_ld_flags
+ export _pcre2_vscript_script_flag
+ if (cd conftest.vscript && \
+ $_pcre2_vscript_libtool --tag=CC --mode=compile $_pcre2_vscript_cc $_pcre2_vscript_compile_flags -c -o conftest.lo conftest.c && \
+ $_pcre2_vscript_libtool --tag=CC --mode=link $_pcre2_vscript_cc $_pcre2_vscript_ld_flags -o libconftest.la conftest.lo -rpath /usr/lib -Wl,$_pcre2_vscript_script_flag,conftest.map) >&5 2>&1
+then :
+ pcre2_cv_check_vscript_flag=unsupported
+fi
+ unset _pcre2_vscript_libtool
+ unset _pcre2_vscript_cc
+ unset _pcre2_vscript_compile_flags
+ unset _pcre2_vscript_ld_flags
+ unset _pcre2_vscript_script_flag
+ rm -rf conftest.vscript
+
+
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pcre2_cv_check_vscript_flag" >&5
+printf "%s\n" "$pcre2_cv_check_vscript_flag" >&6; }
+
+ if test x$pcre2_cv_check_vscript_flag != xunsupported
+then :
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if version scripts work without wildcard" >&5
+printf %s "checking if version scripts work without wildcard... " >&6; }
+if test ${pcre2_cv_check_vscript_no_star+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ pcre2_cv_check_vscript_no_star=no
+
+ rm -rf conftest.vscript
+ mkdir conftest.vscript
+ cat > conftest.vscript/conftest.c <<_ACEOF
+int hidethis(void) { return 0; }
+int exposethis(void) { return hidethis(); }
+_ACEOF
+ echo "PCRE2_10.00 { global: exposethis; local: hidethis; };" > conftest.vscript/conftest.map
+ _pcre2_abs_top_builddir="$ac_pwd"
+ _pcre2_vscript_libtool="$SHELL $_pcre2_abs_top_builddir/libtool"
+ _pcre2_vscript_cc="$CC"
+ _pcre2_vscript_compile_flags="$CFLAGS $CPPFLAGS"
+ _pcre2_vscript_ld_flags="$CFLAGS $LDFLAGS"
+ _pcre2_vscript_script_flag="$pcre2_cv_check_vscript_flag"
+ export _pcre2_vscript_libtool
+ export _pcre2_vscript_cc
+ export _pcre2_vscript_compile_flags
+ export _pcre2_vscript_ld_flags
+ export _pcre2_vscript_script_flag
+ if (cd conftest.vscript && \
+ $_pcre2_vscript_libtool --tag=CC --mode=compile $_pcre2_vscript_cc $_pcre2_vscript_compile_flags -c -o conftest.lo conftest.c && \
+ $_pcre2_vscript_libtool --tag=CC --mode=link $_pcre2_vscript_cc $_pcre2_vscript_ld_flags -o libconftest.la conftest.lo -rpath /usr/lib -Wl,$_pcre2_vscript_script_flag,conftest.map) >&5 2>&1
+then :
+ pcre2_cv_check_vscript_no_star=yes
+fi
+ unset _pcre2_vscript_libtool
+ unset _pcre2_vscript_cc
+ unset _pcre2_vscript_compile_flags
+ unset _pcre2_vscript_ld_flags
+ unset _pcre2_vscript_script_flag
+ rm -rf conftest.vscript
+
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pcre2_cv_check_vscript_no_star" >&5
+printf "%s\n" "$pcre2_cv_check_vscript_no_star" >&6; }
+
+ pcre2_check_vscript_flag=$pcre2_cv_check_vscript_flag
+ pcre2_check_vscript_no_star=$pcre2_cv_check_vscript_no_star
+
+else $as_nop
+
+ pcre2_check_vscript_flag=
+ pcre2_check_vscript_no_star=no
+
+fi
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking linker version script flag" >&5
+printf %s "checking linker version script flag... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
+printf "%s\n" "disabled" >&6; }
+
+ pcre2_check_vscript_flag=
+ pcre2_check_vscript_no_star=no
+
+fi
+
+
+
+# Check for Clang __attribute__((uninitialized)) feature
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __attribute__((uninitialized))" >&5
+printf %s "checking for __attribute__((uninitialized))... " >&6; }
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+tmp_CFLAGS=$CFLAGS
+if test $WORKING_WERROR -eq 1; then
+ CFLAGS="$CFLAGS -Werror"
+fi
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+char buf[128] __attribute__((uninitialized));(void)buf
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ pcre2_cc_cv_attribute_uninitialized=yes
+else $as_nop
+ pcre2_cc_cv_attribute_uninitialized=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pcre2_cc_cv_attribute_uninitialized" >&5
+printf "%s\n" "$pcre2_cc_cv_attribute_uninitialized" >&6; }
+if test "$pcre2_cc_cv_attribute_uninitialized" = yes; then
+
+printf "%s\n" "#define HAVE_ATTRIBUTE_UNINITIALIZED 1" >>confdefs.h
+
+fi
+CFLAGS=$tmp_CFLAGS
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Check for the assume() builtin
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __assume()" >&5
+printf %s "checking for __assume()... " >&6; }
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+__assume(1)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ pcre2_cc_cv_builtin_assume=yes
+else $as_nop
+ pcre2_cc_cv_builtin_assume=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pcre2_cc_cv_builtin_assume" >&5
+printf "%s\n" "$pcre2_cc_cv_builtin_assume" >&6; }
+if test "$pcre2_cc_cv_builtin_assume" = yes; then
+
+printf "%s\n" "#define HAVE_BUILTIN_ASSUME 1" >>confdefs.h
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Check for the mul_overflow() builtin
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __builtin_mul_overflow()" >&5
+printf %s "checking for __builtin_mul_overflow()... " >&6; }
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #ifdef HAVE_SYS_TYPES_H
+ #include
+ #endif
+ #include
+
+ int a, b;
+ size_t m;
+
+int
+main (void)
+{
+__builtin_mul_overflow(a, b, &m)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ pcre2_cc_cv_builtin_mul_overflow=yes
+else $as_nop
+ pcre2_cc_cv_builtin_mul_overflow=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pcre2_cc_cv_builtin_mul_overflow" >&5
+printf "%s\n" "$pcre2_cc_cv_builtin_mul_overflow" >&6; }
+if test "$pcre2_cc_cv_builtin_mul_overflow" = yes; then
+
+printf "%s\n" "#define HAVE_BUILTIN_MUL_OVERFLOW 1" >>confdefs.h
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Check for the unreachable() builtin
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __builtin_unreachable()" >&5
+printf %s "checking for __builtin_unreachable()... " >&6; }
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int r;
+int
+main (void)
+{
+if (r) __builtin_unreachable()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ pcre2_cc_cv_builtin_unreachable=yes
+else $as_nop
+ pcre2_cc_cv_builtin_unreachable=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pcre2_cc_cv_builtin_unreachable" >&5
+printf "%s\n" "$pcre2_cc_cv_builtin_unreachable" >&6; }
+if test "$pcre2_cc_cv_builtin_unreachable" = yes; then
+
+printf "%s\n" "#define HAVE_BUILTIN_UNREACHABLE 1" >>confdefs.h
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Versioning
+
+PCRE2_MAJOR="10"
+PCRE2_MINOR="48"
+PCRE2_PRERELEASE=""
+PCRE2_DATE="2026-08-31"
+
+if test "$PCRE2_MINOR" = "08" -o "$PCRE2_MINOR" = "09"
+then
+ echo "***"
+ echo "*** Minor version number $PCRE2_MINOR must not be used. ***"
+ echo "*** Use only 00 to 07 or 10 onwards, to avoid octal issues. ***"
+ echo "***"
+ exit 1
+fi
+
+
+
+
+
+
+# Set a more sensible default value for $(htmldir).
+if test "x$htmldir" = 'x${docdir}'
+then
+ htmldir='${docdir}/html'
+fi
+
+# Force an error for PCRE1 size options
+# Check whether --enable-pcre8 was given.
+if test ${enable_pcre8+y}
+then :
+ enableval=$enable_pcre8;
+else $as_nop
+ enable_pcre8=no
+fi
+
+# Check whether --enable-pcre16 was given.
+if test ${enable_pcre16+y}
+then :
+ enableval=$enable_pcre16;
+else $as_nop
+ enable_pcre16=no
+fi
+
+# Check whether --enable-pcre32 was given.
+if test ${enable_pcre32+y}
+then :
+ enableval=$enable_pcre32;
+else $as_nop
+ enable_pcre32=no
+fi
+
+
+if test "$enable_pcre8$enable_pcre16$enable_pcre32" != "nonono"
+then
+ echo "** ERROR: Use --[en|dis]able-pcre2-[8|16|32], not --[en|dis]able-pcre[8|16|32]"
+ exit 1
+fi
+
+# Handle --disable-pcre2-8 (enabled by default)
+# Check whether --enable-pcre2-8 was given.
+if test ${enable_pcre2_8+y}
+then :
+ enableval=$enable_pcre2_8;
+else $as_nop
+ enable_pcre2_8=unset
+fi
+
+
+
+# Handle --enable-pcre2-16 (disabled by default)
+# Check whether --enable-pcre2-16 was given.
+if test ${enable_pcre2_16+y}
+then :
+ enableval=$enable_pcre2_16;
+else $as_nop
+ enable_pcre2_16=unset
+fi
+
+
+
+# Handle --enable-pcre2-32 (disabled by default)
+# Check whether --enable-pcre2-32 was given.
+if test ${enable_pcre2_32+y}
+then :
+ enableval=$enable_pcre2_32;
+else $as_nop
+ enable_pcre2_32=unset
+fi
+
+
+
+# Handle --enable-debug (disabled by default)
+# Check whether --enable-debug was given.
+if test ${enable_debug+y}
+then :
+ enableval=$enable_debug;
+else $as_nop
+ enable_debug=no
+fi
+
+
+# Handle --enable-jit (disabled by default)
+# Check whether --enable-jit was given.
+if test ${enable_jit+y}
+then :
+ enableval=$enable_jit;
+else $as_nop
+ enable_jit=no
+fi
+
+
+# This code enables JIT if the hardware supports it.
+if test "$enable_jit" = "auto"; then
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ SAVE_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS=-I$srcdir
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #define SLJIT_CONFIG_AUTO 1
+ #include "deps/sljit/sljit_src/sljitConfigCPU.h"
+ #if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
+ #error unsupported
+ #endif
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ enable_jit=yes
+else $as_nop
+ enable_jit=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ CPPFLAGS=$SAVE_CPPFLAGS
+ echo checking for JIT support on this hardware... $enable_jit
+fi
+
+# Handle --enable-jit-sealloc (disabled by default and only experimental)
+case $host_os in
+ linux* | netbsd*)
+ # Check whether --enable-jit-sealloc was given.
+if test ${enable_jit_sealloc+y}
+then :
+ enableval=$enable_jit_sealloc;
+else $as_nop
+ enable_jit_sealloc=no
+fi
+
+ ;;
+ *)
+ enable_jit_sealloc=unsupported
+ ;;
+esac
+
+# Handle --disable-pcre2grep-jit (enabled by default)
+# Check whether --enable-pcre2grep-jit was given.
+if test ${enable_pcre2grep_jit+y}
+then :
+ enableval=$enable_pcre2grep_jit;
+else $as_nop
+ enable_pcre2grep_jit=yes
+fi
+
+
+# Handle --disable-pcre2grep-callout (enabled by default)
+# Check whether --enable-pcre2grep-callout was given.
+if test ${enable_pcre2grep_callout+y}
+then :
+ enableval=$enable_pcre2grep_callout;
+else $as_nop
+ enable_pcre2grep_callout=yes
+fi
+
+
+# Handle --disable-pcre2grep-callout-fork (enabled by default)
+# Check whether --enable-pcre2grep-callout-fork was given.
+if test ${enable_pcre2grep_callout_fork+y}
+then :
+ enableval=$enable_pcre2grep_callout_fork;
+else $as_nop
+ enable_pcre2grep_callout_fork=yes
+fi
+
+
+# Handle --enable-rebuild-chartables
+# Check whether --enable-rebuild-chartables was given.
+if test ${enable_rebuild_chartables+y}
+then :
+ enableval=$enable_rebuild_chartables;
+else $as_nop
+ enable_rebuild_chartables=no
+fi
+
+
+# Handle --disable-unicode (enabled by default)
+# Check whether --enable-unicode was given.
+if test ${enable_unicode+y}
+then :
+ enableval=$enable_unicode;
+else $as_nop
+ enable_unicode=unset
+fi
+
+
+# Handle newline options
+ac_pcre2_newline=lf
+# Check whether --enable-newline-is-cr was given.
+if test ${enable_newline_is_cr+y}
+then :
+ enableval=$enable_newline_is_cr; ac_pcre2_newline=cr
+fi
+
+# Check whether --enable-newline-is-lf was given.
+if test ${enable_newline_is_lf+y}
+then :
+ enableval=$enable_newline_is_lf; ac_pcre2_newline=lf
+fi
+
+# Check whether --enable-newline-is-crlf was given.
+if test ${enable_newline_is_crlf+y}
+then :
+ enableval=$enable_newline_is_crlf; ac_pcre2_newline=crlf
+fi
+
+# Check whether --enable-newline-is-anycrlf was given.
+if test ${enable_newline_is_anycrlf+y}
+then :
+ enableval=$enable_newline_is_anycrlf; ac_pcre2_newline=anycrlf
+fi
+
+# Check whether --enable-newline-is-any was given.
+if test ${enable_newline_is_any+y}
+then :
+ enableval=$enable_newline_is_any; ac_pcre2_newline=any
+fi
+
+# Check whether --enable-newline-is-nul was given.
+if test ${enable_newline_is_nul+y}
+then :
+ enableval=$enable_newline_is_nul; ac_pcre2_newline=nul
+fi
+
+enable_newline="$ac_pcre2_newline"
+
+# Handle --enable-bsr-anycrlf
+# Check whether --enable-bsr-anycrlf was given.
+if test ${enable_bsr_anycrlf+y}
+then :
+ enableval=$enable_bsr_anycrlf;
+else $as_nop
+ enable_bsr_anycrlf=no
+fi
+
+
+# Handle --enable-never-backslash-C
+# Check whether --enable-never-backslash-C was given.
+if test ${enable_never_backslash_C+y}
+then :
+ enableval=$enable_never_backslash_C;
+else $as_nop
+ enable_never_backslash_C=no
+fi
+
+
+# Handle --enable-ebcdic
+# Check whether --enable-ebcdic was given.
+if test ${enable_ebcdic+y}
+then :
+ enableval=$enable_ebcdic;
+else $as_nop
+ enable_ebcdic=no
+fi
+
+
+# Handle --enable-ebcdic-nl25
+# Check whether --enable-ebcdic-nl25 was given.
+if test ${enable_ebcdic_nl25+y}
+then :
+ enableval=$enable_ebcdic_nl25;
+else $as_nop
+ enable_ebcdic_nl25=no
+fi
+
+
+# Handle --enable-ebcdic-ignoring-compiler
+# Check whether --enable-ebcdic-ignoring-compiler was given.
+if test ${enable_ebcdic_ignoring_compiler+y}
+then :
+ enableval=$enable_ebcdic_ignoring_compiler;
+else $as_nop
+ enable_ebcdic_ignoring_compiler=no
+fi
+
+
+# Handle --enable-pcre2grep-libz
+# Check whether --enable-pcre2grep-libz was given.
+if test ${enable_pcre2grep_libz+y}
+then :
+ enableval=$enable_pcre2grep_libz;
+else $as_nop
+ enable_pcre2grep_libz=no
+fi
+
+
+# Handle --enable-pcre2grep-libbz2
+# Check whether --enable-pcre2grep-libbz2 was given.
+if test ${enable_pcre2grep_libbz2+y}
+then :
+ enableval=$enable_pcre2grep_libbz2;
+else $as_nop
+ enable_pcre2grep_libbz2=no
+fi
+
+
+# Handle --with-pcre2grep-bufsize=N
+
+# Check whether --with-pcre2grep-bufsize was given.
+if test ${with_pcre2grep_bufsize+y}
+then :
+ withval=$with_pcre2grep_bufsize;
+else $as_nop
+ with_pcre2grep_bufsize=20480
+fi
+
+
+# Handle --with-pcre2grep-max-bufsize=N
+
+# Check whether --with-pcre2grep-max-bufsize was given.
+if test ${with_pcre2grep_max_bufsize+y}
+then :
+ withval=$with_pcre2grep_max_bufsize;
+else $as_nop
+ with_pcre2grep_max_bufsize=1048576
+fi
+
+
+# Handle --enable-pcre2test-libedit
+# Check whether --enable-pcre2test-libedit was given.
+if test ${enable_pcre2test_libedit+y}
+then :
+ enableval=$enable_pcre2test_libedit;
+else $as_nop
+ enable_pcre2test_libedit=no
+fi
+
+
+# Handle --enable-pcre2test-libreadline
+# Check whether --enable-pcre2test-libreadline was given.
+if test ${enable_pcre2test_libreadline+y}
+then :
+ enableval=$enable_pcre2test_libreadline;
+else $as_nop
+ enable_pcre2test_libreadline=no
+fi
+
+
+# Handle --with-link-size=N
+
+# Check whether --with-link-size was given.
+if test ${with_link_size+y}
+then :
+ withval=$with_link_size;
+else $as_nop
+ with_link_size=2
+fi
+
+
+# Handle --with-max-varlookbehind=N
+
+# Check whether --with-max-varlookbehind was given.
+if test ${with_max_varlookbehind+y}
+then :
+ withval=$with_max_varlookbehind;
+else $as_nop
+ with_max_varlookbehind=255
+fi
+
+
+# Handle --with-parens-nest-limit=N
+
+# Check whether --with-parens-nest-limit was given.
+if test ${with_parens_nest_limit+y}
+then :
+ withval=$with_parens_nest_limit;
+else $as_nop
+ with_parens_nest_limit=250
+fi
+
+
+# Handle --with-heap-limit
+
+# Check whether --with-heap-limit was given.
+if test ${with_heap_limit+y}
+then :
+ withval=$with_heap_limit;
+else $as_nop
+ with_heap_limit=20000000
+fi
+
+
+# Handle --with-match-limit=N
+
+# Check whether --with-match-limit was given.
+if test ${with_match_limit+y}
+then :
+ withval=$with_match_limit;
+else $as_nop
+ with_match_limit=10000000
+fi
+
+
+# Handle --with-match-limit-depth=N
+# Recognize old synonym --with-match-limit-recursion
+#
+# Note: In config.h, the default is to define MATCH_LIMIT_DEPTH symbolically as
+# MATCH_LIMIT, which in turn is defined to be some numeric value (e.g.
+# 10000000). MATCH_LIMIT_DEPTH can otherwise be set to some different numeric
+# value (or even the same numeric value as MATCH_LIMIT, though no longer
+# defined in terms of the latter).
+#
+
+# Check whether --with-match-limit-depth was given.
+if test ${with_match_limit_depth+y}
+then :
+ withval=$with_match_limit_depth;
+else $as_nop
+ with_match_limit_depth=MATCH_LIMIT
+fi
+
+
+
+# Check whether --with-match-limit-recursion was given.
+if test ${with_match_limit_recursion+y}
+then :
+ withval=$with_match_limit_recursion;
+else $as_nop
+ with_match_limit_recursion=UNSET
+fi
+
+
+# Handle --enable-valgrind
+# Check whether --enable-valgrind was given.
+if test ${enable_valgrind+y}
+then :
+ enableval=$enable_valgrind;
+else $as_nop
+ enable_valgrind=no
+fi
+
+
+# Enable code coverage reports using gcov
+# Check whether --enable-coverage was given.
+if test ${enable_coverage+y}
+then :
+ enableval=$enable_coverage;
+else $as_nop
+ enable_coverage=no
+fi
+
+
+# Handle --enable-fuzz-support
+# Check whether --enable-fuzz_support was given.
+if test ${enable_fuzz_support+y}
+then :
+ enableval=$enable_fuzz_support;
+else $as_nop
+ enable_fuzz_support=no
+fi
+
+
+# Handle --enable-diff-fuzz-support
+# Check whether --enable-diff_fuzz_support was given.
+if test ${enable_diff_fuzz_support+y}
+then :
+ enableval=$enable_diff_fuzz_support;
+else $as_nop
+ enable_diff_fuzz_support=no
+fi
+
+
+# Handle --disable-stack-for-recursion
+# This option became obsolete at release 10.30.
+# Check whether --enable-stack-for-recursion was given.
+if test ${enable_stack_for_recursion+y}
+then :
+ enableval=$enable_stack_for_recursion;
+else $as_nop
+ enable_stack_for_recursion=yes
+fi
+
+
+# Original code
+# AC_ARG_ENABLE(stack-for-recursion,
+# AS_HELP_STRING([--disable-stack-for-recursion],
+# [don't use stack recursion when matching]),
+# , enable_stack_for_recursion=yes)
+
+# Handle --disable-percent_zt (set as "auto" by default)
+# Check whether --enable-percent-zt was given.
+if test ${enable_percent_zt+y}
+then :
+ enableval=$enable_percent_zt;
+else $as_nop
+ enable_percent_zt=auto
+fi
+
+
+# Handle --enable-Werror/errwarn
+# Check whether --enable-Werror was given.
+if test ${enable_Werror+y}
+then :
+ enableval=$enable_Werror;
+else $as_nop
+ enable_Werror=no
+fi
+
+# Check whether --enable-errwarn was given.
+if test ${enable_errwarn+y}
+then :
+ enableval=$enable_errwarn;
+else $as_nop
+ enable_errwarn=no
+fi
+
+
+# Set the default value for pcre2-8
+if test "x$enable_pcre2_8" = "xunset"
+then
+ enable_pcre2_8=yes
+fi
+
+# Set the default value for pcre2-16
+if test "x$enable_pcre2_16" = "xunset"
+then
+ enable_pcre2_16=no
+fi
+
+# Set the default value for pcre2-32
+if test "x$enable_pcre2_32" = "xunset"
+then
+ enable_pcre2_32=no
+fi
+
+# Make sure at least one library is selected
+if test "x$enable_pcre2_8$enable_pcre2_16$enable_pcre2_32" = "xnonono"
+then
+ as_fn_error $? "At least one of the 8, 16 or 32 bit libraries must be enabled" "$LINENO" 5
+fi
+
+# Unicode is enabled by default.
+if test "x$enable_unicode" = "xunset"
+then
+ enable_unicode=yes
+fi
+
+# Convert the newline identifier into the appropriate integer value. These must
+# agree with the PCRE2_NEWLINE_xxx values in pcre2.h.
+
+case "$enable_newline" in
+ cr) ac_pcre2_newline_value=1 ;;
+ lf) ac_pcre2_newline_value=2 ;;
+ crlf) ac_pcre2_newline_value=3 ;;
+ any) ac_pcre2_newline_value=4 ;;
+ anycrlf) ac_pcre2_newline_value=5 ;;
+ nul) ac_pcre2_newline_value=6 ;;
+ *)
+ as_fn_error $? "invalid argument \"$enable_newline\" to --enable-newline option" "$LINENO" 5
+ ;;
+esac
+
+# --enable-ebcdic-nl25 and --enable-ebcdic-ignoring-compiler imply --enable-ebcdic
+if test "x$enable_ebcdic_nl25" = "xyes" -o "x$enable_ebcdic_ignoring_compiler" = "xyes"; then
+ enable_ebcdic=yes
+fi
+
+# Make sure that if enable_ebcdic is set (without
+# enable_ebcdic_ignoring_compiler), rebuild_chartables is also enabled.
+# Also check that UTF support is not requested, because PCRE2 cannot handle
+# EBCDIC and UTF in the same build. To do so it would need to use different
+# character constants depending on the mode.
+# Also, EBCDIC cannot be used with 16-bit and 32-bit libraries.
+if test "x$enable_ebcdic" = "xyes"; then
+ if test "x$enable_ebcdic_ignoring_compiler" != "xyes"; then
+ enable_rebuild_chartables=yes
+ fi
+ if test "x$enable_unicode" = "xyes"; then
+ as_fn_error $? "support for EBCDIC and Unicode cannot be enabled at the same time" "$LINENO" 5
+ fi
+ if test "x$enable_pcre2_16" = "xyes" -o "x$enable_pcre2_32" = "xyes"; then
+ as_fn_error $? "EBCDIC support is available only for the 8-bit library" "$LINENO" 5
+ fi
+fi
+
+# Check argument to --with-link-size
+case "$with_link_size" in
+ 2|3|4) ;;
+ *)
+ as_fn_error $? "invalid argument \"$with_link_size\" to --with-link-size option" "$LINENO" 5
+ ;;
+esac
+
+
+
+# Checks for header files.
+ac_fn_c_check_header_compile "$LINENO" "assert.h" "ac_cv_header_assert_h" "$ac_includes_default"
+if test "x$ac_cv_header_assert_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_ASSERT_H 1" >>confdefs.h
+
+fi
+ac_fn_c_check_header_compile "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default"
+if test "x$ac_cv_header_limits_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIMITS_H 1" >>confdefs.h
+
+fi
+ac_fn_c_check_header_compile "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_types_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_TYPES_H 1" >>confdefs.h
+
+fi
+ac_fn_c_check_header_compile "$LINENO" "sys/stat.h" "ac_cv_header_sys_stat_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_stat_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_STAT_H 1" >>confdefs.h
+
+fi
+ac_fn_c_check_header_compile "$LINENO" "dirent.h" "ac_cv_header_dirent_h" "$ac_includes_default"
+if test "x$ac_cv_header_dirent_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_DIRENT_H 1" >>confdefs.h
+
+fi
+
+ for ac_header in windows.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default"
+if test "x$ac_cv_header_windows_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_WINDOWS_H 1" >>confdefs.h
+ HAVE_WINDOWS_H=1
+fi
+
+done
+ for ac_header in sys/wait.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "sys/wait.h" "ac_cv_header_sys_wait_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_wait_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_SYS_WAIT_H 1" >>confdefs.h
+ HAVE_SYS_WAIT_H=1
+fi
+
+done
+
+# Conditional compilation
+ if test "x$enable_pcre2_8" = "xyes"; then
+ WITH_PCRE2_8_TRUE=
+ WITH_PCRE2_8_FALSE='#'
+else
+ WITH_PCRE2_8_TRUE='#'
+ WITH_PCRE2_8_FALSE=
+fi
+
+ if test "x$enable_pcre2_16" = "xyes"; then
+ WITH_PCRE2_16_TRUE=
+ WITH_PCRE2_16_FALSE='#'
+else
+ WITH_PCRE2_16_TRUE='#'
+ WITH_PCRE2_16_FALSE=
+fi
+
+ if test "x$enable_pcre2_32" = "xyes"; then
+ WITH_PCRE2_32_TRUE=
+ WITH_PCRE2_32_FALSE='#'
+else
+ WITH_PCRE2_32_TRUE='#'
+ WITH_PCRE2_32_FALSE=
+fi
+
+ if test "x$enable_rebuild_chartables" = "xyes"; then
+ WITH_REBUILD_CHARTABLES_TRUE=
+ WITH_REBUILD_CHARTABLES_FALSE='#'
+else
+ WITH_REBUILD_CHARTABLES_TRUE='#'
+ WITH_REBUILD_CHARTABLES_FALSE=
+fi
+
+ if test "x$enable_jit" = "xyes"; then
+ WITH_JIT_TRUE=
+ WITH_JIT_FALSE='#'
+else
+ WITH_JIT_TRUE='#'
+ WITH_JIT_FALSE=
+fi
+
+ if test "x$enable_unicode" = "xyes"; then
+ WITH_UNICODE_TRUE=
+ WITH_UNICODE_FALSE='#'
+else
+ WITH_UNICODE_TRUE='#'
+ WITH_UNICODE_FALSE=
+fi
+
+ if test "x$enable_ebcdic" = "xyes"; then
+ WITH_EBCDIC_TRUE=
+ WITH_EBCDIC_FALSE='#'
+else
+ WITH_EBCDIC_TRUE='#'
+ WITH_EBCDIC_FALSE=
+fi
+
+ if test "x$enable_ebcdic_nl25" = "xyes"; then
+ WITH_EBCDIC_NL25_TRUE=
+ WITH_EBCDIC_NL25_FALSE='#'
+else
+ WITH_EBCDIC_NL25_TRUE='#'
+ WITH_EBCDIC_NL25_FALSE=
+fi
+
+ if test "x$enable_valgrind" = "xyes"; then
+ WITH_VALGRIND_TRUE=
+ WITH_VALGRIND_FALSE='#'
+else
+ WITH_VALGRIND_TRUE='#'
+ WITH_VALGRIND_FALSE=
+fi
+
+ if test "x$enable_fuzz_support" = "xyes"; then
+ WITH_FUZZ_SUPPORT_TRUE=
+ WITH_FUZZ_SUPPORT_FALSE='#'
+else
+ WITH_FUZZ_SUPPORT_TRUE='#'
+ WITH_FUZZ_SUPPORT_FALSE=
+fi
+
+ if test "x$enable_diff_fuzz_support" = "xyes"; then
+ WITH_DIFF_FUZZ_SUPPORT_TRUE=
+ WITH_DIFF_FUZZ_SUPPORT_FALSE='#'
+else
+ WITH_DIFF_FUZZ_SUPPORT_TRUE='#'
+ WITH_DIFF_FUZZ_SUPPORT_FALSE=
+fi
+
+
+if test "$enable_fuzz_support" = "yes" -a "$enable_pcre2_8" = "no"; then
+ echo "** ERROR: Fuzzer support requires the 8-bit library"
+ exit 1
+fi
+
+if test "$enable_diff_fuzz_support" = "yes"; then
+ if test "$enable_fuzz_support" = "no"; then
+ echo "** ERROR: Differential fuzzing support requires fuzzing support"
+ exit 1
+ fi
+ if test "$enable_jit" = "no"; then
+ echo "** ERROR: Differential fuzzing support requires Just-in-Time compilation support"
+ exit 1
+ fi
+
+printf "%s\n" "#define SUPPORT_DIFF_FUZZ /**/" >>confdefs.h
+
+fi
+
+# Checks for typedefs, structures, and compiler characteristics.
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
+printf %s "checking for an ANSI C-conforming const... " >&6; }
+if test ${ac_cv_c_const+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this sort of thing. */
+ typedef int charset[2];
+ const charset cs = { 0, 0 };
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *pcpcc;
+ char **ppc;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* IBM XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ pcpcc = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++pcpcc;
+ ppc = (char**) pcpcc;
+ pcpcc = (char const *const *) ppc;
+ { /* SCO 3.2v4 cc rejects this sort of thing. */
+ char tx;
+ char *t = &tx;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ if (s) return 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* IBM XL C 1.02.0.0 rejects this sort of thing, saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; } bx;
+ struct s *b = &bx; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ if (!foo) return 0;
+ }
+ return !cs[0] && !zero.x;
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_c_const=yes
+else $as_nop
+ ac_cv_c_const=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5
+printf "%s\n" "$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+printf "%s\n" "#define const /**/" >>confdefs.h
+
+fi
+
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes
+then :
+
+else $as_nop
+
+printf "%s\n" "#define size_t unsigned int" >>confdefs.h
+
+fi
+
+
+# Checks for library functions.
+
+ac_fn_c_check_func "$LINENO" "memfd_create" "ac_cv_func_memfd_create"
+if test "x$ac_cv_func_memfd_create" = xyes
+then :
+ printf "%s\n" "#define HAVE_MEMFD_CREATE 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "mkostemp" "ac_cv_func_mkostemp"
+if test "x$ac_cv_func_mkostemp" = xyes
+then :
+ printf "%s\n" "#define HAVE_MKOSTEMP 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "secure_getenv" "ac_cv_func_secure_getenv"
+if test "x$ac_cv_func_secure_getenv" = xyes
+then :
+ printf "%s\n" "#define HAVE_SECURE_GETENV 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "setrlimit" "ac_cv_func_setrlimit"
+if test "x$ac_cv_func_setrlimit" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETRLIMIT 1" >>confdefs.h
+
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for realpath" >&5
+printf %s "checking for realpath... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include
+#include
+
+int
+main (void)
+{
+
+char buffer[PATH_MAX];
+realpath(".", buffer);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+printf "%s\n" "#define HAVE_REALPATH 1" >>confdefs.h
+
+
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+
+# Check for the availability of libz (aka zlib)
+
+ for ac_header in zlib.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_zlib_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_ZLIB_H 1" >>confdefs.h
+ HAVE_ZLIB_H=1
+fi
+
+done
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gzopen in -lz" >&5
+printf %s "checking for gzopen in -lz... " >&6; }
+if test ${ac_cv_lib_z_gzopen+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lz $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char gzopen ();
+int
+main (void)
+{
+return gzopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_z_gzopen=yes
+else $as_nop
+ ac_cv_lib_z_gzopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzopen" >&5
+printf "%s\n" "$ac_cv_lib_z_gzopen" >&6; }
+if test "x$ac_cv_lib_z_gzopen" = xyes
+then :
+ HAVE_LIBZ=1
+fi
+
+
+# Check for the availability of libbz2. Originally we just used AC_CHECK_LIB,
+# as for libz. However, this had the following problem, diagnosed and fixed by
+# a user:
+#
+# - libbz2 uses the Pascal calling convention (WINAPI) for the functions
+# under Win32.
+# - The standard autoconf AC_CHECK_LIB fails to include "bzlib.h",
+# therefore missing the function definition.
+# - The compiler thus generates a "C" signature for the test function.
+# - The linker fails to find the "C" function.
+# - PCRE2 fails to configure if asked to do so against libbz2.
+#
+# Solution:
+#
+# - Replace the AC_CHECK_LIB test with a custom test.
+
+ for ac_header in bzlib.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "bzlib.h" "ac_cv_header_bzlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_bzlib_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_BZLIB_H 1" >>confdefs.h
+ HAVE_BZLIB_H=1
+fi
+
+done
+# Original test
+# AC_CHECK_LIB([bz2], [BZ2_bzopen], [HAVE_LIBBZ2=1])
+#
+# Custom test follows
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libbz2" >&5
+printf %s "checking for libbz2... " >&6; }
+OLD_LIBS="$LIBS"
+LIBS="$LIBS -lbz2"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#ifdef HAVE_BZLIB_H
+#include
+#endif
+int
+main (void)
+{
+return (int)BZ2_bzopen("conftest", "rb");
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; };HAVE_LIBBZ2=1; break;
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS="$OLD_LIBS"
+
+# Check for the availability of libreadline
+
+if test "$enable_pcre2test_libreadline" = "yes"; then
+ for ac_header in readline/readline.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "readline/readline.h" "ac_cv_header_readline_readline_h" "$ac_includes_default"
+if test "x$ac_cv_header_readline_readline_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_READLINE_READLINE_H 1" >>confdefs.h
+ HAVE_READLINE_H=1
+fi
+
+done
+ for ac_header in readline/history.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "readline/history.h" "ac_cv_header_readline_history_h" "$ac_includes_default"
+if test "x$ac_cv_header_readline_history_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_READLINE_HISTORY_H 1" >>confdefs.h
+ HAVE_HISTORY_H=1
+fi
+
+done
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5
+printf %s "checking for readline in -lreadline... " >&6; }
+if test ${ac_cv_lib_readline_readline+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lreadline $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char readline ();
+int
+main (void)
+{
+return readline ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_readline_readline=yes
+else $as_nop
+ ac_cv_lib_readline_readline=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5
+printf "%s\n" "$ac_cv_lib_readline_readline" >&6; }
+if test "x$ac_cv_lib_readline_readline" = xyes
+then :
+ LIBREADLINE="-lreadline"
+else $as_nop
+ unset ac_cv_lib_readline_readline;
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5
+printf %s "checking for readline in -lreadline... " >&6; }
+if test ${ac_cv_lib_readline_readline+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lreadline -ltinfo $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char readline ();
+int
+main (void)
+{
+return readline ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_readline_readline=yes
+else $as_nop
+ ac_cv_lib_readline_readline=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5
+printf "%s\n" "$ac_cv_lib_readline_readline" >&6; }
+if test "x$ac_cv_lib_readline_readline" = xyes
+then :
+ LIBREADLINE="-ltinfo"
+else $as_nop
+ unset ac_cv_lib_readline_readline;
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5
+printf %s "checking for readline in -lreadline... " >&6; }
+if test ${ac_cv_lib_readline_readline+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lreadline -lcurses $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char readline ();
+int
+main (void)
+{
+return readline ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_readline_readline=yes
+else $as_nop
+ ac_cv_lib_readline_readline=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5
+printf "%s\n" "$ac_cv_lib_readline_readline" >&6; }
+if test "x$ac_cv_lib_readline_readline" = xyes
+then :
+ LIBREADLINE="-lcurses"
+else $as_nop
+ unset ac_cv_lib_readline_readline;
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5
+printf %s "checking for readline in -lreadline... " >&6; }
+if test ${ac_cv_lib_readline_readline+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lreadline -lncurses $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char readline ();
+int
+main (void)
+{
+return readline ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_readline_readline=yes
+else $as_nop
+ ac_cv_lib_readline_readline=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5
+printf "%s\n" "$ac_cv_lib_readline_readline" >&6; }
+if test "x$ac_cv_lib_readline_readline" = xyes
+then :
+ LIBREADLINE="-lncurses"
+else $as_nop
+ unset ac_cv_lib_readline_readline;
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5
+printf %s "checking for readline in -lreadline... " >&6; }
+if test ${ac_cv_lib_readline_readline+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lreadline -lncursesw $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char readline ();
+int
+main (void)
+{
+return readline ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_readline_readline=yes
+else $as_nop
+ ac_cv_lib_readline_readline=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5
+printf "%s\n" "$ac_cv_lib_readline_readline" >&6; }
+if test "x$ac_cv_lib_readline_readline" = xyes
+then :
+ LIBREADLINE="-lncursesw"
+else $as_nop
+ unset ac_cv_lib_readline_readline;
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5
+printf %s "checking for readline in -lreadline... " >&6; }
+if test ${ac_cv_lib_readline_readline+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lreadline -ltermcap $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char readline ();
+int
+main (void)
+{
+return readline ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_readline_readline=yes
+else $as_nop
+ ac_cv_lib_readline_readline=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5
+printf "%s\n" "$ac_cv_lib_readline_readline" >&6; }
+if test "x$ac_cv_lib_readline_readline" = xyes
+then :
+ LIBREADLINE="-ltermcap"
+else $as_nop
+ LIBREADLINE=""
+fi
+
+fi
+
+fi
+
+fi
+
+fi
+
+fi
+
+
+ if test -n "$LIBREADLINE"; then
+ if test "$LIBREADLINE" != "-lreadline"; then
+ echo "-lreadline needs $LIBREADLINE"
+ LIBREADLINE="-lreadline $LIBREADLINE"
+ fi
+ fi
+fi
+
+# Check for the availability of libedit. Different distributions put its
+# headers in different places. Try to cover the most common ones.
+
+if test "$enable_pcre2test_libedit" = "yes"; then
+ for ac_header in editline/readline.h edit/readline/readline.h readline.h
+do :
+ as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"
+then :
+ cat >>confdefs.h <<_ACEOF
+#define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+ HAVE_LIBEDIT_HEADER=1
+ break
+
+fi
+
+done
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for readline in -ledit" >&5
+printf %s "checking for readline in -ledit... " >&6; }
+if test ${ac_cv_lib_edit_readline+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ledit $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char readline ();
+int
+main (void)
+{
+return readline ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_edit_readline=yes
+else $as_nop
+ ac_cv_lib_edit_readline=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_edit_readline" >&5
+printf "%s\n" "$ac_cv_lib_edit_readline" >&6; }
+if test "x$ac_cv_lib_edit_readline" = xyes
+then :
+ LIBEDIT="-ledit"
+fi
+
+fi
+
+# Set up shared/static library flags
+
+PCRE2_STATIC_CFLAG=""
+if test "x$enable_shared" = "xno" ; then
+
+printf "%s\n" "#define PCRE2_STATIC 1" >>confdefs.h
+
+ PCRE2_STATIC_CFLAG="-DPCRE2_STATIC"
+fi
+
+
+PCRE2POSIX_CFLAG=""
+if test "x$enable_shared" = "xyes" ; then
+
+printf "%s\n" "#define PCRE2POSIX_SHARED 1" >>confdefs.h
+
+ PCRE2POSIX_CFLAG="-DPCRE2POSIX_SHARED"
+fi
+
+
+# Here is where PCRE2-specific defines are handled
+
+if test "$enable_pcre2_8" = "yes"; then
+
+printf "%s\n" "#define SUPPORT_PCRE2_8 /**/" >>confdefs.h
+
+fi
+
+if test "$enable_pcre2_16" = "yes"; then
+
+printf "%s\n" "#define SUPPORT_PCRE2_16 /**/" >>confdefs.h
+
+fi
+
+if test "$enable_pcre2_32" = "yes"; then
+
+printf "%s\n" "#define SUPPORT_PCRE2_32 /**/" >>confdefs.h
+
+fi
+
+if test "$enable_debug" = "yes"; then
+
+printf "%s\n" "#define PCRE2_DEBUG /**/" >>confdefs.h
+
+fi
+
+if test "$enable_percent_zt" = "no"; then
+
+printf "%s\n" "#define DISABLE_PERCENT_ZT /**/" >>confdefs.h
+
+else
+ enable_percent_zt=auto
+fi
+
+# Unless running under Windows, JIT support requires pthreads.
+
+if test "$enable_jit" = "yes"; then
+ if test "$HAVE_WINDOWS_H" != "1"; then
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+printf %s "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test ${ac_cv_prog_CPP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ # Double quotes because $CC needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+else $as_nop
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ # Broken: success on invalid input.
+continue
+else $as_nop
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok
+then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+printf "%s\n" "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+else $as_nop
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ # Broken: success on invalid input.
+continue
+else $as_nop
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok
+then :
+
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ax_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on Tru64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
+ ax_pthread_save_CC="$CC"
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ ax_pthread_save_LIBS="$LIBS"
+ if test "x$PTHREAD_CC" != "x"
+then :
+ CC="$PTHREAD_CC"
+fi
+ if test "x$PTHREAD_CXX" != "x"
+then :
+ CXX="$PTHREAD_CXX"
+fi
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS" >&5
+printf %s "checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char pthread_join ();
+int
+main (void)
+{
+return pthread_join ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_pthread_ok=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5
+printf "%s\n" "$ax_pthread_ok" >&6; }
+ if test "x$ax_pthread_ok" = "xno"; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ CC="$ax_pthread_save_CC"
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ LIBS="$ax_pthread_save_LIBS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items with a "," contain both
+# C compiler flags (before ",") and linker flags (after ","). Other items
+# starting with a "-" are C compiler flags, and remaining items are
+# library names, except for "none" which indicates that we try without
+# any flags at all, and "pthread-config" which is a program returning
+# the flags for the Pth emulation library.
+
+ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
+# (Note: HP C rejects this with "bad form for `-t' option")
+# -pthreads: Solaris/gcc (Note: HP C also rejects)
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads and
+# -D_REENTRANT too), HP C (must be checked before -lpthread, which
+# is present but should not be used directly; and before -mthreads,
+# because the compiler interprets this as "-mt" + "-hreads")
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case $host_os in
+
+ freebsd*)
+
+ # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+ # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+
+ ax_pthread_flags="-kthread lthread $ax_pthread_flags"
+ ;;
+
+ hpux*)
+
+ # From the cc(1) man page: "[-mt] Sets various -D flags to enable
+ # multi-threading and also sets -lpthread."
+
+ ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
+ ;;
+
+ openedition*)
+
+ # IBM z/OS requires a feature-test macro to be defined in order to
+ # enable POSIX threads at all, so give the user a hint if this is
+ # not set. (We don't define these ourselves, as they can affect
+ # other portions of the system API in unpredictable ways.)
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
+ AX_PTHREAD_ZOS_MISSING
+# endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "AX_PTHREAD_ZOS_MISSING" >/dev/null 2>&1
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&5
+printf "%s\n" "$as_me: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&2;}
+fi
+rm -rf conftest*
+
+ ;;
+
+ solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (N.B.: The stubs are missing
+ # pthread_cleanup_push, or rather a function called by this macro,
+ # so we could check for that, but who knows whether they'll stub
+ # that too in a future libc.) So we'll check first for the
+ # standard Solaris way of linking pthreads (-mt -lpthread).
+
+ ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
+ ;;
+esac
+
+# Are we compiling with Clang?
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC is Clang" >&5
+printf %s "checking whether $CC is Clang... " >&6; }
+if test ${ax_cv_PTHREAD_CLANG+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ax_cv_PTHREAD_CLANG=no
+ # Note that Autoconf sets GCC=yes for Clang as well as GCC
+ if test "x$GCC" = "xyes"; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
+# if defined(__clang__) && defined(__llvm__)
+ AX_PTHREAD_CC_IS_CLANG
+# endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "AX_PTHREAD_CC_IS_CLANG" >/dev/null 2>&1
+then :
+ ax_cv_PTHREAD_CLANG=yes
+fi
+rm -rf conftest*
+
+ fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG" >&5
+printf "%s\n" "$ax_cv_PTHREAD_CLANG" >&6; }
+ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
+
+
+# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
+
+# Note that for GCC and Clang -pthread generally implies -lpthread,
+# except when -nostdlib is passed.
+# This is problematic using libtool to build C++ shared libraries with pthread:
+# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
+# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
+# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
+# To solve this, first try -pthread together with -lpthread for GCC
+
+if test "x$GCC" = "xyes"
+then :
+ ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"
+fi
+
+# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
+
+if test "x$ax_pthread_clang" = "xyes"
+then :
+ ax_pthread_flags="-pthread,-lpthread -pthread"
+fi
+
+
+# The presence of a feature test macro requesting re-entrant function
+# definitions is, on some systems, a strong hint that pthreads support is
+# correctly enabled
+
+case $host_os in
+ darwin* | hpux* | linux* | osf* | solaris*)
+ ax_pthread_check_macro="_REENTRANT"
+ ;;
+
+ aix*)
+ ax_pthread_check_macro="_THREAD_SAFE"
+ ;;
+
+ *)
+ ax_pthread_check_macro="--"
+ ;;
+esac
+if test "x$ax_pthread_check_macro" = "x--"
+then :
+ ax_pthread_check_cond=0
+else $as_nop
+ ax_pthread_check_cond="!defined($ax_pthread_check_macro)"
+fi
+
+
+if test "x$ax_pthread_ok" = "xno"; then
+for ax_pthread_try_flag in $ax_pthread_flags; do
+
+ case $ax_pthread_try_flag in
+ none)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5
+printf %s "checking whether pthreads work without any flags... " >&6; }
+ ;;
+
+ *,*)
+ PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
+ PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with \"$PTHREAD_CFLAGS\" and \"$PTHREAD_LIBS\"" >&5
+printf %s "checking whether pthreads work with \"$PTHREAD_CFLAGS\" and \"$PTHREAD_LIBS\"... " >&6; }
+ ;;
+
+ -*)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $ax_pthread_try_flag" >&5
+printf %s "checking whether pthreads work with $ax_pthread_try_flag... " >&6; }
+ PTHREAD_CFLAGS="$ax_pthread_try_flag"
+ ;;
+
+ pthread-config)
+ # Extract the first word of "pthread-config", so it can be a program name with args.
+set dummy pthread-config; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ax_pthread_config+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ax_pthread_config"; then
+ ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ax_pthread_config="yes"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no"
+fi
+fi
+ax_pthread_config=$ac_cv_prog_ax_pthread_config
+if test -n "$ax_pthread_config"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5
+printf "%s\n" "$ax_pthread_config" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ if test "x$ax_pthread_config" = "xno"
+then :
+ continue
+fi
+ PTHREAD_CFLAGS="`pthread-config --cflags`"
+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+ ;;
+
+ *)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$ax_pthread_try_flag" >&5
+printf %s "checking for the pthreads library -l$ax_pthread_try_flag... " >&6; }
+ PTHREAD_LIBS="-l$ax_pthread_try_flag"
+ ;;
+ esac
+
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ ax_pthread_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+# if $ax_pthread_check_cond
+# error "$ax_pthread_check_macro must be defined"
+# endif
+ static void *some_global = NULL;
+ static void routine(void *a)
+ {
+ /* To avoid any unused-parameter or
+ unused-but-set-parameter warning. */
+ some_global = a;
+ }
+ static void *start_routine(void *a) { return a; }
+int
+main (void)
+{
+pthread_t th; pthread_attr_t attr;
+ pthread_create(&th, 0, start_routine, 0);
+ pthread_join(th, 0);
+ pthread_attr_init(&attr);
+ pthread_cleanup_push(routine, 0);
+ pthread_cleanup_pop(0) /* ; */
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_pthread_ok=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ LIBS="$ax_pthread_save_LIBS"
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5
+printf "%s\n" "$ax_pthread_ok" >&6; }
+ if test "x$ax_pthread_ok" = "xyes"
+then :
+ break
+fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+
+# Clang needs special handling, because older versions handle the -pthread
+# option in a rather... idiosyncratic way
+
+if test "x$ax_pthread_clang" = "xyes"; then
+
+ # Clang takes -pthread; it has never supported any other flag
+
+ # (Note 1: This will need to be revisited if a system that Clang
+ # supports has POSIX threads in a separate library. This tends not
+ # to be the way of modern systems, but it's conceivable.)
+
+ # (Note 2: On some systems, notably Darwin, -pthread is not needed
+ # to get POSIX threads support; the API is always present and
+ # active. We could reasonably leave PTHREAD_CFLAGS empty. But
+ # -pthread does define _REENTRANT, and while the Darwin headers
+ # ignore this macro, third-party headers might not.)
+
+ # However, older versions of Clang make a point of warning the user
+ # that, in an invocation where only linking and no compilation is
+ # taking place, the -pthread option has no effect ("argument unused
+ # during compilation"). They expect -pthread to be passed in only
+ # when source code is being compiled.
+ #
+ # Problem is, this is at odds with the way Automake and most other
+ # C build frameworks function, which is that the same flags used in
+ # compilation (CFLAGS) are also used in linking. Many systems
+ # supported by AX_PTHREAD require exactly this for POSIX threads
+ # support, and in fact it is often not straightforward to specify a
+ # flag that is used only in the compilation phase and not in
+ # linking. Such a scenario is extremely rare in practice.
+ #
+ # Even though use of the -pthread flag in linking would only print
+ # a warning, this can be a nuisance for well-run software projects
+ # that build with -Werror. So if the active version of Clang has
+ # this misfeature, we search for an option to squash it.
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread" >&5
+printf %s "checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread... " >&6; }
+if test ${ax_cv_PTHREAD_CLANG_NO_WARN_FLAG+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
+ # Create an alternate version of $ac_link that compiles and
+ # links in two steps (.c -> .o, .o -> exe) instead of one
+ # (.c -> exe), because the warning occurs only in the second
+ # step
+ ax_pthread_save_ac_link="$ac_link"
+ ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
+ ax_pthread_link_step=`printf "%s\n" "$ac_link" | sed "$ax_pthread_sed"`
+ ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
+ if test "x$ax_pthread_try" = "xunknown"
+then :
+ break
+fi
+ CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
+ ac_link="$ax_pthread_save_ac_link"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int main(void){return 0;}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_link="$ax_pthread_2step_ac_link"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int main(void){return 0;}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+ ac_link="$ax_pthread_save_ac_link"
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ if test "x$ax_pthread_try" = "x"
+then :
+ ax_pthread_try=no
+fi
+ ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&5
+printf "%s\n" "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&6; }
+
+ case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
+ no | unknown) ;;
+ *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
+ esac
+
+fi # $ax_pthread_clang = yes
+
+
+
+# Various other checks:
+if test "x$ax_pthread_ok" = "xyes"; then
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ ax_pthread_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+
+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5
+printf %s "checking for joinable pthread attribute... " >&6; }
+if test ${ax_cv_PTHREAD_JOINABLE_ATTR+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ax_cv_PTHREAD_JOINABLE_ATTR=unknown
+ for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+int
+main (void)
+{
+int attr = $ax_pthread_attr; return attr /* ; */
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+ done
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_JOINABLE_ATTR" >&5
+printf "%s\n" "$ax_cv_PTHREAD_JOINABLE_ATTR" >&6; }
+ if test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
+ test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
+ test "x$ax_pthread_joinable_attr_defined" != "xyes"
+then :
+
+printf "%s\n" "#define PTHREAD_CREATE_JOINABLE $ax_cv_PTHREAD_JOINABLE_ATTR" >>confdefs.h
+
+ ax_pthread_joinable_attr_defined=yes
+
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether more special flags are required for pthreads" >&5
+printf %s "checking whether more special flags are required for pthreads... " >&6; }
+if test ${ax_cv_PTHREAD_SPECIAL_FLAGS+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ax_cv_PTHREAD_SPECIAL_FLAGS=no
+ case $host_os in
+ solaris*)
+ ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
+ ;;
+ esac
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_SPECIAL_FLAGS" >&5
+printf "%s\n" "$ax_cv_PTHREAD_SPECIAL_FLAGS" >&6; }
+ if test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
+ test "x$ax_pthread_special_flags_added" != "xyes"
+then :
+ PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
+ ax_pthread_special_flags_added=yes
+fi
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5
+printf %s "checking for PTHREAD_PRIO_INHERIT... " >&6; }
+if test ${ax_cv_PTHREAD_PRIO_INHERIT+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include
+int
+main (void)
+{
+int i = PTHREAD_PRIO_INHERIT;
+ return i;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ax_cv_PTHREAD_PRIO_INHERIT=yes
+else $as_nop
+ ax_cv_PTHREAD_PRIO_INHERIT=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5
+printf "%s\n" "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; }
+ if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
+ test "x$ax_pthread_prio_inherit_defined" != "xyes"
+then :
+
+printf "%s\n" "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h
+
+ ax_pthread_prio_inherit_defined=yes
+
+fi
+
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ LIBS="$ax_pthread_save_LIBS"
+
+ # More AIX lossage: compile with *_r variant
+ if test "x$GCC" != "xyes"; then
+ case $host_os in
+ aix*)
+ case "x/$CC" in #(
+ x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) :
+ #handle absolute path differently from PATH based program lookup
+ case "x$CC" in #(
+ x/*) :
+
+ if as_fn_executable_p ${CC}_r
+then :
+ PTHREAD_CC="${CC}_r"
+fi
+ if test "x${CXX}" != "x"
+then :
+ if as_fn_executable_p ${CXX}_r
+then :
+ PTHREAD_CXX="${CXX}_r"
+fi
+fi
+ ;; #(
+ *) :
+
+ for ac_prog in ${CC}_r
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_PTHREAD_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$PTHREAD_CC"; then
+ ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_PTHREAD_CC="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+PTHREAD_CC=$ac_cv_prog_PTHREAD_CC
+if test -n "$PTHREAD_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5
+printf "%s\n" "$PTHREAD_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$PTHREAD_CC" && break
+done
+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+
+ if test "x${CXX}" != "x"
+then :
+ for ac_prog in ${CXX}_r
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_PTHREAD_CXX+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$PTHREAD_CXX"; then
+ ac_cv_prog_PTHREAD_CXX="$PTHREAD_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_PTHREAD_CXX="$ac_prog"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+PTHREAD_CXX=$ac_cv_prog_PTHREAD_CXX
+if test -n "$PTHREAD_CXX"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CXX" >&5
+printf "%s\n" "$PTHREAD_CXX" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ test -n "$PTHREAD_CXX" && break
+done
+test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
+
+fi
+
+ ;;
+esac
+ ;; #(
+ *) :
+ ;;
+esac
+ ;;
+ esac
+ fi
+fi
+
+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
+
+
+
+
+
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test "x$ax_pthread_ok" = "xyes"; then
+
+printf "%s\n" "#define HAVE_PTHREAD 1" >>confdefs.h
+
+ :
+else
+ ax_pthread_ok=no
+ as_fn_error $? "JIT support requires pthreads" "$LINENO" 5
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ CC="$PTHREAD_CC"
+ CFLAGS="$PTHREAD_CFLAGS $CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ fi
+
+printf "%s\n" "#define SUPPORT_JIT /**/" >>confdefs.h
+
+else
+ enable_pcre2grep_jit="no"
+fi
+
+if test "$enable_jit_sealloc" = "yes"; then
+
+printf "%s\n" "#define SLJIT_PROT_EXECUTABLE_ALLOCATOR 1" >>confdefs.h
+
+fi
+
+if test "$enable_pcre2grep_jit" = "yes"; then
+
+printf "%s\n" "#define SUPPORT_PCRE2GREP_JIT /**/" >>confdefs.h
+
+fi
+
+if test "$enable_pcre2grep_callout" = "yes"; then
+ if test "$enable_pcre2grep_callout_fork" = "yes"; then
+ if test "$HAVE_WINDOWS_H" != "1"; then
+ if test "$HAVE_SYS_WAIT_H" != "1"; then
+ as_fn_error $? "Callout script support needs sys/wait.h." "$LINENO" 5
+ fi
+ fi
+
+printf "%s\n" "#define SUPPORT_PCRE2GREP_CALLOUT_FORK /**/" >>confdefs.h
+
+ fi
+
+printf "%s\n" "#define SUPPORT_PCRE2GREP_CALLOUT /**/" >>confdefs.h
+
+else
+ enable_pcre2grep_callout_fork="no"
+fi
+
+if test "$enable_unicode" = "yes"; then
+
+printf "%s\n" "#define SUPPORT_UNICODE /**/" >>confdefs.h
+
+fi
+
+if test "$enable_pcre2grep_libz" = "yes"; then
+
+printf "%s\n" "#define SUPPORT_LIBZ /**/" >>confdefs.h
+
+fi
+
+if test "$enable_pcre2grep_libbz2" = "yes"; then
+
+printf "%s\n" "#define SUPPORT_LIBBZ2 /**/" >>confdefs.h
+
+fi
+
+if test $with_pcre2grep_bufsize -lt 8192 ; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $with_pcre2grep_bufsize is too small for --with-pcre2grep-bufsize; using 8192" >&5
+printf "%s\n" "$as_me: WARNING: $with_pcre2grep_bufsize is too small for --with-pcre2grep-bufsize; using 8192" >&2;}
+ with_pcre2grep_bufsize="8192"
+else
+ if test $? -gt 1 ; then
+ as_fn_error $? "Bad value for --with-pcre2grep-bufsize" "$LINENO" 5
+ fi
+fi
+
+if test $with_pcre2grep_max_bufsize -lt $with_pcre2grep_bufsize ; then
+ with_pcre2grep_max_bufsize="$with_pcre2grep_bufsize"
+else
+ if test $? -gt 1 ; then
+ as_fn_error $? "Bad value for --with-pcre2grep-max-bufsize" "$LINENO" 5
+ fi
+fi
+
+
+printf "%s\n" "#define PCRE2GREP_BUFSIZE $with_pcre2grep_bufsize" >>confdefs.h
+
+
+
+printf "%s\n" "#define PCRE2GREP_MAX_BUFSIZE $with_pcre2grep_max_bufsize" >>confdefs.h
+
+
+if test "$enable_pcre2test_libedit" = "yes"; then
+
+printf "%s\n" "#define SUPPORT_LIBEDIT /**/" >>confdefs.h
+
+ LIBREADLINE="$LIBEDIT"
+elif test "$enable_pcre2test_libreadline" = "yes"; then
+
+printf "%s\n" "#define SUPPORT_LIBREADLINE /**/" >>confdefs.h
+
+fi
+
+
+printf "%s\n" "#define NEWLINE_DEFAULT $ac_pcre2_newline_value" >>confdefs.h
+
+
+if test "$enable_bsr_anycrlf" = "yes"; then
+
+printf "%s\n" "#define BSR_ANYCRLF /**/" >>confdefs.h
+
+fi
+
+if test "$enable_never_backslash_C" = "yes"; then
+
+printf "%s\n" "#define NEVER_BACKSLASH_C /**/" >>confdefs.h
+
+fi
+
+
+printf "%s\n" "#define LINK_SIZE $with_link_size" >>confdefs.h
+
+
+
+printf "%s\n" "#define MAX_VARLOOKBEHIND $with_max_varlookbehind" >>confdefs.h
+
+
+
+printf "%s\n" "#define PARENS_NEST_LIMIT $with_parens_nest_limit" >>confdefs.h
+
+
+
+printf "%s\n" "#define MATCH_LIMIT $with_match_limit" >>confdefs.h
+
+
+# --with-match-limit-recursion is an obsolete synonym for --with-match-limit-depth
+
+if test "$with_match_limit_recursion" != "UNSET"; then
+cat <>confdefs.h
+
+
+
+printf "%s\n" "#define HEAP_LIMIT $with_heap_limit" >>confdefs.h
+
+
+
+printf "%s\n" "#define MAX_NAME_SIZE 128" >>confdefs.h
+
+
+
+printf "%s\n" "#define MAX_NAME_COUNT 10000" >>confdefs.h
+
+
+
+
+
+
+if test "$enable_ebcdic" = "yes"; then
+
+printf "%s\n" "#define EBCDIC /**/" >>confdefs.h
+
+fi
+
+if test "$enable_ebcdic_nl25" = "yes"; then
+
+printf "%s\n" "#define EBCDIC_NL25 /**/" >>confdefs.h
+
+fi
+
+if test "$enable_ebcdic_ignoring_compiler" = "yes"; then
+
+printf "%s\n" "#define EBCDIC_IGNORING_COMPILER /**/" >>confdefs.h
+
+fi
+
+if test "$enable_valgrind" = "yes"; then
+
+printf "%s\n" "#define SUPPORT_VALGRIND /**/" >>confdefs.h
+
+fi
+
+# Platform specific issues
+NO_UNDEFINED=
+case $host_os in
+ cygwin* | mingw* )
+ if test X"$enable_shared" = Xyes; then
+ NO_UNDEFINED="-no-undefined"
+ fi
+ ;;
+esac
+
+# The extra LDFLAGS for each particular library. The libpcre2*_version values
+# are m4 variables, assigned above.
+
+EXTRA_LIBPCRE2_8_LDFLAGS="$EXTRA_LIBPCRE2_8_LDFLAGS \
+ $NO_UNDEFINED -version-info 16:0:16"
+
+EXTRA_LIBPCRE2_16_LDFLAGS="$EXTRA_LIBPCRE2_16_LDFLAGS \
+ $NO_UNDEFINED -version-info 16:0:16"
+
+EXTRA_LIBPCRE2_32_LDFLAGS="$EXTRA_LIBPCRE2_32_LDFLAGS \
+ $NO_UNDEFINED -version-info 16:0:16"
+
+EXTRA_LIBPCRE2_POSIX_LDFLAGS="$EXTRA_LIBPCRE2_POSIX_LDFLAGS \
+ $NO_UNDEFINED -version-info 3:8:0"
+
+# Append each library's version script, if the platform supports it.
+
+if test x$pcre2_check_vscript_flag != x ; then
+ EXTRA_LIBPCRE2_8_LDFLAGS="$EXTRA_LIBPCRE2_8_LDFLAGS \
+ -Wl,$pcre2_check_vscript_flag,\$(builddir)/src/libpcre2-8.sym"
+
+ EXTRA_LIBPCRE2_16_LDFLAGS="$EXTRA_LIBPCRE2_16_LDFLAGS \
+ -Wl,$pcre2_check_vscript_flag,\$(builddir)/src/libpcre2-16.sym"
+
+ EXTRA_LIBPCRE2_32_LDFLAGS="$EXTRA_LIBPCRE2_32_LDFLAGS \
+ -Wl,$pcre2_check_vscript_flag,\$(builddir)/src/libpcre2-32.sym"
+
+ EXTRA_LIBPCRE2_POSIX_LDFLAGS="$EXTRA_LIBPCRE2_POSIX_LDFLAGS \
+ -Wl,$pcre2_check_vscript_flag,\$(builddir)/src/libpcre2-posix.sym"
+fi
+
+
+
+
+
+
+# When we run 'make distcheck', use these arguments. Turning off compiler
+# optimization makes it run faster.
+DISTCHECK_CONFIGURE_FLAGS="CFLAGS='' CXXFLAGS='' --enable-pcre2-16 --enable-pcre2-32 --enable-jit"
+
+
+# Check that, if --enable-pcre2grep-libz or --enable-pcre2grep-libbz2 is
+# specified, the relevant library is available.
+
+if test "$enable_pcre2grep_libz" = "yes"; then
+ if test "$HAVE_ZLIB_H" != "1"; then
+ echo "** Cannot --enable-pcre2grep-libz because zlib.h was not found"
+ exit 1
+ fi
+ if test "$HAVE_LIBZ" != "1"; then
+ echo "** Cannot --enable-pcre2grep-libz because libz was not found"
+ exit 1
+ fi
+ LIBZ="-lz"
+fi
+
+
+if test "$enable_pcre2grep_libbz2" = "yes"; then
+ if test "$HAVE_BZLIB_H" != "1"; then
+ echo "** Cannot --enable-pcre2grep-libbz2 because bzlib.h was not found"
+ exit 1
+ fi
+ if test "$HAVE_LIBBZ2" != "1"; then
+ echo "** Cannot --enable-pcre2grep-libbz2 because libbz2 was not found"
+ exit 1
+ fi
+ LIBBZ2="-lbz2"
+fi
+
+
+# Similarly for --enable-pcre2test-readline
+
+if test "$enable_pcre2test_libedit" = "yes"; then
+ if test "$enable_pcre2test_libreadline" = "yes"; then
+ echo "** Cannot use both --enable-pcre2test-libedit and --enable-pcre2test-readline"
+ exit 1
+ fi
+ if test -z "$HAVE_LIBEDIT_HEADER"; then
+ echo "** Cannot --enable-pcre2test-libedit because neither editline/readline.h,"
+ echo "** edit/readline/readline.h nor a compatible header was found."
+ exit 1
+ fi
+ if test -z "$LIBEDIT"; then
+ echo "** Cannot --enable-pcre2test-libedit because libedit library was not found."
+ exit 1
+ fi
+fi
+
+if test "$enable_pcre2test_libreadline" = "yes"; then
+ if test "$HAVE_READLINE_H" != "1"; then
+ echo "** Cannot --enable-pcre2test-readline because readline/readline.h was not found."
+ exit 1
+ fi
+ if test "$HAVE_HISTORY_H" != "1"; then
+ echo "** Cannot --enable-pcre2test-readline because readline/history.h was not found."
+ exit 1
+ fi
+ if test -z "$LIBREADLINE"; then
+ echo "** Cannot --enable-pcre2test-readline because readline library was not found."
+ exit 1
+ fi
+fi
+
+# Handle valgrind support
+
+if test "$enable_valgrind" = "yes"; then
+
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_PKG_CONFIG+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+printf "%s\n" "$PKG_CONFIG" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+ ac_pt_PKG_CONFIG=$PKG_CONFIG
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_ac_pt_PKG_CONFIG+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ case $ac_pt_PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+printf "%s\n" "$ac_pt_PKG_CONFIG" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_pt_PKG_CONFIG" = x; then
+ PKG_CONFIG=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ PKG_CONFIG=$ac_pt_PKG_CONFIG
+ fi
+else
+ PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=0.9.0
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+printf %s "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ PKG_CONFIG=""
+ fi
+fi
+
+pkg_failed=no
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for valgrind" >&5
+printf %s "checking for valgrind... " >&6; }
+
+if test -n "$VALGRIND_CFLAGS"; then
+ pkg_cv_VALGRIND_CFLAGS="$VALGRIND_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"valgrind\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "valgrind") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_VALGRIND_CFLAGS=`$PKG_CONFIG --cflags "valgrind" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$VALGRIND_LIBS"; then
+ pkg_cv_VALGRIND_LIBS="$VALGRIND_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"valgrind\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "valgrind") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_VALGRIND_LIBS=`$PKG_CONFIG --libs "valgrind" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ VALGRIND_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "valgrind" 2>&1`
+ else
+ VALGRIND_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "valgrind" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$VALGRIND_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements (valgrind) were not met:
+
+$VALGRIND_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables VALGRIND_CFLAGS
+and VALGRIND_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables VALGRIND_CFLAGS
+and VALGRIND_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see .
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ VALGRIND_CFLAGS=$pkg_cv_VALGRIND_CFLAGS
+ VALGRIND_LIBS=$pkg_cv_VALGRIND_LIBS
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+
+fi
+fi
+
+# Handle code coverage reporting support
+if test "$enable_coverage" = "yes"; then
+ if test "x$GCC" != "xyes"; then
+ as_fn_error $? "Code coverage reports can only be generated when using GCC" "$LINENO" 5
+ fi
+
+ # ccache is incompatible with gcov
+ # Extract the first word of "shtool", so it can be a program name with args.
+set dummy shtool; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_SHTOOL+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ case $SHTOOL in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_SHTOOL="$SHTOOL" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_SHTOOL="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_SHTOOL" && ac_cv_path_SHTOOL="false"
+ ;;
+esac
+fi
+SHTOOL=$ac_cv_path_SHTOOL
+if test -n "$SHTOOL"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SHTOOL" >&5
+printf "%s\n" "$SHTOOL" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ case `$SHTOOL path $CC` in
+ *ccache*) cc_ccache=yes;;
+ *) cc_ccache=no;;
+ esac
+
+ if test "$cc_ccache" = "yes"; then
+ if test -z "$CCACHE_DISABLE" -o "$CCACHE_DISABLE" != "1"; then
+ as_fn_error $? "must export CCACHE_DISABLE=1 to disable ccache for code coverage" "$LINENO" 5
+ fi
+ fi
+
+
+ # Extract the first word of "lcov", so it can be a program name with args.
+set dummy lcov; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_LCOV+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ case $LCOV in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_LCOV="$LCOV" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_LCOV="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_LCOV" && ac_cv_path_LCOV="false"
+ ;;
+esac
+fi
+LCOV=$ac_cv_path_LCOV
+if test -n "$LCOV"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LCOV" >&5
+printf "%s\n" "$LCOV" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ if test "x$LCOV" = "xfalse"; then
+ as_fn_error $? "lcov not found" "$LINENO" 5
+ fi
+
+
+ # Extract the first word of "genhtml", so it can be a program name with args.
+set dummy genhtml; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_GENHTML+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ case $GENHTML in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_GENHTML="$GENHTML" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_GENHTML="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_GENHTML" && ac_cv_path_GENHTML="false"
+ ;;
+esac
+fi
+GENHTML=$ac_cv_path_GENHTML
+if test -n "$GENHTML"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GENHTML" >&5
+printf "%s\n" "$GENHTML" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+ if test "x$GENHTML" = "xfalse"; then
+ as_fn_error $? "genhtml not found" "$LINENO" 5
+ fi
+
+ # Set flags needed for gcov
+ GCOV_CFLAGS="-O0 -ggdb3 -fprofile-arcs -ftest-coverage"
+ GCOV_CXXFLAGS="-O0 -ggdb3 -fprofile-arcs -ftest-coverage"
+ GCOV_LIBS="-lgcov"
+
+
+
+fi # enable_coverage
+
+ if test "x$enable_coverage" = "xyes"; then
+ WITH_GCOV_TRUE=
+ WITH_GCOV_FALSE='#'
+else
+ WITH_GCOV_TRUE='#'
+ WITH_GCOV_FALSE=
+fi
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether Intel CET is enabled" >&5
+printf %s "checking whether Intel CET is enabled... " >&6; }
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+#ifndef __CET__
+# error CET is not enabled
+#endif
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ pcre2_cc_cv_intel_cet_enabled=yes
+else $as_nop
+ pcre2_cc_cv_intel_cet_enabled=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $pcre2_cc_cv_intel_cet_enabled" >&5
+printf "%s\n" "$pcre2_cc_cv_intel_cet_enabled" >&6; }
+if test "$pcre2_cc_cv_intel_cet_enabled" = yes; then
+ CET_CFLAGS="-mshstk"
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# LIB_POSTFIX is used by CMakeLists.txt for Windows debug builds.
+# Pass empty LIB_POSTFIX to *.pc files and pcre2-config here.
+
+
+# Set the extra "local: *" symbol section conditionally for Solaris (effectively).
+
+if test x$pcre2_check_vscript_flag != x && test x$pcre2_check_vscript_no_star = xno; then
+ PCRE2_EXTRA_LOCAL_SYMS=" local: *;"
+else
+ PCRE2_EXTRA_LOCAL_SYMS=""
+fi
+
+
+# Produce these files, in addition to config.h.
+
+ac_config_files="$ac_config_files Makefile libpcre2-8.pc libpcre2-16.pc libpcre2-32.pc libpcre2-posix.pc pcre2-config src/pcre2.h src/libpcre2-8.sym src/libpcre2-16.sym src/libpcre2-32.sym src/libpcre2-posix.sym"
+
+
+# Make the generated script files executable.
+ac_config_commands="$ac_config_commands script-chmod"
+
+
+# Make sure that pcre2_chartables.c is removed in case the method for
+# creating it was changed by reconfiguration.
+ac_config_commands="$ac_config_commands delete-old-chartables"
+
+
+# Handle --enable-Werror/errwarn. This must come last, so that we don't mess
+# with any of the library-detection tests (or similar).
+if test "X$enable_Werror" = Xyes; then
+ CFLAGS="$CFLAGS -Werror"
+fi
+if test "X$enable_errwarn" = Xyes; then
+ CFLAGS="$CFLAGS -errwarn=%all"
+fi
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
+printf %s "checking that generated files are newer than configure... " >&6; }
+ if test -n "$am_sleep_pid"; then
+ # Hide warnings about reused PIDs.
+ wait $am_sleep_pid 2>/dev/null
+ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: done" >&5
+printf "%s\n" "done" >&6; }
+ if test -n "$EXEEXT"; then
+ am__EXEEXT_TRUE=
+ am__EXEEXT_FALSE='#'
+else
+ am__EXEEXT_TRUE='#'
+ am__EXEEXT_FALSE=
+fi
+
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+ as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_PCRE2_8_TRUE}" && test -z "${WITH_PCRE2_8_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_PCRE2_8\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_PCRE2_16_TRUE}" && test -z "${WITH_PCRE2_16_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_PCRE2_16\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_PCRE2_32_TRUE}" && test -z "${WITH_PCRE2_32_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_PCRE2_32\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_REBUILD_CHARTABLES_TRUE}" && test -z "${WITH_REBUILD_CHARTABLES_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_REBUILD_CHARTABLES\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_JIT_TRUE}" && test -z "${WITH_JIT_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_JIT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_UNICODE_TRUE}" && test -z "${WITH_UNICODE_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_UNICODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_EBCDIC_TRUE}" && test -z "${WITH_EBCDIC_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_EBCDIC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_EBCDIC_NL25_TRUE}" && test -z "${WITH_EBCDIC_NL25_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_EBCDIC_NL25\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_VALGRIND_TRUE}" && test -z "${WITH_VALGRIND_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_VALGRIND\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_FUZZ_SUPPORT_TRUE}" && test -z "${WITH_FUZZ_SUPPORT_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_FUZZ_SUPPORT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_DIFF_FUZZ_SUPPORT_TRUE}" && test -z "${WITH_DIFF_FUZZ_SUPPORT_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_DIFF_FUZZ_SUPPORT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_GCOV_TRUE}" && test -z "${WITH_GCOV_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_GCOV\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else $as_nop
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
+as_nl='
+'
+export as_nl
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
+
+# The user is always right.
+if ${PATH_SEPARATOR+false} :; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ printf "%s\n" "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else $as_nop
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else $as_nop
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by PCRE2 $as_me 10.48, which was
+generated by GNU Autoconf 2.71. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config='$ac_cs_config_escaped'
+ac_cs_version="\\
+PCRE2 config.status 10.48
+configured by $0, generated by GNU Autoconf 2.71,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2021 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ printf "%s\n" "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ printf "%s\n" "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ printf "%s\n" "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ printf "%s\n" "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`'
+DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`'
+SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
+host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
+build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
+build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
+SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
+Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
+GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
+EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
+FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
+LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
+NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
+LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
+exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+FILECMD='`$ECHO "$FILECMD" | $SED "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
+want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
+sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
+AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
+STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
+lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
+CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
+compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`'
+nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
+lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
+lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`'
+objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
+libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
+version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
+install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`'
+configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
+striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in AS \
+DLLTOOL \
+OBJDUMP \
+SHELL \
+ECHO \
+PATH_SEPARATOR \
+SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+FILECMD \
+deplibs_check_method \
+file_magic_cmd \
+file_magic_glob \
+want_nocaseglob \
+sharedlib_from_linklib_cmd \
+AR \
+archiver_list_spec \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_import \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+lt_cv_nm_interface \
+nm_file_list_spec \
+lt_cv_truncate_bin \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_pic \
+lt_prog_compiler_wl \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+MANIFEST_TOOL \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_separator \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+install_override_mode \
+finish_eval \
+old_striplib \
+striplib; do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postlink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+configure_time_dlsearch_path \
+configure_time_lt_sys_library_path; do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+ac_aux_dir='$ac_aux_dir'
+
+# See if we are running on zsh, and set the options that allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+fi
+
+
+ PACKAGE='$PACKAGE'
+ VERSION='$VERSION'
+ RM='$RM'
+ ofile='$ofile'
+
+ac_aux_dir='$ac_aux_dir'
+
+
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "src/config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;;
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "libpcre2-8.pc") CONFIG_FILES="$CONFIG_FILES libpcre2-8.pc" ;;
+ "libpcre2-16.pc") CONFIG_FILES="$CONFIG_FILES libpcre2-16.pc" ;;
+ "libpcre2-32.pc") CONFIG_FILES="$CONFIG_FILES libpcre2-32.pc" ;;
+ "libpcre2-posix.pc") CONFIG_FILES="$CONFIG_FILES libpcre2-posix.pc" ;;
+ "pcre2-config") CONFIG_FILES="$CONFIG_FILES pcre2-config" ;;
+ "src/pcre2.h") CONFIG_FILES="$CONFIG_FILES src/pcre2.h" ;;
+ "src/libpcre2-8.sym") CONFIG_FILES="$CONFIG_FILES src/libpcre2-8.sym" ;;
+ "src/libpcre2-16.sym") CONFIG_FILES="$CONFIG_FILES src/libpcre2-16.sym" ;;
+ "src/libpcre2-32.sym") CONFIG_FILES="$CONFIG_FILES src/libpcre2-32.sym" ;;
+ "src/libpcre2-posix.sym") CONFIG_FILES="$CONFIG_FILES src/libpcre2-posix.sym" ;;
+ "script-chmod") CONFIG_COMMANDS="$CONFIG_COMMANDS script-chmod" ;;
+ "delete-old-chartables") CONFIG_COMMANDS="$CONFIG_COMMANDS delete-old-chartables" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
+ test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers
+ test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' >$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' >$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ printf "%s\n" "/* $configure_input */" >&1 \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+printf "%s\n" "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ printf "%s\n" "/* $configure_input */" >&1 \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$_am_arg" : 'X\(//\)[^/]' \| \
+ X"$_am_arg" : 'X\(//\)$' \| \
+ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$_am_arg" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+ :C) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+printf "%s\n" "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+ # Older Autoconf quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ # TODO: see whether this extra hack can be removed once we start
+ # requiring Autoconf 2.70 or later.
+ case $CONFIG_FILES in #(
+ *\'*) :
+ eval set x "$CONFIG_FILES" ;; #(
+ *) :
+ set x $CONFIG_FILES ;; #(
+ *) :
+ ;;
+esac
+ shift
+ # Used to flag and report bootstrapping failures.
+ am_rc=0
+ for am_mf
+ do
+ # Strip MF so we end up with the name of the file.
+ am_mf=`printf "%s\n" "$am_mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile which includes
+ # dependency-tracking related rules and includes.
+ # Grep'ing the whole file directly is not great: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
+ || continue
+ am_dirpart=`$as_dirname -- "$am_mf" ||
+$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$am_mf" : 'X\(//\)[^/]' \| \
+ X"$am_mf" : 'X\(//\)$' \| \
+ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X"$am_mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ am_filepart=`$as_basename -- "$am_mf" ||
+$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$am_mf" : 'X\(//\)$' \| \
+ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
+printf "%s\n" X/"$am_mf" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { echo "$as_me:$LINENO: cd "$am_dirpart" \
+ && sed -e '/# am--include-marker/d' "$am_filepart" \
+ | $MAKE -f - am--depfiles" >&5
+ (cd "$am_dirpart" \
+ && sed -e '/# am--include-marker/d' "$am_filepart" \
+ | $MAKE -f - am--depfiles) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } || am_rc=$?
+ done
+ if test $am_rc -ne 0; then
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Something went wrong bootstrapping makefile fragments
+ for automatic dependency tracking. If GNU make was not used, consider
+ re-running the configure script with MAKE=\"gmake\" (or whatever is
+ necessary). You can also try re-running configure with the
+ '--disable-dependency-tracking' option to at least be able to build
+ the package (albeit without support for automatic dependency tracking).
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ { am_dirpart=; unset am_dirpart;}
+ { am_filepart=; unset am_filepart;}
+ { am_mf=; unset am_mf;}
+ { am_rc=; unset am_rc;}
+ rm -f conftest-deps.mk
+}
+ ;;
+ "libtool":C)
+
+ # See if we are running on zsh, and set the options that allow our
+ # commands through without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+ fi
+
+ cfgfile=${ofile}T
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+ $RM "$cfgfile"
+
+ cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+# Generated automatically by $as_me ($PACKAGE) $VERSION
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit, 1996
+
+# Copyright (C) 2014 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions. There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program or library that is built
+# using GNU Libtool, you may include this file under the same
+# distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=''
+
+# Configured defaults for sys_lib_dlsearch_path munging.
+: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Assembler program.
+AS=$lt_AS
+
+# DLL creation program.
+DLLTOOL=$lt_DLLTOOL
+
+# Object dumper program.
+OBJDUMP=$lt_OBJDUMP
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shared archive member basename,for filename based shared library versioning on AIX.
+shared_archive_member_spec=$shared_archive_member_spec
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# The PATH separator for the build system.
+PATH_SEPARATOR=$lt_PATH_SEPARATOR
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# convert \$build file names to \$host format.
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+
+# convert \$build files to toolchain format.
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+
+# A file(cmd) program that detects file types.
+FILECMD=$lt_FILECMD
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method = "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# How to find potential files when deplibs_check_method = "file_magic".
+file_magic_glob=$lt_file_magic_glob
+
+# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
+want_nocaseglob=$lt_want_nocaseglob
+
+# Command to associate shared and link libraries.
+sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
+
+# The archiver.
+AR=$lt_AR
+
+# Flags to create an archive (by configure).
+lt_ar_flags=$lt_ar_flags
+
+# Flags to create an archive.
+AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"}
+
+# How to feed a file listing to the archiver.
+archiver_list_spec=$lt_archiver_list_spec
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm into a list of symbols to manually relocate.
+global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# The name lister interface.
+nm_interface=$lt_lt_cv_nm_interface
+
+# Specify filename containing input files for \$NM.
+nm_file_list_spec=$lt_nm_file_list_spec
+
+# The root where to search for dependent libraries,and where our libraries should be installed.
+lt_sysroot=$lt_sysroot
+
+# Command to truncate a binary pipe.
+lt_truncate_bin=$lt_lt_cv_truncate_bin
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Manifest tool.
+MANIFEST_TOOL=$lt_MANIFEST_TOOL
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Detected run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path
+
+# Explicit LT_SYS_LIBRARY_PATH set during ./configure time.
+configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \$shlibpath_var if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+ cat <<'_LT_EOF' >> "$cfgfile"
+
+# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+
+# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+# string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+# string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+# "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+# VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+ case x$2 in
+ x)
+ ;;
+ *:)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+ ;;
+ x:*)
+ eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ *::*)
+ eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+ eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+ ;;
+ *)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ esac
+}
+
+
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+ for cc_temp in $*""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+ done
+ func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+
+
+# ### END FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_EOF
+
+ case $host_os in
+ aix3*)
+ cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test set != "${COLLECT_NAMES+set}"; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+_LT_EOF
+ ;;
+ esac
+
+
+
+ltmain=$ac_aux_dir/ltmain.sh
+
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ $SED '$q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" ||
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+
+ ;;
+ "script-chmod":C) chmod a+x pcre2-config ;;
+ "delete-old-chartables":C) rm -f src/pcre2_chartables.c ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
+# --disable-stack-for-recursion is obsolete and has no effect.
+
+if test "$enable_stack_for_recursion" = "no"; then
+cat <
+ #endif
+ #include
+
+ int a, b;
+ size_t m;
+ ]], [[__builtin_mul_overflow(a, b, &m)]])],
+ [pcre2_cc_cv_builtin_mul_overflow=yes],
+ [pcre2_cc_cv_builtin_mul_overflow=no])
+AC_MSG_RESULT([$pcre2_cc_cv_builtin_mul_overflow])
+if test "$pcre2_cc_cv_builtin_mul_overflow" = yes; then
+ AC_DEFINE([HAVE_BUILTIN_MUL_OVERFLOW], 1,
+ [Define this if your compiler provides __builtin_mul_overflow()])
+fi
+AC_LANG_POP([C])
+
+# Check for the unreachable() builtin
+
+AC_MSG_CHECKING([for __builtin_unreachable()])
+AC_LANG_PUSH([C])
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[int r;]], [[if (r) __builtin_unreachable()]])],
+ [pcre2_cc_cv_builtin_unreachable=yes],
+ [pcre2_cc_cv_builtin_unreachable=no])
+AC_MSG_RESULT([$pcre2_cc_cv_builtin_unreachable])
+if test "$pcre2_cc_cv_builtin_unreachable" = yes; then
+ AC_DEFINE([HAVE_BUILTIN_UNREACHABLE], 1,
+ [Define this if your compiler provides __builtin_unreachable()])
+fi
+AC_LANG_POP([C])
+
+# Versioning
+
+PCRE2_MAJOR="pcre2_major"
+PCRE2_MINOR="pcre2_minor"
+PCRE2_PRERELEASE="pcre2_prerelease"
+PCRE2_DATE="pcre2_date"
+
+if test "$PCRE2_MINOR" = "08" -o "$PCRE2_MINOR" = "09"
+then
+ echo "***"
+ echo "*** Minor version number $PCRE2_MINOR must not be used. ***"
+ echo "*** Use only 00 to 07 or 10 onwards, to avoid octal issues. ***"
+ echo "***"
+ exit 1
+fi
+
+AC_SUBST(PCRE2_MAJOR)
+AC_SUBST(PCRE2_MINOR)
+AC_SUBST(PCRE2_PRERELEASE)
+AC_SUBST(PCRE2_DATE)
+
+# Set a more sensible default value for $(htmldir).
+if test "x$htmldir" = 'x${docdir}'
+then
+ htmldir='${docdir}/html'
+fi
+
+# Force an error for PCRE1 size options
+AC_ARG_ENABLE(pcre8,,,enable_pcre8=no)
+AC_ARG_ENABLE(pcre16,,,enable_pcre16=no)
+AC_ARG_ENABLE(pcre32,,,enable_pcre32=no)
+
+if test "$enable_pcre8$enable_pcre16$enable_pcre32" != "nonono"
+then
+ echo "** ERROR: Use --[[en|dis]]able-pcre2-[[8|16|32]], not --[[en|dis]]able-pcre[[8|16|32]]"
+ exit 1
+fi
+
+# Handle --disable-pcre2-8 (enabled by default)
+AC_ARG_ENABLE(pcre2-8,
+ AS_HELP_STRING([--disable-pcre2-8],
+ [disable 8 bit character support]),
+ , enable_pcre2_8=unset)
+AC_SUBST(enable_pcre2_8)
+
+# Handle --enable-pcre2-16 (disabled by default)
+AC_ARG_ENABLE(pcre2-16,
+ AS_HELP_STRING([--enable-pcre2-16],
+ [enable 16 bit character support]),
+ , enable_pcre2_16=unset)
+AC_SUBST(enable_pcre2_16)
+
+# Handle --enable-pcre2-32 (disabled by default)
+AC_ARG_ENABLE(pcre2-32,
+ AS_HELP_STRING([--enable-pcre2-32],
+ [enable 32 bit character support]),
+ , enable_pcre2_32=unset)
+AC_SUBST(enable_pcre2_32)
+
+# Handle --enable-debug (disabled by default)
+AC_ARG_ENABLE(debug,
+ AS_HELP_STRING([--enable-debug],
+ [enable debugging code]),
+ , enable_debug=no)
+
+# Handle --enable-jit (disabled by default)
+AC_ARG_ENABLE(jit,
+ AS_HELP_STRING([--enable-jit],
+ [enable Just-In-Time compiling support]),
+ , enable_jit=no)
+
+# This code enables JIT if the hardware supports it.
+if test "$enable_jit" = "auto"; then
+ AC_LANG(C)
+ SAVE_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS=-I$srcdir
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+ #define SLJIT_CONFIG_AUTO 1
+ #include "deps/sljit/sljit_src/sljitConfigCPU.h"
+ #if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
+ #error unsupported
+ #endif]])], enable_jit=yes, enable_jit=no)
+ CPPFLAGS=$SAVE_CPPFLAGS
+ echo checking for JIT support on this hardware... $enable_jit
+fi
+
+# Handle --enable-jit-sealloc (disabled by default and only experimental)
+case $host_os in
+ linux* | netbsd*)
+ AC_ARG_ENABLE(jit-sealloc,
+ AS_HELP_STRING([--enable-jit-sealloc],
+ [enable SELinux compatible execmem allocator in JIT (experimental)]),
+ ,enable_jit_sealloc=no)
+ ;;
+ *)
+ enable_jit_sealloc=unsupported
+ ;;
+esac
+
+# Handle --disable-pcre2grep-jit (enabled by default)
+AC_ARG_ENABLE(pcre2grep-jit,
+ AS_HELP_STRING([--disable-pcre2grep-jit],
+ [disable JIT support in pcre2grep]),
+ , enable_pcre2grep_jit=yes)
+
+# Handle --disable-pcre2grep-callout (enabled by default)
+AC_ARG_ENABLE(pcre2grep-callout,
+ AS_HELP_STRING([--disable-pcre2grep-callout],
+ [disable callout script support in pcre2grep]),
+ , enable_pcre2grep_callout=yes)
+
+# Handle --disable-pcre2grep-callout-fork (enabled by default)
+AC_ARG_ENABLE(pcre2grep-callout-fork,
+ AS_HELP_STRING([--disable-pcre2grep-callout-fork],
+ [disable callout script fork support in pcre2grep]),
+ , enable_pcre2grep_callout_fork=yes)
+
+# Handle --enable-rebuild-chartables
+AC_ARG_ENABLE(rebuild-chartables,
+ AS_HELP_STRING([--enable-rebuild-chartables],
+ [rebuild character tables in current locale]),
+ , enable_rebuild_chartables=no)
+
+# Handle --disable-unicode (enabled by default)
+AC_ARG_ENABLE(unicode,
+ AS_HELP_STRING([--disable-unicode],
+ [disable Unicode support]),
+ , enable_unicode=unset)
+
+# Handle newline options
+ac_pcre2_newline=lf
+AC_ARG_ENABLE(newline-is-cr,
+ AS_HELP_STRING([--enable-newline-is-cr],
+ [use CR as newline character]),
+ ac_pcre2_newline=cr)
+AC_ARG_ENABLE(newline-is-lf,
+ AS_HELP_STRING([--enable-newline-is-lf],
+ [use LF as newline character (default)]),
+ ac_pcre2_newline=lf)
+AC_ARG_ENABLE(newline-is-crlf,
+ AS_HELP_STRING([--enable-newline-is-crlf],
+ [use CRLF as newline sequence]),
+ ac_pcre2_newline=crlf)
+AC_ARG_ENABLE(newline-is-anycrlf,
+ AS_HELP_STRING([--enable-newline-is-anycrlf],
+ [use CR, LF, or CRLF as newline sequence]),
+ ac_pcre2_newline=anycrlf)
+AC_ARG_ENABLE(newline-is-any,
+ AS_HELP_STRING([--enable-newline-is-any],
+ [use any valid Unicode newline sequence]),
+ ac_pcre2_newline=any)
+AC_ARG_ENABLE(newline-is-nul,
+ AS_HELP_STRING([--enable-newline-is-nul],
+ [use NUL (binary zero) as newline character]),
+ ac_pcre2_newline=nul)
+enable_newline="$ac_pcre2_newline"
+
+# Handle --enable-bsr-anycrlf
+AC_ARG_ENABLE(bsr-anycrlf,
+ AS_HELP_STRING([--enable-bsr-anycrlf],
+ [\R matches only CR, LF, CRLF by default]),
+ , enable_bsr_anycrlf=no)
+
+# Handle --enable-never-backslash-C
+AC_ARG_ENABLE(never-backslash-C,
+ AS_HELP_STRING([--enable-never-backslash-C],
+ [use of \C causes an error]),
+ , enable_never_backslash_C=no)
+
+# Handle --enable-ebcdic
+AC_ARG_ENABLE(ebcdic,
+ AS_HELP_STRING([--enable-ebcdic],
+ [assume EBCDIC coding rather than ASCII; incompatible with --enable-unicode; use only in (uncommon) EBCDIC environments]),
+ , enable_ebcdic=no)
+
+# Handle --enable-ebcdic-nl25
+AC_ARG_ENABLE(ebcdic-nl25,
+ AS_HELP_STRING([--enable-ebcdic-nl25],
+ [set EBCDIC code for NL to 0x25 instead of 0x15; it implies --enable-ebcdic]),
+ , enable_ebcdic_nl25=no)
+
+# Handle --enable-ebcdic-ignoring-compiler
+AC_ARG_ENABLE(ebcdic-ignoring-compiler,
+ AS_HELP_STRING([--enable-ebcdic-ignoring-compiler],
+ [force EBCDIC 1047 using numeric literals rather than C character literals; it implies --enable-ebcdic]),
+ , enable_ebcdic_ignoring_compiler=no)
+
+# Handle --enable-pcre2grep-libz
+AC_ARG_ENABLE(pcre2grep-libz,
+ AS_HELP_STRING([--enable-pcre2grep-libz],
+ [link pcre2grep with libz to handle .gz files]),
+ , enable_pcre2grep_libz=no)
+
+# Handle --enable-pcre2grep-libbz2
+AC_ARG_ENABLE(pcre2grep-libbz2,
+ AS_HELP_STRING([--enable-pcre2grep-libbz2],
+ [link pcre2grep with libbz2 to handle .bz2 files]),
+ , enable_pcre2grep_libbz2=no)
+
+# Handle --with-pcre2grep-bufsize=N
+AC_ARG_WITH(pcre2grep-bufsize,
+ AS_HELP_STRING([--with-pcre2grep-bufsize=N],
+ [pcre2grep initial buffer size (default=20480, minimum=8192)]),
+ , with_pcre2grep_bufsize=20480)
+
+# Handle --with-pcre2grep-max-bufsize=N
+AC_ARG_WITH(pcre2grep-max-bufsize,
+ AS_HELP_STRING([--with-pcre2grep-max-bufsize=N],
+ [pcre2grep maximum buffer size (default=1048576, minimum=8192)]),
+ , with_pcre2grep_max_bufsize=1048576)
+
+# Handle --enable-pcre2test-libedit
+AC_ARG_ENABLE(pcre2test-libedit,
+ AS_HELP_STRING([--enable-pcre2test-libedit],
+ [link pcre2test with libedit]),
+ , enable_pcre2test_libedit=no)
+
+# Handle --enable-pcre2test-libreadline
+AC_ARG_ENABLE(pcre2test-libreadline,
+ AS_HELP_STRING([--enable-pcre2test-libreadline],
+ [link pcre2test with libreadline]),
+ , enable_pcre2test_libreadline=no)
+
+# Handle --with-link-size=N
+AC_ARG_WITH(link-size,
+ AS_HELP_STRING([--with-link-size=N],
+ [internal link size (2, 3, or 4 allowed; default=2)]),
+ , with_link_size=2)
+
+# Handle --with-max-varlookbehind=N
+AC_ARG_WITH(max-varlookbehind,
+ AS_HELP_STRING([--with-max-varlookbehind=N],
+ [maximum length of variable lookbehind (default=255)]),
+ , with_max_varlookbehind=255)
+
+# Handle --with-parens-nest-limit=N
+AC_ARG_WITH(parens-nest-limit,
+ AS_HELP_STRING([--with-parens-nest-limit=N],
+ [nested parentheses limit (default=250)]),
+ , with_parens_nest_limit=250)
+
+# Handle --with-heap-limit
+AC_ARG_WITH(heap-limit,
+ AS_HELP_STRING([--with-heap-limit=N],
+ [default limit on heap memory (kibibytes, default=20000000)]),
+ , with_heap_limit=20000000)
+
+# Handle --with-match-limit=N
+AC_ARG_WITH(match-limit,
+ AS_HELP_STRING([--with-match-limit=N],
+ [default limit on internal looping (default=10000000)]),
+ , with_match_limit=10000000)
+
+# Handle --with-match-limit-depth=N
+# Recognize old synonym --with-match-limit-recursion
+#
+# Note: In config.h, the default is to define MATCH_LIMIT_DEPTH symbolically as
+# MATCH_LIMIT, which in turn is defined to be some numeric value (e.g.
+# 10000000). MATCH_LIMIT_DEPTH can otherwise be set to some different numeric
+# value (or even the same numeric value as MATCH_LIMIT, though no longer
+# defined in terms of the latter).
+#
+AC_ARG_WITH(match-limit-depth,
+ AS_HELP_STRING([--with-match-limit-depth=N],
+ [default limit on match tree depth (default=MATCH_LIMIT)]),
+ , with_match_limit_depth=MATCH_LIMIT)
+
+AC_ARG_WITH(match-limit-recursion,,
+ , with_match_limit_recursion=UNSET)
+
+# Handle --enable-valgrind
+AC_ARG_ENABLE(valgrind,
+ AS_HELP_STRING([--enable-valgrind],
+ [enable valgrind support]),
+ , enable_valgrind=no)
+
+# Enable code coverage reports using gcov
+AC_ARG_ENABLE(coverage,
+ AS_HELP_STRING([--enable-coverage],
+ [enable code coverage reports using gcov]),
+ , enable_coverage=no)
+
+# Handle --enable-fuzz-support
+AC_ARG_ENABLE(fuzz_support,
+ AS_HELP_STRING([--enable-fuzz-support],
+ [enable fuzzer support]),
+ , enable_fuzz_support=no)
+
+# Handle --enable-diff-fuzz-support
+AC_ARG_ENABLE(diff_fuzz_support,
+ AS_HELP_STRING([--enable-diff-fuzz-support],
+ [enable differential fuzzer support]),
+ , enable_diff_fuzz_support=no)
+
+# Handle --disable-stack-for-recursion
+# This option became obsolete at release 10.30.
+AC_ARG_ENABLE(stack-for-recursion,,
+ , enable_stack_for_recursion=yes)
+
+# Original code
+# AC_ARG_ENABLE(stack-for-recursion,
+# AS_HELP_STRING([--disable-stack-for-recursion],
+# [don't use stack recursion when matching]),
+# , enable_stack_for_recursion=yes)
+
+# Handle --disable-percent_zt (set as "auto" by default)
+AC_ARG_ENABLE(percent-zt,
+ AS_HELP_STRING([--disable-percent-zt],
+ [disable the use of z and t formatting modifiers]),
+ , enable_percent_zt=auto)
+
+# Handle --enable-Werror/errwarn
+AC_ARG_ENABLE(Werror,
+ AS_HELP_STRING([--enable-Werror],
+ [Add -Werror to CFLAGS (GCC/Clang style); if -Werror is passed to ./configure via CFLAGS it interferes with feature detection]),
+ , enable_Werror=no)
+AC_ARG_ENABLE(errwarn,
+ AS_HELP_STRING([--enable-errwarn],
+ [Add -errwarn=%all to CFLAGS (Sun cc style)]),
+ , enable_errwarn=no)
+
+# Set the default value for pcre2-8
+if test "x$enable_pcre2_8" = "xunset"
+then
+ enable_pcre2_8=yes
+fi
+
+# Set the default value for pcre2-16
+if test "x$enable_pcre2_16" = "xunset"
+then
+ enable_pcre2_16=no
+fi
+
+# Set the default value for pcre2-32
+if test "x$enable_pcre2_32" = "xunset"
+then
+ enable_pcre2_32=no
+fi
+
+# Make sure at least one library is selected
+if test "x$enable_pcre2_8$enable_pcre2_16$enable_pcre2_32" = "xnonono"
+then
+ AC_MSG_ERROR([At least one of the 8, 16 or 32 bit libraries must be enabled])
+fi
+
+# Unicode is enabled by default.
+if test "x$enable_unicode" = "xunset"
+then
+ enable_unicode=yes
+fi
+
+# Convert the newline identifier into the appropriate integer value. These must
+# agree with the PCRE2_NEWLINE_xxx values in pcre2.h.
+
+case "$enable_newline" in
+ cr) ac_pcre2_newline_value=1 ;;
+ lf) ac_pcre2_newline_value=2 ;;
+ crlf) ac_pcre2_newline_value=3 ;;
+ any) ac_pcre2_newline_value=4 ;;
+ anycrlf) ac_pcre2_newline_value=5 ;;
+ nul) ac_pcre2_newline_value=6 ;;
+ *)
+ AC_MSG_ERROR([invalid argument "$enable_newline" to --enable-newline option])
+ ;;
+esac
+
+# --enable-ebcdic-nl25 and --enable-ebcdic-ignoring-compiler imply --enable-ebcdic
+if test "x$enable_ebcdic_nl25" = "xyes" -o "x$enable_ebcdic_ignoring_compiler" = "xyes"; then
+ enable_ebcdic=yes
+fi
+
+# Make sure that if enable_ebcdic is set (without
+# enable_ebcdic_ignoring_compiler), rebuild_chartables is also enabled.
+# Also check that UTF support is not requested, because PCRE2 cannot handle
+# EBCDIC and UTF in the same build. To do so it would need to use different
+# character constants depending on the mode.
+# Also, EBCDIC cannot be used with 16-bit and 32-bit libraries.
+if test "x$enable_ebcdic" = "xyes"; then
+ if test "x$enable_ebcdic_ignoring_compiler" != "xyes"; then
+ enable_rebuild_chartables=yes
+ fi
+ if test "x$enable_unicode" = "xyes"; then
+ AC_MSG_ERROR([support for EBCDIC and Unicode cannot be enabled at the same time])
+ fi
+ if test "x$enable_pcre2_16" = "xyes" -o "x$enable_pcre2_32" = "xyes"; then
+ AC_MSG_ERROR([EBCDIC support is available only for the 8-bit library])
+ fi
+fi
+
+# Check argument to --with-link-size
+case "$with_link_size" in
+ 2|3|4) ;;
+ *)
+ AC_MSG_ERROR([invalid argument "$with_link_size" to --with-link-size option])
+ ;;
+esac
+
+AH_TOP([
+/* PCRE2 is written in Standard C, but there are a few non-standard things it
+can cope with, allowing it to run on SunOS4 and other "close to standard"
+systems.
+
+In environments that support the GNU autotools, config.h.in is converted into
+config.h by the "configure" script. In environments that use CMake,
+config-cmake.in is converted into config.h. If you are going to build PCRE2 "by
+hand" without using "configure" or CMake, you should copy the distributed
+config.h.generic to config.h, and edit the macro definitions to be the way you
+need them. You must then add -DHAVE_CONFIG_H to all of your compile commands,
+so that config.h is included at the start of every source.
+
+Alternatively, you can avoid editing by using -D on the compiler command line
+to set the macro values. In this case, you do not have to set -DHAVE_CONFIG_H,
+but if you do, default values will be taken from config.h for non-boolean
+macros that are not defined on the command line.
+
+Boolean macros such as HAVE_STDLIB_H and SUPPORT_PCRE2_8 should either be
+defined (conventionally to 1) for TRUE, and not defined at all for FALSE. All
+such macros are listed as a commented #undef in config.h.generic. Macros such
+as MATCH_LIMIT, whose actual value is relevant, have defaults defined, but are
+surrounded by #ifndef/#endif lines so that the value can be overridden by -D. */])
+
+# Checks for header files.
+AC_CHECK_HEADERS(assert.h limits.h sys/types.h sys/stat.h dirent.h)
+AC_CHECK_HEADERS([windows.h], [HAVE_WINDOWS_H=1])
+AC_CHECK_HEADERS([sys/wait.h], [HAVE_SYS_WAIT_H=1])
+
+# Conditional compilation
+AM_CONDITIONAL(WITH_PCRE2_8, test "x$enable_pcre2_8" = "xyes")
+AM_CONDITIONAL(WITH_PCRE2_16, test "x$enable_pcre2_16" = "xyes")
+AM_CONDITIONAL(WITH_PCRE2_32, test "x$enable_pcre2_32" = "xyes")
+AM_CONDITIONAL(WITH_REBUILD_CHARTABLES, test "x$enable_rebuild_chartables" = "xyes")
+AM_CONDITIONAL(WITH_JIT, test "x$enable_jit" = "xyes")
+AM_CONDITIONAL(WITH_UNICODE, test "x$enable_unicode" = "xyes")
+AM_CONDITIONAL(WITH_EBCDIC, test "x$enable_ebcdic" = "xyes")
+AM_CONDITIONAL(WITH_EBCDIC_NL25, test "x$enable_ebcdic_nl25" = "xyes")
+AM_CONDITIONAL(WITH_VALGRIND, test "x$enable_valgrind" = "xyes")
+AM_CONDITIONAL(WITH_FUZZ_SUPPORT, test "x$enable_fuzz_support" = "xyes")
+AM_CONDITIONAL(WITH_DIFF_FUZZ_SUPPORT, test "x$enable_diff_fuzz_support" = "xyes")
+
+if test "$enable_fuzz_support" = "yes" -a "$enable_pcre2_8" = "no"; then
+ echo "** ERROR: Fuzzer support requires the 8-bit library"
+ exit 1
+fi
+
+if test "$enable_diff_fuzz_support" = "yes"; then
+ if test "$enable_fuzz_support" = "no"; then
+ echo "** ERROR: Differential fuzzing support requires fuzzing support"
+ exit 1
+ fi
+ if test "$enable_jit" = "no"; then
+ echo "** ERROR: Differential fuzzing support requires Just-in-Time compilation support"
+ exit 1
+ fi
+ AC_DEFINE([SUPPORT_DIFF_FUZZ], [], [
+ Define to any value to enable differential fuzzing support.])
+fi
+
+# Checks for typedefs, structures, and compiler characteristics.
+
+AC_C_CONST
+AC_TYPE_SIZE_T
+
+# Checks for library functions.
+
+AC_CHECK_FUNCS(memfd_create mkostemp secure_getenv setrlimit)
+AC_MSG_CHECKING([for realpath])
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#include
+#include
+]],[[
+char buffer[PATH_MAX];
+realpath(".", buffer);
+]])],
+[AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_REALPATH], 1,
+ [Define to 1 if you have the `realpath' function.])
+],
+AC_MSG_RESULT([no]))
+
+# Check for the availability of libz (aka zlib)
+
+AC_CHECK_HEADERS([zlib.h], [HAVE_ZLIB_H=1])
+AC_CHECK_LIB([z], [gzopen], [HAVE_LIBZ=1])
+
+# Check for the availability of libbz2. Originally we just used AC_CHECK_LIB,
+# as for libz. However, this had the following problem, diagnosed and fixed by
+# a user:
+#
+# - libbz2 uses the Pascal calling convention (WINAPI) for the functions
+# under Win32.
+# - The standard autoconf AC_CHECK_LIB fails to include "bzlib.h",
+# therefore missing the function definition.
+# - The compiler thus generates a "C" signature for the test function.
+# - The linker fails to find the "C" function.
+# - PCRE2 fails to configure if asked to do so against libbz2.
+#
+# Solution:
+#
+# - Replace the AC_CHECK_LIB test with a custom test.
+
+AC_CHECK_HEADERS([bzlib.h], [HAVE_BZLIB_H=1])
+# Original test
+# AC_CHECK_LIB([bz2], [BZ2_bzopen], [HAVE_LIBBZ2=1])
+#
+# Custom test follows
+
+AC_MSG_CHECKING([for libbz2])
+OLD_LIBS="$LIBS"
+LIBS="$LIBS -lbz2"
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+#ifdef HAVE_BZLIB_H
+#include
+#endif]],
+[[return (int)BZ2_bzopen("conftest", "rb");]])],
+[AC_MSG_RESULT([yes]);HAVE_LIBBZ2=1; break;],
+AC_MSG_RESULT([no]))
+LIBS="$OLD_LIBS"
+
+# Check for the availability of libreadline
+
+if test "$enable_pcre2test_libreadline" = "yes"; then
+ AC_CHECK_HEADERS([readline/readline.h], [HAVE_READLINE_H=1])
+ AC_CHECK_HEADERS([readline/history.h], [HAVE_HISTORY_H=1])
+ AC_CHECK_LIB([readline], [readline], [LIBREADLINE="-lreadline"],
+ [unset ac_cv_lib_readline_readline;
+ AC_CHECK_LIB([readline], [readline], [LIBREADLINE="-ltinfo"],
+ [unset ac_cv_lib_readline_readline;
+ AC_CHECK_LIB([readline], [readline], [LIBREADLINE="-lcurses"],
+ [unset ac_cv_lib_readline_readline;
+ AC_CHECK_LIB([readline], [readline], [LIBREADLINE="-lncurses"],
+ [unset ac_cv_lib_readline_readline;
+ AC_CHECK_LIB([readline], [readline], [LIBREADLINE="-lncursesw"],
+ [unset ac_cv_lib_readline_readline;
+ AC_CHECK_LIB([readline], [readline], [LIBREADLINE="-ltermcap"],
+ [LIBREADLINE=""],
+ [-ltermcap])],
+ [-lncursesw])],
+ [-lncurses])],
+ [-lcurses])],
+ [-ltinfo])])
+ AC_SUBST(LIBREADLINE)
+ if test -n "$LIBREADLINE"; then
+ if test "$LIBREADLINE" != "-lreadline"; then
+ echo "-lreadline needs $LIBREADLINE"
+ LIBREADLINE="-lreadline $LIBREADLINE"
+ fi
+ fi
+fi
+
+# Check for the availability of libedit. Different distributions put its
+# headers in different places. Try to cover the most common ones.
+
+if test "$enable_pcre2test_libedit" = "yes"; then
+ AC_CHECK_HEADERS([editline/readline.h edit/readline/readline.h readline.h], [
+ HAVE_LIBEDIT_HEADER=1
+ break
+ ])
+ AC_CHECK_LIB([edit], [readline], [LIBEDIT="-ledit"])
+fi
+
+# Set up shared/static library flags
+
+PCRE2_STATIC_CFLAG=""
+if test "x$enable_shared" = "xno" ; then
+ AC_DEFINE([PCRE2_STATIC], [1], [
+ Define to any value if linking statically. Ideally, if both static and
+ shared libraries are being built, then PCRE2_STATIC would be defined only
+ for the static build. Indeed, this is a requirement on Windows. With
+ Autoconf and libtool however, it is idiomatic to compile the sources once
+ to create both the static and shared library, so in this case, PCRE2_STATIC
+ should only be defined if no shared library is being built.])
+ PCRE2_STATIC_CFLAG="-DPCRE2_STATIC"
+fi
+AC_SUBST(PCRE2_STATIC_CFLAG)
+
+PCRE2POSIX_CFLAG=""
+if test "x$enable_shared" = "xyes" ; then
+ AC_DEFINE([PCRE2POSIX_SHARED], [1], [
+ Define to any value if linking libpcre2-posix dynamically. Ideally, if both
+ static and shared libraries are being built, then PCRE2POSIX_SHARED would be
+ defined only for the shared build. Indeed, this is a requirement on Windows.
+ However, when building with Autoconf and libtool, we compile the sources once
+ only to create both the static and shared library, so in this case,
+ PCRE2POSIX_SHARED should only be defined if the shared library is being built,
+ regardless of whether or not the static library is also being built.])
+ PCRE2POSIX_CFLAG="-DPCRE2POSIX_SHARED"
+fi
+AC_SUBST(PCRE2POSIX_CFLAG)
+
+# Here is where PCRE2-specific defines are handled
+
+if test "$enable_pcre2_8" = "yes"; then
+ AC_DEFINE([SUPPORT_PCRE2_8], [], [
+ Define to any value to enable the 8 bit PCRE2 library.])
+fi
+
+if test "$enable_pcre2_16" = "yes"; then
+ AC_DEFINE([SUPPORT_PCRE2_16], [], [
+ Define to any value to enable the 16 bit PCRE2 library.])
+fi
+
+if test "$enable_pcre2_32" = "yes"; then
+ AC_DEFINE([SUPPORT_PCRE2_32], [], [
+ Define to any value to enable the 32 bit PCRE2 library.])
+fi
+
+if test "$enable_debug" = "yes"; then
+ AC_DEFINE([PCRE2_DEBUG], [], [
+ Define to any value to include debugging code.])
+fi
+
+if test "$enable_percent_zt" = "no"; then
+ AC_DEFINE([DISABLE_PERCENT_ZT], [], [
+ Define to any value to disable the use of the z and t modifiers in
+ formatting settings such as %zu or %td (this is rarely needed).])
+else
+ enable_percent_zt=auto
+fi
+
+# Unless running under Windows, JIT support requires pthreads.
+
+if test "$enable_jit" = "yes"; then
+ if test "$HAVE_WINDOWS_H" != "1"; then
+ AX_PTHREAD([], [AC_MSG_ERROR([JIT support requires pthreads])])
+ CC="$PTHREAD_CC"
+ CFLAGS="$PTHREAD_CFLAGS $CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ fi
+ AC_DEFINE([SUPPORT_JIT], [], [
+ Define to any value to enable support for Just-In-Time compiling.])
+else
+ enable_pcre2grep_jit="no"
+fi
+
+if test "$enable_jit_sealloc" = "yes"; then
+ AC_DEFINE([SLJIT_PROT_EXECUTABLE_ALLOCATOR], [1], [
+ Define to any non-zero number to enable support for SELinux
+ compatible executable memory allocator in JIT. Note that this
+ will have no effect unless SUPPORT_JIT is also defined.])
+fi
+
+if test "$enable_pcre2grep_jit" = "yes"; then
+ AC_DEFINE([SUPPORT_PCRE2GREP_JIT], [], [
+ Define to any value to enable JIT support in pcre2grep. Note that this will
+ have no effect unless SUPPORT_JIT is also defined.])
+fi
+
+if test "$enable_pcre2grep_callout" = "yes"; then
+ if test "$enable_pcre2grep_callout_fork" = "yes"; then
+ if test "$HAVE_WINDOWS_H" != "1"; then
+ if test "$HAVE_SYS_WAIT_H" != "1"; then
+ AC_MSG_ERROR([Callout script support needs sys/wait.h.])
+ fi
+ fi
+ AC_DEFINE([SUPPORT_PCRE2GREP_CALLOUT_FORK], [], [
+ Define to any value to enable fork support in pcre2grep callout scripts.
+ This will have no effect unless SUPPORT_PCRE2GREP_CALLOUT is also
+ defined.])
+ fi
+ AC_DEFINE([SUPPORT_PCRE2GREP_CALLOUT], [], [
+ Define to any value to enable callout script support in pcre2grep.])
+else
+ enable_pcre2grep_callout_fork="no"
+fi
+
+if test "$enable_unicode" = "yes"; then
+ AC_DEFINE([SUPPORT_UNICODE], [], [
+ Define to any value to enable support for Unicode and UTF encoding.
+ This will work even in an EBCDIC environment, but it is incompatible
+ with the EBCDIC macro. That is, PCRE2 can support *either* EBCDIC
+ code *or* ASCII/Unicode, but not both at once.])
+fi
+
+if test "$enable_pcre2grep_libz" = "yes"; then
+ AC_DEFINE([SUPPORT_LIBZ], [], [
+ Define to any value to allow pcre2grep to be linked with libz, so that it is
+ able to handle .gz files.])
+fi
+
+if test "$enable_pcre2grep_libbz2" = "yes"; then
+ AC_DEFINE([SUPPORT_LIBBZ2], [], [
+ Define to any value to allow pcre2grep to be linked with libbz2, so that it
+ is able to handle .bz2 files.])
+fi
+
+if test $with_pcre2grep_bufsize -lt 8192 ; then
+ AC_MSG_WARN([$with_pcre2grep_bufsize is too small for --with-pcre2grep-bufsize; using 8192])
+ with_pcre2grep_bufsize="8192"
+else
+ if test $? -gt 1 ; then
+ AC_MSG_ERROR([Bad value for --with-pcre2grep-bufsize])
+ fi
+fi
+
+if test $with_pcre2grep_max_bufsize -lt $with_pcre2grep_bufsize ; then
+ with_pcre2grep_max_bufsize="$with_pcre2grep_bufsize"
+else
+ if test $? -gt 1 ; then
+ AC_MSG_ERROR([Bad value for --with-pcre2grep-max-bufsize])
+ fi
+fi
+
+AC_DEFINE_UNQUOTED([PCRE2GREP_BUFSIZE], [$with_pcre2grep_bufsize], [
+ The value of PCRE2GREP_BUFSIZE is the starting size of the buffer used by
+ pcre2grep to hold parts of the file it is searching. The buffer will be
+ expanded up to PCRE2GREP_MAX_BUFSIZE if necessary, for files containing very
+ long lines. The actual amount of memory used by pcre2grep is three times this
+ number, because it allows for the buffering of "before" and "after" lines.])
+
+AC_DEFINE_UNQUOTED([PCRE2GREP_MAX_BUFSIZE], [$with_pcre2grep_max_bufsize], [
+ The value of PCRE2GREP_MAX_BUFSIZE specifies the maximum size of the buffer
+ used by pcre2grep to hold parts of the file it is searching. The actual
+ amount of memory used by pcre2grep is three times this number, because it
+ allows for the buffering of "before" and "after" lines.])
+
+if test "$enable_pcre2test_libedit" = "yes"; then
+ AC_DEFINE([SUPPORT_LIBEDIT], [], [
+ Define to any value to allow pcre2test to be linked with libedit.])
+ LIBREADLINE="$LIBEDIT"
+elif test "$enable_pcre2test_libreadline" = "yes"; then
+ AC_DEFINE([SUPPORT_LIBREADLINE], [], [
+ Define to any value to allow pcre2test to be linked with libreadline.])
+fi
+
+AC_DEFINE_UNQUOTED([NEWLINE_DEFAULT], [$ac_pcre2_newline_value], [
+ The value of NEWLINE_DEFAULT determines the default newline character
+ sequence. PCRE2 client programs can override this by selecting other values
+ at run time. The valid values are 1 (CR), 2 (LF), 3 (CRLF), 4 (ANY),
+ 5 (ANYCRLF), and 6 (NUL).])
+
+if test "$enable_bsr_anycrlf" = "yes"; then
+ AC_DEFINE([BSR_ANYCRLF], [], [
+ By default, the \R escape sequence matches any Unicode line ending
+ character or sequence of characters. If BSR_ANYCRLF is defined (to any
+ value), this is changed so that backslash-R matches only CR, LF, or CRLF.
+ The build-time default can be overridden by the user of PCRE2 at runtime.])
+fi
+
+if test "$enable_never_backslash_C" = "yes"; then
+ AC_DEFINE([NEVER_BACKSLASH_C], [], [
+ Defining NEVER_BACKSLASH_C locks out the use of \C in all patterns.])
+fi
+
+AC_DEFINE_UNQUOTED([LINK_SIZE], [$with_link_size], [
+ The value of LINK_SIZE determines the number of bytes used to store
+ links as offsets within the compiled regex. The default is 2, which
+ allows for compiled patterns up to 65535 code units long. This covers the
+ vast majority of cases. However, PCRE2 can also be compiled to use 3 or 4
+ bytes instead. This allows for longer patterns in extreme cases.])
+
+AC_DEFINE_UNQUOTED([MAX_VARLOOKBEHIND], [$with_max_varlookbehind], [
+ The value of MAX_VARLOOKBEHIND specifies the default maximum length, in
+ characters, for a variable-length lookbehind assertion.])
+
+AC_DEFINE_UNQUOTED([PARENS_NEST_LIMIT], [$with_parens_nest_limit], [
+ The value of PARENS_NEST_LIMIT specifies the maximum depth of nested
+ parentheses (of any kind) in a pattern. This limits the amount of system
+ stack that is used while compiling a pattern.])
+
+AC_DEFINE_UNQUOTED([MATCH_LIMIT], [$with_match_limit], [
+ The value of MATCH_LIMIT determines the default number of times the
+ pcre2_match() function can record a backtrack position during a single
+ matching attempt. The value is also used to limit a loop counter in
+ pcre2_dfa_match(). There is a runtime interface for setting a different
+ limit. The limit exists in order to catch runaway regular expressions that
+ take forever to determine that they do not match. The default is set very
+ large so that it does not accidentally catch legitimate cases.])
+
+# --with-match-limit-recursion is an obsolete synonym for --with-match-limit-depth
+
+if test "$with_match_limit_recursion" != "UNSET"; then
+cat <.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva .
+
+case $1 in
+ '')
+ echo "$0: No command. Try '$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+ depmode Dependency tracking mode.
+ source Source file read by 'PROGRAMS ARGS'.
+ object Object file output by 'PROGRAMS ARGS'.
+ DEPDIR directory where to store dependencies.
+ depfile Dependency file to output.
+ tmpdepfile Temporary file to use when outputting dependencies.
+ libtool Whether libtool is used (yes/no).
+
+Report bugs to .
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "depcomp $scriptversion"
+ exit $?
+ ;;
+esac
+
+# Get the directory component of the given path, and save it in the
+# global variables '$dir'. Note that this directory component will
+# be either empty or ending with a '/' character. This is deliberate.
+set_dir_from ()
+{
+ case $1 in
+ */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
+ *) dir=;;
+ esac
+}
+
+# Get the suffix-stripped basename of the given path, and save it the
+# global variable '$base'.
+set_base_from ()
+{
+ base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
+}
+
+# If no dependency file was actually created by the compiler invocation,
+# we still have to create a dummy depfile, to avoid errors with the
+# Makefile "include basename.Plo" scheme.
+make_dummy_depfile ()
+{
+ echo "#dummy" > "$depfile"
+}
+
+# Factor out some common post-processing of the generated depfile.
+# Requires the auxiliary global variable '$tmpdepfile' to be set.
+aix_post_process_depfile ()
+{
+ # If the compiler actually managed to produce a dependency file,
+ # post-process it.
+ if test -f "$tmpdepfile"; then
+ # Each line is of the form 'foo.o: dependency.h'.
+ # Do two passes, one to just change these to
+ # $object: dependency.h
+ # and one to simply output
+ # dependency.h:
+ # which is needed to avoid the deleted-header problem.
+ { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
+ sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
+ } > "$depfile"
+ rm -f "$tmpdepfile"
+ else
+ make_dummy_depfile
+ fi
+}
+
+# A tabulation character.
+tab=' '
+# A newline character.
+nl='
+'
+# Character ranges might be problematic outside the C locale.
+# These definitions help.
+upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
+lower=abcdefghijklmnopqrstuvwxyz
+digits=0123456789
+alpha=${upper}${lower}
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
+ exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+ sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Avoid interferences from the environment.
+gccflag= dashmflag=
+
+# Some modes work just like other modes, but use different flags. We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write. Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+ # HP compiler uses -M and no extra arg.
+ gccflag=-M
+ depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+ # This is just like msvisualcpp but w/o cygpath translation.
+ # Just convert the backslash-escaped backslashes to single forward
+ # slashes to satisfy depend.m4
+ cygpath_u='sed s,\\\\,/,g'
+ depmode=msvisualcpp
+fi
+
+if test "$depmode" = msvc7msys; then
+ # This is just like msvc7 but w/o cygpath translation.
+ # Just convert the backslash-escaped backslashes to single forward
+ # slashes to satisfy depend.m4
+ cygpath_u='sed s,\\\\,/,g'
+ depmode=msvc7
+fi
+
+if test "$depmode" = xlc; then
+ # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
+ gccflag=-qmakedep=gcc,-MF
+ depmode=gcc
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want. Yay! Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff. Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am. Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+ for arg
+ do
+ case $arg in
+ -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+ *) set fnord "$@" "$arg" ;;
+ esac
+ shift # fnord
+ shift # $arg
+ done
+ "$@"
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
+## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
+## (see the conditional assignment to $gccflag above).
+## There are various ways to get dependency output from gcc. Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+## up in a subdir. Having to rename by hand is ugly.
+## (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+## -MM, not -M (despite what the docs say). Also, it might not be
+## supported by the other compilers which use the 'gcc' depmode.
+## - Using -M directly means running the compiler twice (even worse
+## than renaming).
+ if test -z "$gccflag"; then
+ gccflag=-MD,
+ fi
+ "$@" -Wp,"$gccflag$tmpdepfile"
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ # The second -e expression handles DOS-style file names with drive
+ # letters.
+ sed -e 's/^[^:]*: / /' \
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the "deleted header file" problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header). We avoid this by adding
+## dummy dependencies for each header file. Too bad gcc doesn't do
+## this for us directly.
+## Some versions of gcc put a space before the ':'. On the theory
+## that the space means something, we add a space to the output as
+## well. hp depmode also adds that space, but also prefixes the VPATH
+## to the object. Take care to not repeat it in the output.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ tr ' ' "$nl" < "$tmpdepfile" \
+ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
+ | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+sgi)
+ if test "$libtool" = yes; then
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
+ else
+ "$@" -MDupdate "$tmpdepfile"
+ fi
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
+ echo "$object : \\" > "$depfile"
+ # Clip off the initial element (the dependent). Don't try to be
+ # clever and replace this with sed code, as IRIX sed won't handle
+ # lines with more than a fixed number of characters (4096 in
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
+ # the IRIX cc adds comments like '#:fec' to the end of the
+ # dependency line.
+ tr ' ' "$nl" < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
+ | tr "$nl" ' ' >> "$depfile"
+ echo >> "$depfile"
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' "$nl" < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> "$depfile"
+ else
+ make_dummy_depfile
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+xlc)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+aix)
+ # The C for AIX Compiler uses -M and outputs the dependencies
+ # in a .u file. In older versions, this file always lives in the
+ # current directory. Also, the AIX compiler puts '$object:' at the
+ # start of each line; $object doesn't have directory information.
+ # Version 6 uses the directory in both cases.
+ set_dir_from "$object"
+ set_base_from "$object"
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$base.u
+ tmpdepfile3=$dir.libs/$base.u
+ "$@" -Wc,-M
+ else
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$dir$base.u
+ tmpdepfile3=$dir$base.u
+ "$@" -M
+ fi
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ aix_post_process_depfile
+ ;;
+
+tcc)
+ # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
+ # FIXME: That version still under development at the moment of writing.
+ # Make that this statement remains true also for stable, released
+ # versions.
+ # It will wrap lines (doesn't matter whether long or short) with a
+ # trailing '\', as in:
+ #
+ # foo.o : \
+ # foo.c \
+ # foo.h \
+ #
+ # It will put a trailing '\' even on the last line, and will use leading
+ # spaces rather than leading tabs (at least since its commit 0394caf7
+ # "Emit spaces for -MD").
+ "$@" -MD -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
+ # We have to change lines of the first kind to '$object: \'.
+ sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
+ # And for each line of the second kind, we have to emit a 'dep.h:'
+ # dummy dependency, to avoid the deleted-header problem.
+ sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+## The order of this option in the case statement is important, since the
+## shell code in configure will try each of these formats in the order
+## listed in this file. A plain '-MD' option would be understood by many
+## compilers, so we must ensure this comes after the gcc and icc options.
+pgcc)
+ # Portland's C compiler understands '-MD'.
+ # Will always output deps to 'file.d' where file is the root name of the
+ # source file under compilation, even if file resides in a subdirectory.
+ # The object file name does not affect the name of the '.d' file.
+ # pgcc 10.2 will output
+ # foo.o: sub/foo.c sub/foo.h
+ # and will wrap long lines using '\' :
+ # foo.o: sub/foo.c ... \
+ # sub/foo.h ... \
+ # ...
+ set_dir_from "$object"
+ # Use the source, not the object, to determine the base name, since
+ # that's sadly what pgcc will do too.
+ set_base_from "$source"
+ tmpdepfile=$base.d
+
+ # For projects that build the same source file twice into different object
+ # files, the pgcc approach of using the *source* file root name can cause
+ # problems in parallel builds. Use a locking strategy to avoid stomping on
+ # the same $tmpdepfile.
+ lockdir=$base.d-lock
+ trap "
+ echo '$0: caught signal, cleaning up...' >&2
+ rmdir '$lockdir'
+ exit 1
+ " 1 2 13 15
+ numtries=100
+ i=$numtries
+ while test $i -gt 0; do
+ # mkdir is a portable test-and-set.
+ if mkdir "$lockdir" 2>/dev/null; then
+ # This process acquired the lock.
+ "$@" -MD
+ stat=$?
+ # Release the lock.
+ rmdir "$lockdir"
+ break
+ else
+ # If the lock is being held by a different process, wait
+ # until the winning process is done or we timeout.
+ while test -d "$lockdir" && test $i -gt 0; do
+ sleep 1
+ i=`expr $i - 1`
+ done
+ fi
+ i=`expr $i - 1`
+ done
+ trap - 1 2 13 15
+ if test $i -le 0; then
+ echo "$0: failed to acquire lock after $numtries attempts" >&2
+ echo "$0: check lockdir '$lockdir'" >&2
+ exit 1
+ fi
+
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ # Each line is of the form `foo.o: dependent.h',
+ # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process this invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
+ | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp2)
+ # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+ # compilers, which have integrated preprocessors. The correct option
+ # to use with these is +Maked; it writes dependencies to a file named
+ # 'foo.d', which lands next to the object file, wherever that
+ # happens to be.
+ # Much of this is similar to the tru64 case; see comments there.
+ set_dir_from "$object"
+ set_base_from "$object"
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir.libs/$base.d
+ "$@" -Wc,+Maked
+ else
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir$base.d
+ "$@" +Maked
+ fi
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile1" "$tmpdepfile2"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
+ # Add 'dependent.h:' lines.
+ sed -ne '2,${
+ s/^ *//
+ s/ \\*$//
+ s/$/:/
+ p
+ }' "$tmpdepfile" >> "$depfile"
+ else
+ make_dummy_depfile
+ fi
+ rm -f "$tmpdepfile" "$tmpdepfile2"
+ ;;
+
+tru64)
+ # The Tru64 compiler uses -MD to generate dependencies as a side
+ # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+ # dependencies in 'foo.d' instead, so we check for that too.
+ # Subdirectories are respected.
+ set_dir_from "$object"
+ set_base_from "$object"
+
+ if test "$libtool" = yes; then
+ # Libtool generates 2 separate objects for the 2 libraries. These
+ # two compilations output dependencies in $dir.libs/$base.o.d and
+ # in $dir$base.o.d. We have to check for both files, because
+ # one of the two compilations can be disabled. We should prefer
+ # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+ # automatically cleaned when .libs/ is deleted, while ignoring
+ # the former would cause a distcleancheck panic.
+ tmpdepfile1=$dir$base.o.d # libtool 1.5
+ tmpdepfile2=$dir.libs/$base.o.d # Likewise.
+ tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
+ "$@" -Wc,-MD
+ else
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir$base.d
+ tmpdepfile3=$dir$base.d
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ # Same post-processing that is required for AIX mode.
+ aix_post_process_depfile
+ ;;
+
+msvc7)
+ if test "$libtool" = yes; then
+ showIncludes=-Wc,-showIncludes
+ else
+ showIncludes=-showIncludes
+ fi
+ "$@" $showIncludes > "$tmpdepfile"
+ stat=$?
+ grep -v '^Note: including file: ' "$tmpdepfile"
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ # The first sed program below extracts the file names and escapes
+ # backslashes for cygpath. The second sed program outputs the file
+ # name when reading, but also accumulates all include files in the
+ # hold buffer in order to output them again at the end. This only
+ # works with sed implementations that can handle large buffers.
+ sed < "$tmpdepfile" -n '
+/^Note: including file: *\(.*\)/ {
+ s//\1/
+ s/\\/\\\\/g
+ p
+}' | $cygpath_u | sort -u | sed -n '
+s/ /\\ /g
+s/\(.*\)/'"$tab"'\1 \\/p
+s/.\(.*\) \\/\1:/
+H
+$ {
+ s/.*/'"$tab"'/
+ G
+ p
+}' >> "$depfile"
+ echo >> "$depfile" # make sure the fragment doesn't end with a backslash
+ rm -f "$tmpdepfile"
+ ;;
+
+msvc7msys)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+#nosideeffect)
+ # This comment above is used by automake to tell side-effect
+ # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove '-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ test -z "$dashmflag" && dashmflag=-M
+ # Require at least two characters before searching for ':'
+ # in the target name. This is to cope with DOS-style filenames:
+ # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
+ "$@" $dashmflag |
+ sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process this sed invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ tr ' ' "$nl" < "$tmpdepfile" \
+ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+ | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+dashXmstdout)
+ # This case only exists to satisfy depend.m4. It is never actually
+ # run, as this mode is specially recognized in the preamble.
+ exit 1
+ ;;
+
+makedepend)
+ "$@" || exit $?
+ # Remove any Libtool call
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+ # X makedepend
+ shift
+ cleared=no eat=no
+ for arg
+ do
+ case $cleared in
+ no)
+ set ""; shift
+ cleared=yes ;;
+ esac
+ if test $eat = yes; then
+ eat=no
+ continue
+ fi
+ case "$arg" in
+ -D*|-I*)
+ set fnord "$@" "$arg"; shift ;;
+ # Strip any option that makedepend may not understand. Remove
+ # the object too, otherwise makedepend will parse it as a source file.
+ -arch)
+ eat=yes ;;
+ -*|$object)
+ ;;
+ *)
+ set fnord "$@" "$arg"; shift ;;
+ esac
+ done
+ obj_suffix=`echo "$object" | sed 's/^.*\././'`
+ touch "$tmpdepfile"
+ ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+ rm -f "$depfile"
+ # makedepend may prepend the VPATH from the source file name to the object.
+ # No need to regex-escape $object, excess matching of '.' is harmless.
+ sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process the last invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ sed '1,2d' "$tmpdepfile" \
+ | tr ' ' "$nl" \
+ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+ | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
+ ;;
+
+cpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove '-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ "$@" -E \
+ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+ | sed '$ s: \\$::' > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ cat < "$tmpdepfile" >> "$depfile"
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvisualcpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ IFS=" "
+ for arg
+ do
+ case "$arg" in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+ set fnord "$@"
+ shift
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift
+ shift
+ ;;
+ esac
+ done
+ "$@" -E 2>/dev/null |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
+ echo "$tab" >> "$depfile"
+ sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvcmsys)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/deps/sljit/LICENSE b/deps/sljit/LICENSE
new file mode 100644
index 0000000..0aaecaa
--- /dev/null
+++ b/deps/sljit/LICENSE
@@ -0,0 +1,25 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/deps/sljit/README.md b/deps/sljit/README.md
new file mode 100644
index 0000000..ef44763
--- /dev/null
+++ b/deps/sljit/README.md
@@ -0,0 +1,74 @@
+
+
+# SLJIT
+
+Platform-independent low-level JIT compiler
+
+https://zherczeg.github.io/sljit/
+
+
+
+---
+
+## Purpose
+
+SLJIT is a low-level, platform-independent JIT compiler, which is very well suited for translating bytecode into machine code.
+
+## Features
+
+- Supports a variety of target architectures:
+ - `x86` 32 / 64
+ - `ARM` 32 / 64
+ - `RISC-V` 32 / 64
+ - `s390x` 64
+ - `PowerPC` 32 / 64
+ - `LoongArch` 64
+ - `MIPS` 32 / 64
+- Supports a large number of operations
+ - Self-modifying code
+ - Tail calls
+ - Fast calls
+ - Byte order reverse (endianness switching)
+ - Unaligned memory accesses
+ - SIMD
+ - Atomic operations
+- Allows direct access to registers (both integer and floating point)
+- Supports stack space allocation for function local variables
+- Supports all-in-one compilation
+ - Allows SLJIT's API to be completely hidden from external use
+- Allows serializing the compiler into a byte buffer
+ - Useful for ahead-of-time (AOT) compilation
+ - Code generation can be resumed after deserialization (partial AOT compilation)
+
+## Documentation
+
+The primary source of documentation is [`sljitLir.h`](./sljit_src/sljitLir.h).
+
+Additional documentation can be found on [SLJIT's website](https://zherczeg.github.io/sljit/), as well as in the [`docs` folder](./docs/).
+
+## Contact
+
+Either open an [issue](https://github.com/zherczeg/sljit/issues) or write an email to hzmester@freemail.hu.
+
+## License
+
+SLJIT is licensed under the [Simplified BSD License](./LICENSE).
+
+## Special Thanks
+
+- Alexander Nasonov
+- Carlo Marcelo Arenas Belón
+- Christian Persch
+- Daniel Richard G.
+- Giuseppe D'Angelo
+- H.J. Lu
+- James Cowgill
+- Jason Hood
+- Jiong Wang (*TileGX support*)
+- Marc Mutz
+- Martin Storsjö
+- Michael McConville
+- Mingtao Zhou (*LoongArch support*)
+- Walter Lee
+- Wen Xichang
+- YunQiang Su
diff --git a/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c b/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c
new file mode 100644
index 0000000..9bd2094
--- /dev/null
+++ b/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorApple.c
@@ -0,0 +1,137 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+#include
+/*
+ On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a
+ version where it's OK to have more than one JIT block or where MAP_JIT is
+ required.
+ On non-macOS systems, returns MAP_JIT if it is defined.
+*/
+#include
+
+#if (defined(TARGET_OS_OSX) && TARGET_OS_OSX) || (TARGET_OS_MAC && !TARGET_OS_IPHONE)
+
+#if defined(SLJIT_CONFIG_X86) && SLJIT_CONFIG_X86
+
+#include
+#include
+
+#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
+
+#ifdef MAP_JIT
+#define SLJIT_MAP_JIT (get_map_jit_flag())
+static SLJIT_INLINE int get_map_jit_flag(void)
+{
+ size_t page_size;
+ void *ptr;
+ struct utsname name;
+ static int map_jit_flag = -1;
+
+ if (map_jit_flag < 0) {
+ map_jit_flag = 0;
+ uname(&name);
+
+ /* Kernel version for 10.14.0 (Mojave) or later */
+ if (atoi(name.release) >= 18) {
+ page_size = get_page_alignment() + 1;
+ /* Only use MAP_JIT if a hardened runtime is used */
+ ptr = mmap(NULL, page_size, PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON, -1, 0);
+
+ if (ptr != MAP_FAILED)
+ munmap(ptr, page_size);
+ else
+ map_jit_flag = MAP_JIT;
+ }
+ }
+ return map_jit_flag;
+}
+#else /* !defined(MAP_JIT) */
+#define SLJIT_MAP_JIT (0)
+#endif
+
+#elif defined(SLJIT_CONFIG_ARM) && SLJIT_CONFIG_ARM
+
+#include
+#include
+
+#define SLJIT_MAP_JIT (MAP_JIT)
+#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \
+ apple_update_wx_flags(enable_exec)
+
+static SLJIT_INLINE void apple_update_wx_flags(sljit_s32 enable_exec)
+{
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 110000
+ if (__builtin_available(macos 11, *))
+#endif /* BigSur */
+ pthread_jit_write_protect_np(enable_exec);
+}
+
+#elif defined(SLJIT_CONFIG_PPC) && SLJIT_CONFIG_PPC
+
+#define SLJIT_MAP_JIT (0)
+#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
+
+#else
+#error "Unsupported architecture"
+#endif /* SLJIT_CONFIG */
+
+#else /* !TARGET_OS_OSX */
+
+#ifdef MAP_JIT
+#define SLJIT_MAP_JIT (MAP_JIT)
+#else
+#define SLJIT_MAP_JIT (0)
+#endif
+
+#endif /* TARGET_OS_OSX */
+
+static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
+{
+ void *retval;
+ int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
+ int flags = MAP_PRIVATE;
+ int fd = -1;
+
+ flags |= MAP_ANON | SLJIT_MAP_JIT;
+
+ retval = mmap(NULL, size, prot, flags, fd, 0);
+ if (retval == MAP_FAILED)
+ return NULL;
+
+ SLJIT_UPDATE_WX_FLAGS(retval, (uint8_t *)retval + size, 0);
+
+ return retval;
+}
+
+static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
+{
+ munmap(chunk, size);
+}
+
+#include "sljitExecAllocatorCore.c"
diff --git a/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c b/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c
new file mode 100644
index 0000000..314483c
--- /dev/null
+++ b/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c
@@ -0,0 +1,327 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ This file contains a simple executable memory allocator
+
+ It is assumed, that executable code blocks are usually medium (or sometimes
+ large) memory blocks, and the allocator is not too frequently called (less
+ optimized than other allocators). Thus, using it as a generic allocator is
+ not suggested.
+
+ How does it work:
+ Memory is allocated in continuous memory areas called chunks by alloc_chunk()
+ Chunk format:
+ [ block ][ block ] ... [ block ][ block terminator ]
+
+ All blocks and the block terminator is started with block_header. The block
+ header contains the size of the previous and the next block. These sizes
+ can also contain special values.
+ Block size:
+ 0 - The block is a free_block, with a different size member.
+ 1 - The block is a block terminator.
+ n - The block is used at the moment, and the value contains its size.
+ Previous block size:
+ 0 - This is the first block of the memory chunk.
+ n - The size of the previous block.
+
+ Using these size values we can go forward or backward on the block chain.
+ The unused blocks are stored in a chain list pointed by sljit_free_blocks.
+ This list is useful if we need to find a suitable memory area when the
+ allocator is called.
+
+ When a block is freed, the new free block is connected to its adjacent free
+ blocks if possible.
+
+ [ free block ][ used block ][ free block ]
+ and "used block" is freed, the three blocks are connected together:
+ [ one big free block ]
+*/
+
+/* Expected functions:
+ alloc_chunk / free_chunk :
+ * allocate executable system memory chunks
+ * the size is always divisible by CHUNK_SIZE
+ SLJIT_ALLOCATOR_LOCK / SLJIT_ALLOCATOR_UNLOCK :
+ * provided as part of sljitUtils
+ * only the allocator requires this lock, sljit is fully thread safe
+ as it only uses local variables
+
+ Supported defines:
+ SLJIT_HAS_CHUNK_HEADER - (optional) sljit_chunk_header is defined
+ SLJIT_HAS_EXECUTABLE_OFFSET - (optional) has executable offset data
+ SLJIT_UPDATE_WX_FLAGS - (optional) update WX flags
+*/
+
+#ifdef SLJIT_HAS_CHUNK_HEADER
+#define CHUNK_HEADER_SIZE (sizeof(struct sljit_chunk_header))
+#else /* !SLJIT_HAS_CHUNK_HEADER */
+#define CHUNK_HEADER_SIZE 0
+#endif /* SLJIT_HAS_CHUNK_HEADER */
+
+#ifndef SLJIT_UPDATE_WX_FLAGS
+#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
+#endif /* SLJIT_UPDATE_WX_FLAGS */
+
+#ifndef CHUNK_SIZE
+/* 64 KByte if not specified. */
+#define CHUNK_SIZE (sljit_uw)0x10000
+#endif /* CHUNK_SIZE */
+
+struct block_header {
+ sljit_uw size;
+ sljit_uw prev_size;
+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
+ sljit_sw executable_offset;
+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
+};
+
+struct free_block {
+ struct block_header header;
+ struct free_block *next;
+ struct free_block *prev;
+ sljit_uw size;
+};
+
+#define AS_BLOCK_HEADER(base, offset) \
+ ((struct block_header*)(((sljit_u8*)base) + offset))
+#define AS_FREE_BLOCK(base, offset) \
+ ((struct free_block*)(((sljit_u8*)base) + offset))
+#define MEM_START(base) ((void*)((base) + 1))
+#define CHUNK_MASK (~(CHUNK_SIZE - 1))
+#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7u) & ~(sljit_uw)7)
+#define CHUNK_EXTRA_SIZE (sizeof(struct block_header) + CHUNK_HEADER_SIZE)
+
+static struct free_block* sljit_free_blocks;
+static sljit_uw sljit_allocated_size;
+static sljit_uw sljit_total_size;
+
+static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size)
+{
+ free_block->header.size = 0;
+ free_block->size = size;
+
+ free_block->next = sljit_free_blocks;
+ free_block->prev = NULL;
+ if (sljit_free_blocks)
+ sljit_free_blocks->prev = free_block;
+ sljit_free_blocks = free_block;
+}
+
+static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block)
+{
+ if (free_block->next)
+ free_block->next->prev = free_block->prev;
+
+ if (free_block->prev)
+ free_block->prev->next = free_block->next;
+ else {
+ SLJIT_ASSERT(sljit_free_blocks == free_block);
+ sljit_free_blocks = free_block->next;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
+{
+ struct block_header *header;
+ struct block_header *next_header;
+ struct free_block *free_block;
+ sljit_uw chunk_size;
+
+#ifdef SLJIT_HAS_CHUNK_HEADER
+ struct sljit_chunk_header *chunk_header;
+#else /* !SLJIT_HAS_CHUNK_HEADER */
+ void *chunk_header;
+#endif /* SLJIT_HAS_CHUNK_HEADER */
+
+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
+ sljit_sw executable_offset;
+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
+
+ if (size < (64 - sizeof(struct block_header)))
+ size = (64 - sizeof(struct block_header));
+ size = ALIGN_SIZE(size);
+
+ SLJIT_ALLOCATOR_LOCK();
+ free_block = sljit_free_blocks;
+ while (free_block) {
+ if (free_block->size >= size) {
+ chunk_size = free_block->size;
+ SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);
+ if (chunk_size > size + 64) {
+ /* We just cut a block from the end of the free block. */
+ chunk_size -= size;
+ free_block->size = chunk_size;
+ header = AS_BLOCK_HEADER(free_block, chunk_size);
+ header->prev_size = chunk_size;
+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
+ header->executable_offset = free_block->header.executable_offset;
+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
+ AS_BLOCK_HEADER(header, size)->prev_size = size;
+ } else {
+ sljit_remove_free_block(free_block);
+ header = (struct block_header*)free_block;
+ size = chunk_size;
+ }
+ sljit_allocated_size += size;
+ header->size = size;
+ SLJIT_ALLOCATOR_UNLOCK();
+ return MEM_START(header);
+ }
+ free_block = free_block->next;
+ }
+
+ chunk_size = (size + CHUNK_EXTRA_SIZE + CHUNK_SIZE - 1) & CHUNK_MASK;
+
+ chunk_header = alloc_chunk(chunk_size);
+ if (!chunk_header) {
+ SLJIT_ALLOCATOR_UNLOCK();
+ return NULL;
+ }
+
+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
+ executable_offset = (sljit_sw)((sljit_u8*)chunk_header->executable - (sljit_u8*)chunk_header);
+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
+
+ chunk_size -= CHUNK_EXTRA_SIZE;
+ sljit_total_size += chunk_size;
+
+ header = (struct block_header*)(((sljit_u8*)chunk_header) + CHUNK_HEADER_SIZE);
+
+ header->prev_size = 0;
+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
+ header->executable_offset = executable_offset;
+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
+
+ if (chunk_size > size + 64) {
+ /* Cut the allocated space into a free and a used block. */
+ sljit_allocated_size += size;
+ header->size = size;
+ chunk_size -= size;
+
+ free_block = AS_FREE_BLOCK(header, size);
+ free_block->header.prev_size = size;
+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
+ free_block->header.executable_offset = executable_offset;
+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
+ sljit_insert_free_block(free_block, chunk_size);
+ next_header = AS_BLOCK_HEADER(free_block, chunk_size);
+ } else {
+ /* All space belongs to this allocation. */
+ sljit_allocated_size += chunk_size;
+ header->size = chunk_size;
+ next_header = AS_BLOCK_HEADER(header, chunk_size);
+ }
+ next_header->size = 1;
+ next_header->prev_size = chunk_size;
+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
+ next_header->executable_offset = executable_offset;
+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
+ SLJIT_ALLOCATOR_UNLOCK();
+ return MEM_START(header);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void *ptr)
+{
+ struct block_header *header;
+ struct free_block *free_block;
+
+ SLJIT_ALLOCATOR_LOCK();
+ header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header));
+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
+ header = AS_BLOCK_HEADER(header, -header->executable_offset);
+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
+ sljit_allocated_size -= header->size;
+
+ SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);
+
+ /* Connecting free blocks together if possible. */
+
+ /* If header->prev_size == 0, free_block will equal to header.
+ In this case, free_block->header.size will be > 0. */
+ free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size);
+ if (SLJIT_UNLIKELY(!free_block->header.size)) {
+ free_block->size += header->size;
+ header = AS_BLOCK_HEADER(free_block, free_block->size);
+ header->prev_size = free_block->size;
+ } else {
+ free_block = (struct free_block*)header;
+ sljit_insert_free_block(free_block, header->size);
+ }
+
+ header = AS_BLOCK_HEADER(free_block, free_block->size);
+ if (SLJIT_UNLIKELY(!header->size)) {
+ free_block->size += ((struct free_block*)header)->size;
+ sljit_remove_free_block((struct free_block*)header);
+ header = AS_BLOCK_HEADER(free_block, free_block->size);
+ header->prev_size = free_block->size;
+ }
+
+ /* The whole chunk is free. */
+ if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {
+ /* If this block is freed, we still have (sljit_allocated_size / 2) free space. */
+ if (sljit_total_size - free_block->size > (sljit_allocated_size * 3 / 2)) {
+ sljit_total_size -= free_block->size;
+ sljit_remove_free_block(free_block);
+ free_chunk(free_block, free_block->size + CHUNK_EXTRA_SIZE);
+ }
+ }
+
+ SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1);
+ SLJIT_ALLOCATOR_UNLOCK();
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
+{
+ struct free_block* free_block;
+ struct free_block* next_free_block;
+
+ SLJIT_ALLOCATOR_LOCK();
+ SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);
+
+ free_block = sljit_free_blocks;
+ while (free_block) {
+ next_free_block = free_block->next;
+ if (!free_block->header.prev_size &&
+ AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) {
+ sljit_total_size -= free_block->size;
+ sljit_remove_free_block(free_block);
+ free_chunk(free_block, free_block->size + CHUNK_EXTRA_SIZE);
+ }
+ free_block = next_free_block;
+ }
+
+ SLJIT_ASSERT(sljit_total_size || (!sljit_total_size && !sljit_free_blocks));
+ SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1);
+ SLJIT_ALLOCATOR_UNLOCK();
+}
+
+#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
+SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code)
+{
+ return ((struct block_header*)SLJIT_CODE_TO_PTR(code))[-1].executable_offset;
+}
+#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
diff --git a/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorFreeBSD.c b/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorFreeBSD.c
new file mode 100644
index 0000000..3b93a4d
--- /dev/null
+++ b/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorFreeBSD.c
@@ -0,0 +1,89 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+#include
+
+#ifdef PROC_WXMAP_CTL
+static SLJIT_INLINE int sljit_is_wx_block(void)
+{
+ static int wx_block = -1;
+ if (wx_block < 0) {
+ int sljit_wx_enable = PROC_WX_MAPPINGS_PERMIT;
+ wx_block = !!procctl(P_PID, 0, PROC_WXMAP_CTL, &sljit_wx_enable);
+ }
+ return wx_block;
+}
+
+#define SLJIT_IS_WX_BLOCK sljit_is_wx_block()
+#else /* !PROC_WXMAP_CTL */
+#define SLJIT_IS_WX_BLOCK (1)
+#endif /* PROC_WXMAP_CTL */
+
+static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
+{
+ void *retval;
+ int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
+ int flags = MAP_PRIVATE;
+ int fd = -1;
+
+#ifdef PROT_MAX
+ prot |= PROT_MAX(prot);
+#endif
+
+#ifdef MAP_ANON
+ flags |= MAP_ANON;
+#else /* !MAP_ANON */
+ if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero()))
+ return NULL;
+
+ fd = dev_zero;
+#endif /* MAP_ANON */
+
+retry:
+ retval = mmap(NULL, size, prot, flags, fd, 0);
+ if (retval == MAP_FAILED) {
+ if (!SLJIT_IS_WX_BLOCK)
+ goto retry;
+
+ return NULL;
+ }
+
+ /* HardenedBSD's mmap lies, so check permissions again. */
+ if (mprotect(retval, size, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) {
+ munmap(retval, size);
+ return NULL;
+ }
+
+ return retval;
+}
+
+static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
+{
+ munmap(chunk, size);
+}
+
+#include "sljitExecAllocatorCore.c"
diff --git a/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorPosix.c b/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorPosix.c
new file mode 100644
index 0000000..a775f56
--- /dev/null
+++ b/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorPosix.c
@@ -0,0 +1,62 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+#include
+
+static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
+{
+ void *retval;
+ int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
+ int flags = MAP_PRIVATE;
+ int fd = -1;
+
+#ifdef PROT_MAX
+ prot |= PROT_MAX(prot);
+#endif
+
+#ifdef MAP_ANON
+ flags |= MAP_ANON;
+#else /* !MAP_ANON */
+ if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero()))
+ return NULL;
+
+ fd = dev_zero;
+#endif /* MAP_ANON */
+
+ retval = mmap(NULL, size, prot, flags, fd, 0);
+ if (retval == MAP_FAILED)
+ return NULL;
+
+ return retval;
+}
+
+static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
+{
+ munmap(chunk, size);
+}
+
+#include "sljitExecAllocatorCore.c"
diff --git a/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorWindows.c b/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorWindows.c
new file mode 100644
index 0000000..f152a5a
--- /dev/null
+++ b/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorWindows.c
@@ -0,0 +1,40 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
+
+static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
+{
+ return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+}
+
+static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
+{
+ SLJIT_UNUSED_ARG(size);
+ VirtualFree(chunk, 0, MEM_RELEASE);
+}
+
+#include "sljitExecAllocatorCore.c"
diff --git a/deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorNetBSD.c b/deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorNetBSD.c
new file mode 100644
index 0000000..0b7fd57
--- /dev/null
+++ b/deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorNetBSD.c
@@ -0,0 +1,72 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define SLJIT_HAS_CHUNK_HEADER
+#define SLJIT_HAS_EXECUTABLE_OFFSET
+
+struct sljit_chunk_header {
+ void *executable;
+};
+
+/*
+ * MAP_REMAPDUP is a NetBSD extension available sinde 8.0, make sure to
+ * adjust your feature macros (ex: -D_NETBSD_SOURCE) as needed
+ */
+static SLJIT_INLINE struct sljit_chunk_header* alloc_chunk(sljit_uw size)
+{
+ struct sljit_chunk_header *retval;
+
+ retval = (struct sljit_chunk_header *)mmap(NULL, size,
+ PROT_READ | PROT_WRITE | PROT_MPROTECT(PROT_EXEC),
+ MAP_ANON | MAP_SHARED, -1, 0);
+
+ if (retval == MAP_FAILED)
+ return NULL;
+
+ retval->executable = mremap(retval, size, NULL, size, MAP_REMAPDUP);
+ if (retval->executable == MAP_FAILED) {
+ munmap((void *)retval, size);
+ return NULL;
+ }
+
+ if (mprotect(retval->executable, size, PROT_READ | PROT_EXEC) == -1) {
+ munmap(retval->executable, size);
+ munmap((void *)retval, size);
+ return NULL;
+ }
+
+ return retval;
+}
+
+static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
+{
+ struct sljit_chunk_header *header = ((struct sljit_chunk_header *)chunk) - 1;
+
+ munmap(header->executable, size);
+ munmap((void *)header, size);
+}
+
+#include "sljitExecAllocatorCore.c"
diff --git a/deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorPosix.c b/deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorPosix.c
new file mode 100644
index 0000000..f7cb6c5
--- /dev/null
+++ b/deps/sljit/sljit_src/allocator_src/sljitProtExecAllocatorPosix.c
@@ -0,0 +1,172 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define SLJIT_HAS_CHUNK_HEADER
+#define SLJIT_HAS_EXECUTABLE_OFFSET
+
+struct sljit_chunk_header {
+ void *executable;
+};
+
+#include
+#include
+#include
+#include
+
+#ifndef O_NOATIME
+#define O_NOATIME 0
+#endif
+
+/* this is a linux extension available since kernel 3.11 */
+#ifndef O_TMPFILE
+#define O_TMPFILE 0x404000
+#endif
+
+#ifndef _GNU_SOURCE
+char *secure_getenv(const char *name);
+int mkostemp(char *template, int flags);
+#endif
+
+static SLJIT_INLINE int create_tempfile(void)
+{
+ int fd;
+ char tmp_name[256];
+ size_t tmp_name_len = 0;
+ char *dir;
+ struct stat st;
+#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
+ mode_t mode;
+#endif
+
+#ifdef HAVE_MEMFD_CREATE
+ /* this is a GNU extension, make sure to use -D_GNU_SOURCE */
+ fd = memfd_create("sljit", MFD_CLOEXEC);
+ if (fd != -1) {
+ fchmod(fd, 0);
+ return fd;
+ }
+#endif
+
+ dir = secure_getenv("TMPDIR");
+
+ if (dir) {
+ size_t len = strlen(dir);
+ if (len > 0 && len < sizeof(tmp_name)) {
+ if ((stat(dir, &st) == 0) && S_ISDIR(st.st_mode)) {
+ memcpy(tmp_name, dir, len + 1);
+ tmp_name_len = len;
+ }
+ }
+ }
+
+#ifdef P_tmpdir
+ if (!tmp_name_len) {
+ tmp_name_len = strlen(P_tmpdir);
+ if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name))
+ strcpy(tmp_name, P_tmpdir);
+ }
+#endif
+ if (!tmp_name_len) {
+ strcpy(tmp_name, "/tmp");
+ tmp_name_len = 4;
+ }
+
+ SLJIT_ASSERT(tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name));
+
+ if (tmp_name_len > 1 && tmp_name[tmp_name_len - 1] == '/')
+ tmp_name[--tmp_name_len] = '\0';
+
+ fd = open(tmp_name, O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, 0);
+ if (fd != -1)
+ return fd;
+
+ if (tmp_name_len >= sizeof(tmp_name) - 7)
+ return -1;
+
+ strcpy(tmp_name + tmp_name_len, "/XXXXXX");
+#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
+ mode = umask(0777);
+#endif
+ fd = mkostemp(tmp_name, O_CLOEXEC | O_NOATIME);
+#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
+ umask(mode);
+#else
+ fchmod(fd, 0);
+#endif
+
+ if (fd == -1)
+ return -1;
+
+ if (unlink(tmp_name)) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+static SLJIT_INLINE struct sljit_chunk_header* alloc_chunk(sljit_uw size)
+{
+ struct sljit_chunk_header *retval;
+ int fd;
+
+ fd = create_tempfile();
+ if (fd == -1)
+ return NULL;
+
+ if (ftruncate(fd, (off_t)size)) {
+ close(fd);
+ return NULL;
+ }
+
+ retval = (struct sljit_chunk_header *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+
+ if (retval == MAP_FAILED) {
+ close(fd);
+ return NULL;
+ }
+
+ retval->executable = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);
+
+ if (retval->executable == MAP_FAILED) {
+ munmap((void *)retval, size);
+ close(fd);
+ return NULL;
+ }
+
+ close(fd);
+ return retval;
+}
+
+static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
+{
+ struct sljit_chunk_header *header = ((struct sljit_chunk_header *)chunk) - 1;
+
+ munmap(header->executable, size);
+ munmap((void *)header, size);
+}
+
+#include "sljitExecAllocatorCore.c"
diff --git a/deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorPosix.c b/deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorPosix.c
new file mode 100644
index 0000000..62f7371
--- /dev/null
+++ b/deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorPosix.c
@@ -0,0 +1,144 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ This file contains a simple W^X executable memory allocator
+
+ In *NIX, MAP_ANON is required (that is considered a feature) so make
+ sure to set the right availability macros for your system or the code
+ will fail to build.
+
+ If your system doesn't support mapping of anonymous pages (ex: IRIX) it
+ is also likely that it doesn't need this allocator and should be using
+ the standard one instead.
+
+ It allocates a separate map for each code block and may waste a lot of
+ memory, because whatever was requested, will be rounded up to the page
+ size (minimum 4KB, but could be even bigger).
+
+ It changes the page permissions (RW <-> RX) as needed and therefore, if you
+ will be updating the code after it has been generated, need to make sure to
+ block any concurrent execution, or could result in a SIGBUS, that could
+ even manifest itself at a different address than the one that was being
+ modified.
+
+ Only use if you are unable to use the regular allocator because of security
+ restrictions and adding exceptions to your application or the system are
+ not possible.
+*/
+
+#include
+#include
+
+#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \
+ sljit_update_wx_flags((from), (to), (enable_exec))
+
+#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
+#include
+#define SLJIT_SE_LOCK() pthread_mutex_lock(&se_lock)
+#define SLJIT_SE_UNLOCK() pthread_mutex_unlock(&se_lock)
+#else
+#define SLJIT_SE_LOCK()
+#define SLJIT_SE_UNLOCK()
+#endif /* !SLJIT_SINGLE_THREADED */
+
+#define SLJIT_WX_IS_BLOCK(ptr, size) generic_check_is_wx_block(ptr, size)
+
+static SLJIT_INLINE int generic_check_is_wx_block(void *ptr, sljit_uw size)
+{
+ if (SLJIT_LIKELY(!mprotect(ptr, size, PROT_EXEC)))
+ return !!mprotect(ptr, size, PROT_READ | PROT_WRITE);
+
+ return 1;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
+{
+#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
+ static pthread_mutex_t se_lock = PTHREAD_MUTEX_INITIALIZER;
+#endif
+ static int wx_block = -1;
+ int prot = PROT_READ | PROT_WRITE;
+ sljit_uw* ptr;
+
+ if (SLJIT_UNLIKELY(wx_block > 0))
+ return NULL;
+
+#ifdef PROT_MAX
+ prot |= PROT_MAX(PROT_READ | PROT_WRITE | PROT_EXEC);
+#endif
+#ifdef PROT_MPROTECT
+ prot |= PROT_MPROTECT(PROT_EXEC);
+#endif
+
+ size += sizeof(sljit_uw);
+ ptr = (sljit_uw*)mmap(NULL, size, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
+
+ if (ptr == MAP_FAILED)
+ return NULL;
+
+ if (SLJIT_UNLIKELY(wx_block < 0)) {
+ SLJIT_SE_LOCK();
+ wx_block = SLJIT_WX_IS_BLOCK(ptr, size);
+ SLJIT_SE_UNLOCK();
+ if (SLJIT_UNLIKELY(wx_block)) {
+ munmap((void *)ptr, size);
+ return NULL;
+ }
+ }
+
+ *ptr++ = size;
+ return ptr;
+}
+
+#undef SLJIT_SE_UNLOCK
+#undef SLJIT_SE_LOCK
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
+{
+ sljit_uw *start_ptr = ((sljit_uw*)ptr) - 1;
+ munmap((void*)start_ptr, *start_ptr);
+}
+
+static void sljit_update_wx_flags(void *from, void *to, int enable_exec)
+{
+ sljit_uw page_mask = (sljit_uw)get_page_alignment();
+ sljit_uw start = (sljit_uw)from;
+ sljit_uw end = (sljit_uw)to;
+ int prot = PROT_READ | (enable_exec ? PROT_EXEC : PROT_WRITE);
+
+ SLJIT_ASSERT(start < end);
+
+ start &= ~page_mask;
+ end = (end + page_mask) & ~page_mask;
+
+ mprotect((void*)start, end - start, prot);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
+{
+ /* This allocator does not keep unused memory for future allocations. */
+}
diff --git a/deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorWindows.c b/deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorWindows.c
new file mode 100644
index 0000000..a9553bd
--- /dev/null
+++ b/deps/sljit/sljit_src/allocator_src/sljitWXExecAllocatorWindows.c
@@ -0,0 +1,102 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ This file contains a simple W^X executable memory allocator
+
+ In *NIX, MAP_ANON is required (that is considered a feature) so make
+ sure to set the right availability macros for your system or the code
+ will fail to build.
+
+ If your system doesn't support mapping of anonymous pages (ex: IRIX) it
+ is also likely that it doesn't need this allocator and should be using
+ the standard one instead.
+
+ It allocates a separate map for each code block and may waste a lot of
+ memory, because whatever was requested, will be rounded up to the page
+ size (minimum 4KB, but could be even bigger).
+
+ It changes the page permissions (RW <-> RX) as needed and therefore, if you
+ will be updating the code after it has been generated, need to make sure to
+ block any concurrent execution, or could result in a SIGBUS, that could
+ even manifest itself at a different address than the one that was being
+ modified.
+
+ Only use if you are unable to use the regular allocator because of security
+ restrictions and adding exceptions to your application or the system are
+ not possible.
+*/
+
+#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \
+ sljit_update_wx_flags((from), (to), (enable_exec))
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
+{
+ sljit_uw *ptr;
+
+ size += sizeof(sljit_uw);
+ ptr = (sljit_uw*)VirtualAlloc(NULL, size,
+ MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+
+ if (!ptr)
+ return NULL;
+
+ *ptr++ = size;
+
+ return ptr;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
+{
+ sljit_uw start = (sljit_uw)ptr - sizeof(sljit_uw);
+#if defined(SLJIT_DEBUG) && SLJIT_DEBUG
+ sljit_uw page_mask = (sljit_uw)get_page_alignment();
+
+ SLJIT_ASSERT(!(start & page_mask));
+#endif
+ VirtualFree((void*)start, 0, MEM_RELEASE);
+}
+
+static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec)
+{
+ DWORD oldprot;
+ sljit_uw page_mask = (sljit_uw)get_page_alignment();
+ sljit_uw start = (sljit_uw)from;
+ sljit_uw end = (sljit_uw)to;
+ DWORD prot = enable_exec ? PAGE_EXECUTE : PAGE_READWRITE;
+
+ SLJIT_ASSERT(start < end);
+
+ start &= ~page_mask;
+ end = (end + page_mask) & ~page_mask;
+
+ VirtualProtect((void*)start, end - start, prot, &oldprot);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
+{
+ /* This allocator does not keep unused memory for future allocations. */
+}
diff --git a/deps/sljit/sljit_src/sljitConfig.h b/deps/sljit/sljit_src/sljitConfig.h
new file mode 100644
index 0000000..d43e8ae
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitConfig.h
@@ -0,0 +1,142 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SLJIT_CONFIG_H_
+#define SLJIT_CONFIG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ This file contains the basic configuration options for the SLJIT compiler
+ and their default values. These options can be overridden in the
+ sljitConfigPre.h header file when SLJIT_HAVE_CONFIG_PRE is set to a
+ non-zero value.
+*/
+
+/* --------------------------------------------------------------------- */
+/* Utilities */
+/* --------------------------------------------------------------------- */
+
+/* Implements a stack like data structure (by using mmap / VirtualAlloc */
+/* or a custom allocator). */
+#ifndef SLJIT_UTIL_STACK
+/* Enabled by default */
+#define SLJIT_UTIL_STACK 1
+#endif /* SLJIT_UTIL_STACK */
+
+/* Uses user provided allocator to allocate the stack (see SLJIT_UTIL_STACK) */
+#ifndef SLJIT_UTIL_SIMPLE_STACK_ALLOCATION
+/* Disabled by default */
+#define SLJIT_UTIL_SIMPLE_STACK_ALLOCATION 0
+#endif /* SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */
+
+/* Single threaded application. Does not require any locks. */
+#ifndef SLJIT_SINGLE_THREADED
+/* Disabled by default. */
+#define SLJIT_SINGLE_THREADED 0
+#endif /* SLJIT_SINGLE_THREADED */
+
+/* --------------------------------------------------------------------- */
+/* Configuration */
+/* --------------------------------------------------------------------- */
+
+/* If SLJIT_STD_MACROS_DEFINED is not defined, the application should
+ define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMCPY, and NULL. */
+#ifndef SLJIT_STD_MACROS_DEFINED
+/* Disabled by default. */
+#define SLJIT_STD_MACROS_DEFINED 0
+#endif /* SLJIT_STD_MACROS_DEFINED */
+
+/* Executable code allocation:
+ If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should
+ define SLJIT_MALLOC_EXEC and SLJIT_FREE_EXEC.
+ Optionally, depending on the implementation used for the allocator,
+ SLJIT_EXEC_OFFSET and SLJIT_UPDATE_WX_FLAGS might also be needed. */
+#ifndef SLJIT_EXECUTABLE_ALLOCATOR
+/* Enabled by default. */
+#define SLJIT_EXECUTABLE_ALLOCATOR 1
+
+/* When SLJIT_PROT_EXECUTABLE_ALLOCATOR is enabled SLJIT uses
+ an allocator which does not set writable and executable
+ permission flags at the same time.
+ Instead, it creates a shared memory segment (usually backed by a file)
+ and maps it twice, with different permissions, depending on the use
+ case.
+ The trade-off is increased use of virtual memory, incompatibility with
+ fork(), and some possible additional security risks by the use of
+ publicly accessible files for the generated code. */
+#ifndef SLJIT_PROT_EXECUTABLE_ALLOCATOR
+/* Disabled by default. */
+#define SLJIT_PROT_EXECUTABLE_ALLOCATOR 0
+#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */
+
+/* When SLJIT_WX_EXECUTABLE_ALLOCATOR is enabled SLJIT uses an
+ allocator which does not set writable and executable permission
+ flags at the same time.
+ Instead, it creates a new independent map on each invocation and
+ switches permissions at the underlying pages as needed.
+ The trade-off is increased memory use and degraded performance. */
+#ifndef SLJIT_WX_EXECUTABLE_ALLOCATOR
+/* Disabled by default. */
+#define SLJIT_WX_EXECUTABLE_ALLOCATOR 0
+#endif /* SLJIT_WX_EXECUTABLE_ALLOCATOR */
+
+#endif /* !SLJIT_EXECUTABLE_ALLOCATOR */
+
+/* Return with error when an invalid argument is passed. */
+#ifndef SLJIT_ARGUMENT_CHECKS
+/* Disabled by default */
+#define SLJIT_ARGUMENT_CHECKS 0
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+/* Debug checks (assertions, etc.). */
+#ifndef SLJIT_DEBUG
+/* Enabled by default */
+#define SLJIT_DEBUG 1
+#endif /* SLJIT_DEBUG */
+
+/* Verbose operations. */
+#ifndef SLJIT_VERBOSE
+/* Enabled by default */
+#define SLJIT_VERBOSE 1
+#endif /* SLJIT_VERBOSE */
+
+/*
+ SLJIT_IS_FPU_AVAILABLE
+ The availability of the FPU can be controlled by SLJIT_IS_FPU_AVAILABLE.
+ zero value - FPU is NOT present.
+ nonzero value - FPU is present.
+*/
+
+/* For further configurations, see sljitConfigCPU.h and sljitConfigInternal.h */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* SLJIT_CONFIG_H_ */
diff --git a/deps/sljit/sljit_src/sljitConfigCPU.h b/deps/sljit/sljit_src/sljitConfigCPU.h
new file mode 100644
index 0000000..a0d8d44
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitConfigCPU.h
@@ -0,0 +1,265 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SLJIT_CONFIG_CPU_H_
+#define SLJIT_CONFIG_CPU_H_
+
+/* --------------------------------------------------------------------- */
+/* Architecture */
+/* --------------------------------------------------------------------- */
+
+/* Architecture selection. */
+/* #define SLJIT_CONFIG_X86_32 1 */
+/* #define SLJIT_CONFIG_X86_64 1 */
+/* #define SLJIT_CONFIG_ARM_V6 1 */
+/* #define SLJIT_CONFIG_ARM_V7 1 */
+/* #define SLJIT_CONFIG_ARM_THUMB2 1 */
+/* #define SLJIT_CONFIG_ARM_64 1 */
+/* #define SLJIT_CONFIG_PPC_32 1 */
+/* #define SLJIT_CONFIG_PPC_64 1 */
+/* #define SLJIT_CONFIG_MIPS_32 1 */
+/* #define SLJIT_CONFIG_MIPS_64 1 */
+/* #define SLJIT_CONFIG_RISCV_32 1 */
+/* #define SLJIT_CONFIG_RISCV_64 1 */
+/* #define SLJIT_CONFIG_S390X 1 */
+/* #define SLJIT_CONFIG_LOONGARCH_64 */
+/* #define SLJIT_CONFIG_ALPHA_64 1 */
+
+/* #define SLJIT_CONFIG_AUTO 1 */
+/* #define SLJIT_CONFIG_UNSUPPORTED 1 */
+
+/*****************/
+/* Sanity check. */
+/*****************/
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
+ + (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
+ + (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) \
+ + (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
+ + (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
+ + (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
+ + (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
+ + (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
+ + (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
+ + (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
+ + (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \
+ + (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
+ + (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
+ + (defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64) \
+ + (defined SLJIT_CONFIG_ALPHA_64 && SLJIT_CONFIG_ALPHA_64) \
+ + (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
+ + (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2
+#error "Multiple architectures are selected"
+#endif
+
+#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
+ && !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
+ && !(defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) \
+ && !(defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
+ && !(defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
+ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
+ && !(defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
+ && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
+ && !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
+ && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
+ && !(defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \
+ && !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
+ && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
+ && !(defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64) \
+ && !(defined SLJIT_CONFIG_ALPHA_64 && SLJIT_CONFIG_ALPHA_64) \
+ && !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) \
+ && !(defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)
+#if defined SLJIT_CONFIG_AUTO && !SLJIT_CONFIG_AUTO
+#error "An architecture must be selected"
+#else /* SLJIT_CONFIG_AUTO */
+#define SLJIT_CONFIG_AUTO 1
+#endif /* !SLJIT_CONFIG_AUTO */
+#endif /* !SLJIT_CONFIG */
+
+/********************************************************/
+/* Automatic CPU detection (requires compiler support). */
+/********************************************************/
+
+#if (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)
+#ifndef _WIN32
+
+#if defined(__i386__) || defined(__i386)
+#define SLJIT_CONFIG_X86_32 1
+#elif defined(__x86_64__)
+#define SLJIT_CONFIG_X86_64 1
+#elif defined(__aarch64__)
+#define SLJIT_CONFIG_ARM_64 1
+#elif defined(__thumb2__)
+#define SLJIT_CONFIG_ARM_THUMB2 1
+#elif (defined(__ARM_ARCH) && __ARM_ARCH >= 7) || \
+ ((defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7S__)) \
+ || (defined(__ARM_ARCH_8A__) || defined(__ARM_ARCH_8R__)) \
+ || (defined(__ARM_ARCH_9A__)))
+#define SLJIT_CONFIG_ARM_V7 1
+#elif defined(__arm__) || defined (__ARM__)
+#define SLJIT_CONFIG_ARM_V6 1
+#elif defined(__ppc64__) || defined(__powerpc64__) || (defined(_ARCH_PPC64) && defined(__64BIT__)) || (defined(_POWER) && defined(__64BIT__))
+#define SLJIT_CONFIG_PPC_64 1
+#elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER)
+#define SLJIT_CONFIG_PPC_32 1
+#elif defined(__mips__) && !defined(_LP64)
+#define SLJIT_CONFIG_MIPS_32 1
+#elif defined(__mips64)
+#define SLJIT_CONFIG_MIPS_64 1
+#elif defined (__riscv_xlen) && (__riscv_xlen == 32)
+#define SLJIT_CONFIG_RISCV_32 1
+#elif defined (__riscv_xlen) && (__riscv_xlen == 64)
+#define SLJIT_CONFIG_RISCV_64 1
+#elif defined (__loongarch_lp64)
+#define SLJIT_CONFIG_LOONGARCH_64 1
+#elif defined(__s390x__)
+#define SLJIT_CONFIG_S390X 1
+#elif defined(__alpha__)
+#define SLJIT_CONFIG_ALPHA_64 1
+#else
+/* Unsupported architecture */
+#define SLJIT_CONFIG_UNSUPPORTED 1
+#endif
+
+#else /* _WIN32 */
+
+#if defined(_M_X64) || defined(__x86_64__)
+#define SLJIT_CONFIG_X86_64 1
+#elif (defined(_M_ARM) && _M_ARM >= 7 && defined(_M_ARMT)) || defined(__thumb2__)
+#define SLJIT_CONFIG_ARM_THUMB2 1
+#elif (defined(_M_ARM) && _M_ARM >= 7)
+#define SLJIT_CONFIG_ARM_V7 1
+#elif defined(_ARM_)
+#define SLJIT_CONFIG_ARM_V6 1
+#elif defined(_M_ARM64) || defined(__aarch64__)
+#define SLJIT_CONFIG_ARM_64 1
+#else
+#define SLJIT_CONFIG_X86_32 1
+#endif
+
+#endif /* !_WIN32 */
+#endif /* SLJIT_CONFIG_AUTO */
+
+#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
+#undef SLJIT_EXECUTABLE_ALLOCATOR
+#endif /* SLJIT_CONFIG_UNSUPPORTED */
+
+/******************************/
+/* CPU family type detection. */
+/******************************/
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
+ || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
+#define SLJIT_CONFIG_ARM_32 1
+#endif /* SLJIT_CONFIG_ARM_V6 || SLJIT_CONFIG_ARM_V7 || SLJIT_CONFIG_ARM_THUMB2 */
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+#define SLJIT_CONFIG_X86 1
+#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
+#define SLJIT_CONFIG_ARM 1
+#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#define SLJIT_CONFIG_PPC 1
+#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+#define SLJIT_CONFIG_MIPS 1
+#elif (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) || (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+#define SLJIT_CONFIG_RISCV 1
+#elif (defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64)
+#define SLJIT_CONFIG_LOONGARCH 1
+#elif (defined SLJIT_CONFIG_ALPHA_64 && SLJIT_CONFIG_ALPHA_64)
+#define SLJIT_CONFIG_ALPHA 1
+#endif
+
+/*************************/
+/* Endianness detection. */
+/*************************/
+
+#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)
+
+#if defined(SLJIT_CONFIG_ARM) && SLJIT_CONFIG_ARM
+
+#ifdef __ARM_BIG_ENDIAN
+#define SLJIT_BIG_ENDIAN 1
+#else
+#define SLJIT_LITTLE_ENDIAN 1
+#endif
+
+#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
+
+#ifdef __LITTLE_ENDIAN__
+#define SLJIT_LITTLE_ENDIAN 1
+#else
+#define SLJIT_BIG_ENDIAN 1
+#endif
+
+#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
+
+#ifdef __MIPSEL__
+#define SLJIT_LITTLE_ENDIAN 1
+#else
+#define SLJIT_BIG_ENDIAN 1
+#endif
+
+#ifndef SLJIT_MIPS_REV
+
+/* Auto detecting mips revision. */
+#if (defined __mips_isa_rev) && (__mips_isa_rev >= 6)
+#define SLJIT_MIPS_REV 6
+#elif defined(__mips_isa_rev) && __mips_isa_rev >= 1
+#define SLJIT_MIPS_REV __mips_isa_rev
+#elif defined(__clang__) \
+ && (defined(_MIPS_ARCH_OCTEON) || defined(_MIPS_ARCH_P5600))
+/* clang either forgets to define (clang-7) __mips_isa_rev at all
+ * or sets it to zero (clang-8,-9) for -march=octeon (MIPS64 R2+)
+ * and -march=p5600 (MIPS32 R5).
+ * It also sets the __mips macro to 64 or 32 for -mipsN when N <= 5
+ * (should be set to N exactly) so we cannot rely on this too.
+ */
+#define SLJIT_MIPS_REV 1
+#endif
+
+#endif /* !SLJIT_MIPS_REV */
+
+#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
+
+#define SLJIT_BIG_ENDIAN 1
+
+#else
+
+#define SLJIT_LITTLE_ENDIAN 1
+
+#endif
+
+#endif /* !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) */
+
+#if (defined(SLJIT_CONFIG_ARM_64) && SLJIT_CONFIG_ARM_64) \
+ && (defined(SLJIT_BIG_ENDIAN) && SLJIT_BIG_ENDIAN)
+
+#undef SLJIT_CONFIG_ARM_64
+#define SLJIT_CONFIG_UNSUPPORTED 1
+
+#endif
+
+#endif /* SLJIT_CONFIG_CPU_H_ */
diff --git a/deps/sljit/sljit_src/sljitConfigInternal.h b/deps/sljit/sljit_src/sljitConfigInternal.h
new file mode 100644
index 0000000..9c22234
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitConfigInternal.h
@@ -0,0 +1,1017 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SLJIT_CONFIG_INTERNAL_H_
+#define SLJIT_CONFIG_INTERNAL_H_
+
+/*
+ SLJIT defines the following architecture dependent types and macros:
+
+ Types:
+ sljit_s8, sljit_u8 : signed and unsigned 8 bit integer type
+ sljit_s16, sljit_u16 : signed and unsigned 16 bit integer type
+ sljit_s32, sljit_u32 : signed and unsigned 32 bit integer type
+ sljit_sw, sljit_uw : signed and unsigned machine word, enough to store a pointer
+ sljit_sp, sljit_up : signed and unsigned pointer value (usually the same as
+ sljit_uw, but some 64 bit ABIs may use 32 bit pointers)
+ sljit_f32 : 32 bit single precision floating point value
+ sljit_f64 : 64 bit double precision floating point value
+
+ Macros for feature detection (boolean):
+ SLJIT_32BIT_ARCHITECTURE : 32 bit architecture
+ SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
+ SLJIT_LITTLE_ENDIAN : little endian architecture
+ SLJIT_BIG_ENDIAN : big endian architecture
+ SLJIT_UNALIGNED : unaligned memory accesses for non-fpu operations are supported
+ SLJIT_FPU_UNALIGNED : unaligned memory accesses for fpu operations are supported
+ SLJIT_MASKED_SHIFT : all word shifts are always masked
+ SLJIT_MASKED_SHIFT32 : all 32 bit shifts are always masked
+ SLJIT_INDIRECT_CALL : see SLJIT_FUNC_ADDR() for more information
+ SLJIT_UPPER_BITS_IGNORED : 32 bit operations ignores the upper bits of source registers
+ SLJIT_UPPER_BITS_ZERO_EXTENDED : 32 bit operations clears the upper bits of destination registers
+ SLJIT_UPPER_BITS_SIGN_EXTENDED : 32 bit operations replicates the sign bit in the upper bits of destination registers
+ SLJIT_UPPER_BITS_PRESERVED : 32 bit operations preserves the upper bits of destination registers
+ SLJIT_SUBC_SETS_SIGNED : SLJIT_SUBC[32] operation always sets the signed result, so setting
+ the following status flags after a subtract with carry operation is valid:
+ sljit_set_current_flags(..., SLJIT_CURRENT_FLAGS_SUB | SLJIT_SET_SIG_LESS)
+ sljit_set_current_flags(..., SLJIT_CURRENT_FLAGS_SUB | SLJIT_SET_SIG_GREATER)
+ SLJIT_SHARED_COMPARISON_FLAGS: the cpu has different instructions for signed and unsigned
+ comparisons, which sets the same status flags, so passing SLJIT_LESS
+ or SLJIT_SIG_LESS as an argument has the same effect, and this is true
+ for all other signed/unsigned comparison type pairs
+
+ Constants:
+ SLJIT_NUMBER_OF_REGISTERS : number of available registers
+ SLJIT_NUMBER_OF_SCRATCH_REGISTERS : number of available scratch registers
+ SLJIT_NUMBER_OF_SAVED_REGISTERS : number of available saved registers
+ SLJIT_NUMBER_OF_FLOAT_REGISTERS : number of available floating point registers
+ SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS : number of available scratch floating point registers
+ SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS : number of available saved floating point registers
+ SLJIT_NUMBER_OF_VECTOR_REGISTERS : number of available vector registers
+ SLJIT_NUMBER_OF_SCRATCH_VECTOR_REGISTERS : number of available scratch vector registers
+ SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS : number of available saved vector registers
+ SLJIT_NUMBER_OF_TEMPORARY_REGISTERS : number of available temporary registers
+ SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS : number of available temporary floating point registers
+ SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS : number of available temporary vector registers
+ SLJIT_SEPARATE_VECTOR_REGISTERS : if this macro is defined, the vector registers do not
+ overlap with floating point registers
+ SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index
+ SLJIT_POINTER_SHIFT : the shift required to apply when accessing a sljit_sp/sljit_up array by index
+ SLJIT_F32_SHIFT : the shift required to apply when accessing
+ a single precision floating point array by index
+ SLJIT_F64_SHIFT : the shift required to apply when accessing
+ a double precision floating point array by index
+ SLJIT_PREF_SHIFT_REG : x86 systems prefers ecx for shifting by register
+ the scratch register index of ecx is stored in this variable
+ SLJIT_LOCALS_OFFSET : local space starting offset (SLJIT_SP + SLJIT_LOCALS_OFFSET)
+ SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address
+ SLJIT_CONV_MAX_FLOAT : result when a floating point value is converted to integer
+ and the floating point value is higher than the maximum integer value
+ (possible values: SLJIT_CONV_RESULT_MAX_INT or SLJIT_CONV_RESULT_MIN_INT)
+ SLJIT_CONV_MIN_FLOAT : result when a floating point value is converted to integer
+ and the floating point value is lower than the minimum integer value
+ (possible values: SLJIT_CONV_RESULT_MAX_INT or SLJIT_CONV_RESULT_MIN_INT)
+ SLJIT_CONV_NAN_FLOAT : result when a NaN floating point value is converted to integer
+ (possible values: SLJIT_CONV_RESULT_MAX_INT, SLJIT_CONV_RESULT_MIN_INT,
+ or SLJIT_CONV_RESULT_ZERO)
+
+ Other macros:
+ SLJIT_TMP_R0 .. R9 : accessing temporary registers
+ SLJIT_TMP_R(i) : accessing temporary registers
+ SLJIT_TMP_FR0 .. FR9 : accessing temporary floating point registers
+ SLJIT_TMP_FR(i) : accessing temporary floating point registers
+ SLJIT_TMP_VR0 .. VR9 : accessing temporary vector registers
+ SLJIT_TMP_VR(i) : accessing temporary vector registers
+ SLJIT_TMP_DEST_REG : a temporary register for results, see the rules below
+ SLJIT_TMP_DEST_FREG : a temporary register for float results, see the rules below
+ SLJIT_TMP_DEST_VREG : a temporary register for vector results, see the rules below
+ SLJIT_TMP_OPT_REG : an optional temporary register, see the rules below
+ SLJIT_TMP_FLAG_REG : an optional temporary register for storing the value of a flag
+ SLJIT_FUNC : calling convention attribute for both calling JIT from C and C calling back from JIT
+ SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (platform independent helper)
+ SLJIT_F64_SECOND(reg) : provides the register index of the second 32 bit part of a 64 bit
+ floating point register when SLJIT_HAS_F64_AS_F32_PAIR returns non-zero
+
+ Temporary register rules (e.g. SLJIT_TMP_DEST_REG / SLJIT_TMP_OPT_REG):
+ The sljit compiler avoids using temporary registers, but certain instruction
+ forms cannot be generated without them. The number of temporary registers
+ reserved by the compiler depends on the target architecture. An SLJIT_TMP_*
+ name is assigned to some of these registers, which represents their
+ SLJIT_TMP_R(i) index. When such register is optional, it might not be
+ defined on all architectures. For example, the x86-32 code generator does
+ not use any optional temporary registers.
+*/
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_DEBUG && SLJIT_DEBUG && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)))
+#include
+#endif
+
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG \
+ && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE) || !defined(SLJIT_HALT_PROCESS)))
+#include
+#endif
+
+#ifdef __APPLE__
+#include
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+#include
+#endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***********************************************************/
+/* Intel Control-flow Enforcement Technology (CET) spport. */
+/***********************************************************/
+
+#ifdef SLJIT_CONFIG_X86
+
+#if defined(__CET__) && !(defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)
+#define SLJIT_CONFIG_X86_CET 1
+#endif
+
+#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined(__GNUC__)
+#include
+#endif
+
+#endif /* SLJIT_CONFIG_X86 */
+
+/**********************************/
+/* External function definitions. */
+/**********************************/
+
+/* General macros:
+ Note: SLJIT is designed to be independent from them as possible.
+
+ In release mode (SLJIT_DEBUG is not defined) only the following
+ external functions are needed:
+*/
+
+#ifndef SLJIT_MALLOC
+#define SLJIT_MALLOC(size, allocator_data) (malloc(size))
+#endif
+
+#ifndef SLJIT_FREE
+#define SLJIT_FREE(ptr, allocator_data) (free(ptr))
+#endif
+
+#ifndef SLJIT_MEMCPY
+#define SLJIT_MEMCPY(dest, src, len) (memcpy(dest, src, len))
+#endif
+
+#ifndef SLJIT_MEMMOVE
+#define SLJIT_MEMMOVE(dest, src, len) (memmove(dest, src, len))
+#endif
+
+#ifndef SLJIT_ZEROMEM
+#define SLJIT_ZEROMEM(dest, len) (memset(dest, 0, len))
+#endif
+
+/***************************/
+/* Compiler helper macros. */
+/***************************/
+
+#if !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY)
+
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+#define SLJIT_LIKELY(x) __builtin_expect((x), 1)
+#define SLJIT_UNLIKELY(x) __builtin_expect((x), 0)
+#else
+#define SLJIT_LIKELY(x) (x)
+#define SLJIT_UNLIKELY(x) (x)
+#endif
+
+#endif /* !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY) */
+
+#ifndef SLJIT_INLINE
+/* Inline functions. Some old compilers do not support them. */
+#ifdef __SUNPRO_C
+#if __SUNPRO_C < 0x560
+#define SLJIT_INLINE
+#else
+#define SLJIT_INLINE inline
+#endif /* __SUNPRO_C */
+#else
+#define SLJIT_INLINE __inline
+#endif
+#endif /* !SLJIT_INLINE */
+
+#ifndef SLJIT_NOINLINE
+/* Not inline functions. */
+#if defined(__GNUC__)
+#define SLJIT_NOINLINE __attribute__ ((noinline))
+#else
+#define SLJIT_NOINLINE
+#endif
+#endif /* !SLJIT_INLINE */
+
+#ifndef SLJIT_UNUSED_ARG
+/* Unused arguments. */
+#define SLJIT_UNUSED_ARG(arg) (void)arg
+#endif
+
+/*********************************/
+/* Type of public API functions. */
+/*********************************/
+
+#ifndef SLJIT_API_FUNC_ATTRIBUTE
+#if (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC)
+/* Static ABI functions. For all-in-one programs. */
+
+#if defined(__GNUC__)
+/* Disable unused warnings in gcc. */
+#define SLJIT_API_FUNC_ATTRIBUTE static __attribute__((unused))
+#else
+#define SLJIT_API_FUNC_ATTRIBUTE static
+#endif
+
+#else
+#define SLJIT_API_FUNC_ATTRIBUTE
+#endif /* (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) */
+#endif /* defined SLJIT_API_FUNC_ATTRIBUTE */
+
+/****************************/
+/* Instruction cache flush. */
+/****************************/
+
+/*
+ * TODO:
+ *
+ * clang >= 15 could be safe to enable below
+ * older versions are known to abort in some targets
+ * https://github.com/PhilipHazel/pcre2/issues/92
+ *
+ * beware some vendors (ex: Microsoft, Apple) are known to have
+ * removed the code to support this builtin even if the call for
+ * __has_builtin reports it is available.
+ *
+ * make sure linking doesn't fail because __clear_cache() is
+ * missing before changing it or add an exception so that the
+ * system provided method that should be defined below is used
+ * instead.
+ */
+#if (!defined SLJIT_CACHE_FLUSH && defined __has_builtin)
+#if __has_builtin(__builtin___clear_cache) && !defined(__clang__)
+
+/*
+ * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=91248
+ * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=93811
+ * gcc's clear_cache builtin for power is broken
+ */
+#if !defined(SLJIT_CONFIG_PPC)
+#define SLJIT_CACHE_FLUSH(from, to) \
+ __builtin___clear_cache((char*)(from), (char*)(to))
+#endif
+
+#endif /* gcc >= 10 */
+#endif /* (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) */
+
+#ifndef SLJIT_CACHE_FLUSH
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
+ || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
+
+/* Not required to implement on archs with unified caches. */
+#define SLJIT_CACHE_FLUSH(from, to)
+
+#elif defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+
+/* Supported by all macs since Mac OS 10.5.
+ However, it does not work on non-jailbroken iOS devices,
+ although the compilation is successful. */
+#define SLJIT_CACHE_FLUSH(from, to) \
+ sys_icache_invalidate((void*)(from), (size_t)((char*)(to) - (char*)(from)))
+
+#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
+
+/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */
+#define SLJIT_CACHE_FLUSH(from, to) \
+ ppc_cache_flush((from), (to))
+#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
+
+#elif defined(_WIN32)
+
+#define SLJIT_CACHE_FLUSH(from, to) \
+ FlushInstructionCache(GetCurrentProcess(), (void*)(from), (size_t)((char*)(to) - (char*)(from)))
+
+#elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || defined(__clang__)
+
+#define SLJIT_CACHE_FLUSH(from, to) \
+ __builtin___clear_cache((char*)(from), (char*)(to))
+
+#elif defined __ANDROID__
+
+/* Android ARMv7 with gcc lacks __clear_cache; use cacheflush instead. */
+#include
+#define SLJIT_CACHE_FLUSH(from, to) \
+ cacheflush((long)(from), (long)(to), 0)
+
+#else
+
+/* Call __ARM_NR_cacheflush on ARM-Linux or the corresponding MIPS syscall. */
+#define SLJIT_CACHE_FLUSH(from, to) \
+ __clear_cache((char*)(from), (char*)(to))
+
+#endif
+
+#endif /* !SLJIT_CACHE_FLUSH */
+
+/******************************************************/
+/* Integer and floating point type definitions. */
+/******************************************************/
+
+/* 8 bit byte type. */
+typedef unsigned char sljit_u8;
+typedef signed char sljit_s8;
+
+/* 16 bit half-word type. */
+typedef unsigned short int sljit_u16;
+typedef signed short int sljit_s16;
+
+/* 32 bit integer type. */
+typedef unsigned int sljit_u32;
+typedef signed int sljit_s32;
+
+/* Machine word type. Enough for storing a pointer.
+ 32 bit for 32 bit machines.
+ 64 bit for 64 bit machines. */
+#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
+/* Just to have something. */
+#define SLJIT_WORD_SHIFT 0
+typedef unsigned int sljit_uw;
+typedef int sljit_sw;
+#elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
+ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
+ && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
+ && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
+ && !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
+ && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
+ && !(defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64) \
+ && !(defined SLJIT_CONFIG_ALPHA_64 && SLJIT_CONFIG_ALPHA_64)
+#define SLJIT_32BIT_ARCHITECTURE 1
+#define SLJIT_WORD_SHIFT 2
+typedef unsigned int sljit_uw;
+typedef int sljit_sw;
+#else
+#define SLJIT_64BIT_ARCHITECTURE 1
+#define SLJIT_WORD_SHIFT 3
+#ifdef _WIN32
+#ifdef __GNUC__
+/* These types do not require windows.h */
+typedef unsigned long long sljit_uw;
+typedef long long sljit_sw;
+#else
+typedef unsigned __int64 sljit_uw;
+typedef __int64 sljit_sw;
+#endif
+#else /* !_WIN32 */
+typedef unsigned long int sljit_uw;
+typedef long int sljit_sw;
+#endif /* _WIN32 */
+#endif
+
+typedef sljit_sw sljit_sp;
+typedef sljit_uw sljit_up;
+
+/* Floating point types. */
+typedef float sljit_f32;
+typedef double sljit_f64;
+
+/* Shift for pointer sized data. */
+#define SLJIT_POINTER_SHIFT SLJIT_WORD_SHIFT
+
+/* Shift for double precision sized data. */
+#define SLJIT_F32_SHIFT 2
+#define SLJIT_F64_SHIFT 3
+
+#define SLJIT_CONV_RESULT_MAX_INT 0
+#define SLJIT_CONV_RESULT_MIN_INT 1
+#define SLJIT_CONV_RESULT_ZERO 2
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MIN_INT
+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT
+#elif (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM)
+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_ZERO
+#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MAX_INT
+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MAX_INT
+#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT
+#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MAX_INT
+#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT
+#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_ZERO
+#elif (defined SLJIT_CONFIG_ALPHA && SLJIT_CONFIG_ALPHA)
+/* CVTTQ/SVC uses software completion; sljit_emit_fop1_conv_sw_from_f64
+ emits FCMPLT/CMPTEQ + CMOVNE/CMOVEQ fixups to enforce saturation. */
+#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
+#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
+#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_ZERO
+#else
+#error "Result for float to integer conversion is not defined"
+#endif
+
+#ifndef SLJIT_W
+
+/* Defining long constants. */
+#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
+#ifdef _WIN64
+#define SLJIT_W(w) (w##ll)
+#else /* !windows */
+#define SLJIT_W(w) (w##l)
+#endif /* windows */
+#else /* 32 bit */
+#define SLJIT_W(w) (w)
+#endif /* unknown */
+
+#endif /* !SLJIT_W */
+
+/*************************/
+/* Endianness detection. */
+/*************************/
+
+/* Sanity check. */
+#if (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
+#error "Exactly one endianness must be selected"
+#endif
+
+#if !(defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && !(defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
+#error "Exactly one endianness must be selected"
+#endif
+
+#ifndef SLJIT_UNALIGNED
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
+ || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
+ || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
+ || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
+ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
+ || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
+ || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
+ || (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
+#define SLJIT_UNALIGNED 1
+#endif
+
+#endif /* !SLJIT_UNALIGNED */
+
+#ifndef SLJIT_FPU_UNALIGNED
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
+ || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
+ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
+ || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
+ || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
+ || (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
+#define SLJIT_FPU_UNALIGNED 1
+#endif
+
+#endif /* !SLJIT_FPU_UNALIGNED */
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+/* Auto detect SSE2 support using CPUID.
+ On 64 bit x86 cpus, sse2 must be present. */
+#define SLJIT_DETECT_SSE2 1
+#endif
+
+/*****************************************************************************************/
+/* Calling convention of functions generated by SLJIT or called from the generated code. */
+/*****************************************************************************************/
+
+#ifndef SLJIT_FUNC
+#define SLJIT_FUNC
+#endif /* !SLJIT_FUNC */
+
+#ifndef SLJIT_INDIRECT_CALL
+#if ((defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) && (!defined _CALL_ELF || _CALL_ELF == 1)) \
+ || ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && defined _AIX)
+/* It seems certain ppc compilers use an indirect addressing for functions
+ which makes things complicated. */
+#define SLJIT_INDIRECT_CALL 1
+#endif
+#endif /* SLJIT_INDIRECT_CALL */
+
+/* The offset which needs to be subtracted from the return address to
+determine the next executed instruction after return. */
+#ifndef SLJIT_RETURN_ADDRESS_OFFSET
+#define SLJIT_RETURN_ADDRESS_OFFSET 0
+#endif /* SLJIT_RETURN_ADDRESS_OFFSET */
+
+/***************************************************/
+/* Functions of the built-in executable allocator. */
+/***************************************************/
+
+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size);
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);
+/* Note: sljitLir.h also defines sljit_free_unused_memory_exec() function. */
+#define SLJIT_BUILTIN_MALLOC_EXEC(size, exec_allocator_data) sljit_malloc_exec(size)
+#define SLJIT_BUILTIN_FREE_EXEC(ptr, exec_allocator_data) sljit_free_exec(ptr)
+
+#ifndef SLJIT_MALLOC_EXEC
+#define SLJIT_MALLOC_EXEC(size, exec_allocator_data) SLJIT_BUILTIN_MALLOC_EXEC((size), (exec_allocator_data))
+#endif /* SLJIT_MALLOC_EXEC */
+
+#ifndef SLJIT_FREE_EXEC
+#define SLJIT_FREE_EXEC(ptr, exec_allocator_data) SLJIT_BUILTIN_FREE_EXEC((ptr), (exec_allocator_data))
+#endif /* SLJIT_FREE_EXEC */
+
+#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
+SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code);
+#define SLJIT_EXEC_OFFSET(code) sljit_exec_offset(code)
+#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */
+
+#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
+
+#ifndef SLJIT_EXEC_OFFSET
+#define SLJIT_EXEC_OFFSET(ptr) 0
+#endif
+
+/**********************************************/
+/* Registers and locals offset determination. */
+/**********************************************/
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+
+#define SLJIT_NUMBER_OF_REGISTERS 12
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 1
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 7
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1
+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0
+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
+#define SLJIT_LOCALS_OFFSET_BASE (8 * (sljit_s32)sizeof(sljit_sw))
+#define SLJIT_PREF_SHIFT_REG SLJIT_R2
+#define SLJIT_MASKED_SHIFT 1
+#define SLJIT_MASKED_SHIFT32 1
+#define SLJIT_UPPER_BITS_IGNORED 1
+#define SLJIT_UPPER_BITS_ZERO_EXTENDED 1
+#define SLJIT_SUBC_SETS_SIGNED 1
+
+#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+
+#define SLJIT_NUMBER_OF_REGISTERS 13
+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 2
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 15
+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1
+#ifndef _WIN64
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 6
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
+#define SLJIT_LOCALS_OFFSET_BASE 0
+#else /* _WIN64 */
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 10
+#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw))
+#endif /* !_WIN64 */
+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R1
+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
+#define SLJIT_PREF_SHIFT_REG SLJIT_R3
+#define SLJIT_MASKED_SHIFT 1
+#define SLJIT_MASKED_SHIFT32 1
+#define SLJIT_UPPER_BITS_IGNORED 1
+#define SLJIT_UPPER_BITS_ZERO_EXTENDED 1
+#define SLJIT_SUBC_SETS_SIGNED 1
+
+#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)
+
+#define SLJIT_NUMBER_OF_REGISTERS 12
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 2
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R0
+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
+#define SLJIT_LOCALS_OFFSET_BASE 0
+#define SLJIT_SUBC_SETS_SIGNED 1
+
+#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
+
+#define SLJIT_NUMBER_OF_REGISTERS 26
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10
+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R1
+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
+#define SLJIT_LOCALS_OFFSET_BASE (2 * (sljit_s32)sizeof(sljit_sw))
+#define SLJIT_MASKED_SHIFT 1
+#define SLJIT_MASKED_SHIFT32 1
+#define SLJIT_UPPER_BITS_IGNORED 1
+#define SLJIT_UPPER_BITS_ZERO_EXTENDED 1
+#define SLJIT_SUBC_SETS_SIGNED 1
+
+#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
+
+#define SLJIT_NUMBER_OF_REGISTERS 23
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 17
+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 18
+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R0
+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined _AIX)
+#define SLJIT_LOCALS_OFFSET_BASE ((6 + 8) * (sljit_s32)sizeof(sljit_sw))
+#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+/* Add +1 for double alignment. */
+#define SLJIT_LOCALS_OFFSET_BASE ((3 + 1) * (sljit_s32)sizeof(sljit_sw))
+#else
+#define SLJIT_LOCALS_OFFSET_BASE (3 * (sljit_s32)sizeof(sljit_sw))
+#endif /* SLJIT_CONFIG_PPC_64 || _AIX */
+#define SLJIT_UPPER_BITS_IGNORED 1
+#define SLJIT_SHARED_COMPARISON_FLAGS 1
+
+#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
+
+#define SLJIT_NUMBER_OF_REGISTERS 21
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw))
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 13
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 6
+#else
+#define SLJIT_LOCALS_OFFSET_BASE 0
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 29
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
+#endif
+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5
+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 3
+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R0
+#define SLJIT_TMP_FLAG_REG SLJIT_TMP_R3
+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
+#define SLJIT_MASKED_SHIFT 1
+#define SLJIT_MASKED_SHIFT32 1
+#define SLJIT_UPPER_BITS_SIGN_EXTENDED 1
+#define SLJIT_SHARED_COMPARISON_FLAGS 1
+
+#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
+
+#define SLJIT_NUMBER_OF_REGISTERS 23
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 12
+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12
+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
+#define SLJIT_SEPARATE_VECTOR_REGISTERS 1
+#define SLJIT_NUMBER_OF_VECTOR_REGISTERS 30
+#define SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS 0
+#define SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS 2
+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R0
+#define SLJIT_TMP_FLAG_REG SLJIT_TMP_R3
+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
+#define SLJIT_TMP_DEST_VREG SLJIT_TMP_VR0
+#define SLJIT_LOCALS_OFFSET_BASE 0
+#define SLJIT_MASKED_SHIFT 1
+#define SLJIT_MASKED_SHIFT32 1
+#define SLJIT_UPPER_BITS_IGNORED 1
+#define SLJIT_UPPER_BITS_SIGN_EXTENDED 1
+#define SLJIT_SHARED_COMPARISON_FLAGS 1
+
+#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
+
+/*
+ * https://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html#STACKFRAME
+ *
+ * 160
+ * .. FR6
+ * .. FR4
+ * .. FR2
+ * 128 FR0
+ * 120 R15 (used for SP)
+ * 112 R14
+ * 104 R13
+ * 96 R12
+ * ..
+ * 48 R6
+ * ..
+ * 16 R2
+ * 8 RESERVED
+ * 0 SP
+ */
+#define SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE 160
+
+#define SLJIT_NUMBER_OF_REGISTERS 12
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 15
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1
+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R2
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R1
+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
+#define SLJIT_LOCALS_OFFSET_BASE SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE
+#define SLJIT_MASKED_SHIFT 1
+#define SLJIT_UPPER_BITS_IGNORED 1
+#define SLJIT_UPPER_BITS_PRESERVED 1
+#define SLJIT_SHARED_COMPARISON_FLAGS 1
+
+#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
+
+#define SLJIT_NUMBER_OF_REGISTERS 23
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10
+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12
+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R0
+#define SLJIT_TMP_FLAG_REG SLJIT_TMP_R3
+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
+#define SLJIT_LOCALS_OFFSET_BASE 0
+#define SLJIT_MASKED_SHIFT 1
+#define SLJIT_MASKED_SHIFT32 1
+#define SLJIT_UPPER_BITS_SIGN_EXTENDED 1
+#define SLJIT_SHARED_COMPARISON_FLAGS 1
+
+#elif (defined SLJIT_CONFIG_ALPHA && SLJIT_CONFIG_ALPHA)
+
+/* Alpha has 32 general registers (r31 hardwired zero) and 32 float registers
+ (f31 hardwired zero). Reserved: r31 (zero), r30 (sp), r29 (gp, unused by the
+ JIT). Backend temporaries: r24, r25, r26 (ra), r27 (pv), r28 (at). Exposed:
+ 17 scratch (r0-r8, r16-r23) + 7 callee-saved (r9-r15). */
+#define SLJIT_NUMBER_OF_REGISTERS 24
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 28
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R0
+#define SLJIT_TMP_FLAG_REG SLJIT_TMP_R3
+#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
+/* One word is reserved at the bottom of the frame: CPUs without the FIX
+ extension have no register to register move between the integer and float
+ register files, so values are bounced through this slot instead. */
+#define SLJIT_LOCALS_OFFSET_BASE ((sljit_s32)sizeof(sljit_sw))
+#define SLJIT_MASKED_SHIFT 1
+#define SLJIT_MASKED_SHIFT32 1
+#define SLJIT_UPPER_BITS_SIGN_EXTENDED 1
+#define SLJIT_SHARED_COMPARISON_FLAGS 1
+
+#elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
+
+/* Just to have something. */
+#define SLJIT_NUMBER_OF_REGISTERS 0
+#define SLJIT_NUMBER_OF_SAVED_REGISTERS 0
+#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 0
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 0
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
+#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 0
+#define SLJIT_TMP_DEST_REG 0
+#define SLJIT_TMP_DEST_FREG 0
+#define SLJIT_LOCALS_OFFSET_BASE 0
+
+#endif
+
+#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)
+#define SLJIT_NUMBER_OF_VECTOR_REGISTERS (SLJIT_NUMBER_OF_FLOAT_REGISTERS)
+#define SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS (SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS)
+#define SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS (SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)
+#define SLJIT_TMP_DEST_VREG (SLJIT_TMP_DEST_FREG)
+#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */
+
+#define SLJIT_LOCALS_OFFSET (SLJIT_LOCALS_OFFSET_BASE)
+
+#define SLJIT_NUMBER_OF_SCRATCH_REGISTERS \
+ (SLJIT_NUMBER_OF_REGISTERS - SLJIT_NUMBER_OF_SAVED_REGISTERS)
+
+#define SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS \
+ (SLJIT_NUMBER_OF_FLOAT_REGISTERS - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS)
+
+#define SLJIT_NUMBER_OF_SCRATCH_VECTOR_REGISTERS \
+ (SLJIT_NUMBER_OF_VECTOR_REGISTERS - SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS)
+
+#if (defined SLJIT_UPPER_BITS_ZERO_EXTENDED && SLJIT_UPPER_BITS_ZERO_EXTENDED) \
+ + (defined SLJIT_UPPER_BITS_SIGN_EXTENDED && SLJIT_UPPER_BITS_SIGN_EXTENDED) \
+ + (defined SLJIT_UPPER_BITS_PRESERVED && SLJIT_UPPER_BITS_PRESERVED) > 1
+#error "Invalid upper bits defintion"
+#endif
+
+#if (defined SLJIT_UPPER_BITS_PRESERVED && SLJIT_UPPER_BITS_PRESERVED) \
+ && !(defined SLJIT_UPPER_BITS_IGNORED && SLJIT_UPPER_BITS_IGNORED)
+#error "Upper bits preserved requires bits ignored"
+#endif
+
+/**********************************/
+/* Temporary register management. */
+/**********************************/
+
+#define SLJIT_TMP_REGISTER_BASE (SLJIT_NUMBER_OF_REGISTERS + 2)
+#define SLJIT_TMP_FREGISTER_BASE (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
+#define SLJIT_TMP_VREGISTER_BASE (SLJIT_NUMBER_OF_VECTOR_REGISTERS + 1)
+
+/* WARNING: Accessing temporary registers is not recommended, because they
+ are also used by the JIT compiler for various computations. Using them
+ might have any side effects including incorrect operations and crashes,
+ so use them at your own risk. The machine registers themselves might have
+ limitations, e.g. the r0 register on s390x / ppc cannot be used as
+ base address for memory operations. */
+
+/* Temporary registers */
+#define SLJIT_TMP_R0 (SLJIT_TMP_REGISTER_BASE + 0)
+#define SLJIT_TMP_R1 (SLJIT_TMP_REGISTER_BASE + 1)
+#define SLJIT_TMP_R2 (SLJIT_TMP_REGISTER_BASE + 2)
+#define SLJIT_TMP_R3 (SLJIT_TMP_REGISTER_BASE + 3)
+#define SLJIT_TMP_R4 (SLJIT_TMP_REGISTER_BASE + 4)
+#define SLJIT_TMP_R5 (SLJIT_TMP_REGISTER_BASE + 5)
+#define SLJIT_TMP_R6 (SLJIT_TMP_REGISTER_BASE + 6)
+#define SLJIT_TMP_R7 (SLJIT_TMP_REGISTER_BASE + 7)
+#define SLJIT_TMP_R8 (SLJIT_TMP_REGISTER_BASE + 8)
+#define SLJIT_TMP_R9 (SLJIT_TMP_REGISTER_BASE + 9)
+#define SLJIT_TMP_R(i) (SLJIT_TMP_REGISTER_BASE + (i))
+
+#define SLJIT_TMP_FR0 (SLJIT_TMP_FREGISTER_BASE + 0)
+#define SLJIT_TMP_FR1 (SLJIT_TMP_FREGISTER_BASE + 1)
+#define SLJIT_TMP_FR2 (SLJIT_TMP_FREGISTER_BASE + 2)
+#define SLJIT_TMP_FR3 (SLJIT_TMP_FREGISTER_BASE + 3)
+#define SLJIT_TMP_FR4 (SLJIT_TMP_FREGISTER_BASE + 4)
+#define SLJIT_TMP_FR5 (SLJIT_TMP_FREGISTER_BASE + 5)
+#define SLJIT_TMP_FR6 (SLJIT_TMP_FREGISTER_BASE + 6)
+#define SLJIT_TMP_FR7 (SLJIT_TMP_FREGISTER_BASE + 7)
+#define SLJIT_TMP_FR8 (SLJIT_TMP_FREGISTER_BASE + 8)
+#define SLJIT_TMP_FR9 (SLJIT_TMP_FREGISTER_BASE + 9)
+#define SLJIT_TMP_FR(i) (SLJIT_TMP_FREGISTER_BASE + (i))
+
+#define SLJIT_TMP_VR0 (SLJIT_TMP_VREGISTER_BASE + 0)
+#define SLJIT_TMP_VR1 (SLJIT_TMP_VREGISTER_BASE + 1)
+#define SLJIT_TMP_VR2 (SLJIT_TMP_VREGISTER_BASE + 2)
+#define SLJIT_TMP_VR3 (SLJIT_TMP_VREGISTER_BASE + 3)
+#define SLJIT_TMP_VR4 (SLJIT_TMP_VREGISTER_BASE + 4)
+#define SLJIT_TMP_VR5 (SLJIT_TMP_VREGISTER_BASE + 5)
+#define SLJIT_TMP_VR6 (SLJIT_TMP_VREGISTER_BASE + 6)
+#define SLJIT_TMP_VR7 (SLJIT_TMP_VREGISTER_BASE + 7)
+#define SLJIT_TMP_VR8 (SLJIT_TMP_VREGISTER_BASE + 8)
+#define SLJIT_TMP_VR9 (SLJIT_TMP_VREGISTER_BASE + 9)
+#define SLJIT_TMP_VR(i) (SLJIT_TMP_VREGISTER_BASE + (i))
+
+/********************************/
+/* CPU status flags management. */
+/********************************/
+
+#if (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
+ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
+ || (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
+ || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
+ || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
+ || (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH) \
+ || (defined SLJIT_CONFIG_ALPHA && SLJIT_CONFIG_ALPHA)
+#define SLJIT_HAS_STATUS_FLAGS_STATE 1
+#endif
+
+/***************************************/
+/* Floating point register management. */
+/***************************************/
+
+#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
+ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#define SLJIT_F64_SECOND(reg) \
+ ((reg) + SLJIT_FS0 + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)
+#else /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS_32 */
+#define SLJIT_F64_SECOND(reg) \
+ (reg)
+#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */
+
+/*************************************/
+/* Debug and verbose related macros. */
+/*************************************/
+
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+
+#if !defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)
+
+/* SLJIT_HALT_PROCESS must halt the process. */
+#ifndef SLJIT_HALT_PROCESS
+#define SLJIT_HALT_PROCESS() \
+ abort();
+#endif /* !SLJIT_HALT_PROCESS */
+
+#endif /* !SLJIT_ASSERT || !SLJIT_UNREACHABLE */
+
+/* Feel free to redefine these two macros. */
+#ifndef SLJIT_ASSERT
+
+#define SLJIT_ASSERT(x) \
+ do { \
+ if (SLJIT_UNLIKELY(!(x))) { \
+ printf("Assertion failed at " __FILE__ ":%d\n", __LINE__); \
+ SLJIT_HALT_PROCESS(); \
+ } \
+ } while (0)
+
+#endif /* !SLJIT_ASSERT */
+
+#ifndef SLJIT_UNREACHABLE
+
+#define SLJIT_UNREACHABLE() \
+ do { \
+ printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \
+ SLJIT_HALT_PROCESS(); \
+ } while (0)
+
+#endif /* !SLJIT_UNREACHABLE */
+
+#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
+
+/* Forcing empty, but valid statements. */
+#undef SLJIT_ASSERT
+#undef SLJIT_UNREACHABLE
+
+#define SLJIT_ASSERT(x) \
+ do { } while (0)
+#define SLJIT_UNREACHABLE() \
+ do { } while (0)
+
+#endif /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
+
+#ifndef SLJIT_COMPILE_ASSERT
+
+#define SLJIT_COMPILE_ASSERT(x, description) \
+ switch(0) { case 0: case ((x) ? 1 : 0): break; }
+
+#endif /* !SLJIT_COMPILE_ASSERT */
+
+#ifndef SLJIT_FALLTHROUGH
+
+#if defined(__cplusplus) && __cplusplus >= 202002L && \
+ defined(__has_cpp_attribute)
+/* Standards-compatible C++ variant. */
+#if __has_cpp_attribute(fallthrough)
+#define SLJIT_FALLTHROUGH [[fallthrough]];
+#endif
+#elif !defined(__cplusplus) && \
+ defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L && \
+ defined(__has_c_attribute)
+/* Standards-compatible C variant. */
+#if __has_c_attribute(fallthrough)
+#define SLJIT_FALLTHROUGH [[fallthrough]];
+#endif
+#elif ((defined(__clang__) && __clang_major__ >= 10) || \
+ (defined(__GNUC__) && __GNUC__ >= 7)) && \
+ defined(__has_attribute)
+/* Clang and GCC syntax. Rule out old versions because apparently Clang at
+ least has a broken implementation of __has_attribute. */
+#if __has_attribute(fallthrough)
+#define SLJIT_FALLTHROUGH __attribute__((fallthrough));
+#endif
+#endif
+
+#ifndef SLJIT_FALLTHROUGH
+#define SLJIT_FALLTHROUGH
+#endif
+
+#endif /* !SLJIT_FALLTHROUGH */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* SLJIT_CONFIG_INTERNAL_H_ */
diff --git a/deps/sljit/sljit_src/sljitLir.c b/deps/sljit/sljit_src/sljitLir.c
new file mode 100644
index 0000000..e8c77f8
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitLir.c
@@ -0,0 +1,3928 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "sljitLir.h"
+
+#ifdef _WIN32
+
+#include
+
+#endif /* _WIN32 */
+
+#if !(defined SLJIT_STD_MACROS_DEFINED && SLJIT_STD_MACROS_DEFINED)
+
+/* These libraries are needed for the macros below. */
+#include
+#include
+
+#endif /* SLJIT_STD_MACROS_DEFINED */
+
+#define CHECK_ERROR() \
+ do { \
+ if (SLJIT_UNLIKELY(compiler->error)) \
+ return compiler->error; \
+ } while (0)
+
+#define CHECK_ERROR_PTR() \
+ do { \
+ if (SLJIT_UNLIKELY(compiler->error)) \
+ return NULL; \
+ } while (0)
+
+#define FAIL_IF(expr) \
+ do { \
+ if (SLJIT_UNLIKELY(expr)) \
+ return compiler->error; \
+ } while (0)
+
+#define PTR_FAIL_IF(expr) \
+ do { \
+ if (SLJIT_UNLIKELY(expr)) \
+ return NULL; \
+ } while (0)
+
+#define FAIL_IF_NULL(ptr) \
+ do { \
+ if (SLJIT_UNLIKELY(!(ptr))) { \
+ compiler->error = SLJIT_ERR_ALLOC_FAILED; \
+ return SLJIT_ERR_ALLOC_FAILED; \
+ } \
+ } while (0)
+
+#define PTR_FAIL_IF_NULL(ptr) \
+ do { \
+ if (SLJIT_UNLIKELY(!(ptr))) { \
+ compiler->error = SLJIT_ERR_ALLOC_FAILED; \
+ return NULL; \
+ } \
+ } while (0)
+
+#define PTR_FAIL_WITH_EXEC_IF(ptr) \
+ do { \
+ if (SLJIT_UNLIKELY(!(ptr))) { \
+ compiler->error = SLJIT_ERR_EX_ALLOC_FAILED; \
+ return NULL; \
+ } \
+ } while (0)
+
+#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
+
+#define SSIZE_OF(type) ((sljit_s32)sizeof(sljit_ ## type))
+
+#define VARIABLE_FLAG_SHIFT (10)
+/* All variable flags are even. */
+#define VARIABLE_FLAG_MASK (0x3e << VARIABLE_FLAG_SHIFT)
+#define ALL_STATUS_FLAGS_MASK (VARIABLE_FLAG_MASK | SLJIT_SET_Z)
+#define GET_FLAG_TYPE(op) ((op) >> VARIABLE_FLAG_SHIFT)
+#define GET_FLAG_TYPE_MASK(op) (((op) >> VARIABLE_FLAG_SHIFT) & 0x3e)
+#define GET_OPCODE(op) ((op) & 0xff)
+#define HAS_FLAGS(op) ((op) & ALL_STATUS_FLAGS_MASK)
+#define GET_ALL_FLAGS(op) ((op) & (SLJIT_32 | ALL_STATUS_FLAGS_MASK))
+
+#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
+#define TYPE_CAST_NEEDED(op) \
+ ((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S32)
+#else /* !SLJIT_64BIT_ARCHITECTURE */
+#define TYPE_CAST_NEEDED(op) \
+ ((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16)
+#endif /* SLJIT_64BIT_ARCHITECTURE */
+
+#define BUF_SIZE 4096
+
+#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
+#define ABUF_SIZE 2048
+#else /* !SLJIT_32BIT_ARCHITECTURE */
+#define ABUF_SIZE 4096
+#endif /* SLJIT_32BIT_ARCHITECTURE */
+
+/* Parameter parsing. */
+#define REG_MASK 0x7f
+#define OFFS_REG(reg) (((reg) >> 8) & REG_MASK)
+#define OFFS_REG_MASK (REG_MASK << 8)
+#define TO_OFFS_REG(reg) ((reg) << 8)
+#define FAST_IS_REG(reg) ((reg) < REG_MASK)
+
+/* Mask for argument types. */
+#define SLJIT_ARG_MASK 0x7
+#define SLJIT_ARG_FULL_MASK (SLJIT_ARG_MASK | SLJIT_ARG_TYPE_SCRATCH_REG)
+
+/* Mask for register pairs. */
+#define REG_PAIR_MASK 0x7f00
+#define REG_PAIR_FIRST(reg) ((reg) & 0x7f)
+#define REG_PAIR_SECOND(reg) ((reg) >> 8)
+
+/* Mask for sljit_emit_enter. */
+#define ENTER_GET_REGS(regs) ((regs) & 0xff)
+#define ENTER_GET_FLOAT_REGS(regs) (((regs) >> 8) & 0xff)
+#define ENTER_GET_VECTOR_REGS(regs) (((regs) >> 16) & 0xff)
+#define SLJIT_KEPT_SAVEDS_COUNT(options) ((options) & 0x3)
+
+/* Getters for simd operations, which returns with log2(size). */
+#define SLJIT_SIMD_GET_OPCODE(type) ((type) & 0xff)
+#define SLJIT_SIMD_GET_REG_SIZE(type) (((type) >> 12) & 0x3f)
+#define SLJIT_SIMD_GET_ELEM_SIZE(type) (((type) >> 18) & 0x3f)
+#define SLJIT_SIMD_GET_ELEM2_SIZE(type) (((type) >> 24) & 0x3f)
+
+#define SLJIT_SIMD_CHECK_REG(type) (((type) & 0x3f000) >= SLJIT_SIMD_REG_64 && ((type) & 0x3f000) <= SLJIT_SIMD_REG_512)
+#define SLJIT_SIMD_TYPE_MASK(m) ((sljit_s32)0xff000fff & ~(SLJIT_SIMD_FLOAT | SLJIT_SIMD_TEST | (m)))
+#define SLJIT_SIMD_TYPE_MASK2(m) ((sljit_s32)0xc0000fff & ~(SLJIT_SIMD_FLOAT | SLJIT_SIMD_TEST | (m)))
+
+/* Label definitions. */
+
+#define SLJIT_LABEL_ALIGNED ((~(sljit_uw)0) - 1)
+
+struct sljit_extended_label {
+ struct sljit_label label;
+ sljit_uw index;
+ sljit_uw data;
+};
+
+/* Jump definitions. */
+
+/* Jump flag bits. */
+#define JUMP_ADDR 0x1
+#define JUMP_MOV_ADDR 0x2
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+# define PATCH_MB 0x04
+# define PATCH_MW 0x08
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+# define PATCH_MD 0x10
+# define MOV_ADDR_HI 0x20
+# define JUMP_MAX_SIZE ((sljit_uw)(10 + 3))
+# define CJUMP_MAX_SIZE ((sljit_uw)(2 + 10 + 3))
+#else /* !SLJIT_CONFIG_X86_64 */
+# define JUMP_MAX_SIZE ((sljit_uw)5)
+# define CJUMP_MAX_SIZE ((sljit_uw)6)
+#endif /* SLJIT_CONFIG_X86_64 */
+# define TYPE_SHIFT 17
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+/* Bits 7..15 is for debug jump size, SLJIT_REWRITABLE_JUMP is 0x10000 */
+# define JUMP_SIZE_SHIFT 8
+#endif /* SLJIT_DEBUG */
+#endif /* SLJIT_CONFIG_X86 */
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
+# define IS_BL 0x04
+# define PATCH_B 0x08
+#endif /* SLJIT_CONFIG_ARM_V6 || SLJIT_CONFIG_ARM_V7 */
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+# define CPOOL_SIZE 512
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+# define JUMP_SIZE_SHIFT 26
+# define JUMP_MAX_SIZE ((sljit_uw)3)
+#endif /* SLJIT_CONFIG_ARM_V7 */
+
+#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
+# define IS_COND 0x04
+# define IS_BL 0x08
+ /* mov_addr does not use IS_BL */
+# define IS_ABS IS_BL
+ /* conditional + imm8 */
+# define PATCH_TYPE1 0x10
+ /* conditional + imm20 */
+# define PATCH_TYPE2 0x20
+ /* imm11 */
+# define PATCH_TYPE3 0x30
+ /* imm24 */
+# define PATCH_TYPE4 0x40
+ /* BL + imm24 */
+# define PATCH_TYPE5 0x50
+ /* addwi/subwi */
+# define PATCH_TYPE6 0x60
+ /* 0xf00 cc code for branches */
+# define JUMP_SIZE_SHIFT 26
+# define JUMP_MAX_SIZE ((sljit_uw)5)
+#endif /* SLJIT_CONFIG_ARM_THUMB2 */
+
+#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
+# define IS_COND 0x004
+# define IS_CBZ 0x008
+# define IS_BL 0x010
+# define PATCH_COND 0x020
+# define PATCH_B 0x040
+# define PATCH_B32 0x080
+# define PATCH_ABS48 0x100
+# define PATCH_ABS64 0x200
+# define JUMP_SIZE_SHIFT 58
+# define JUMP_MAX_SIZE ((sljit_uw)5)
+#endif /* SLJIT_CONFIG_ARM_64 */
+
+#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
+# define IS_COND 0x004
+# define IS_CALL 0x008
+# define PATCH_B 0x010
+# define PATCH_ABS_B 0x020
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+# define PATCH_ABS32 0x040
+# define PATCH_ABS48 0x080
+# define JUMP_SIZE_SHIFT 58
+# define JUMP_MAX_SIZE ((sljit_uw)7)
+#else /* !SLJIT_CONFIG_PPC_64 */
+# define JUMP_SIZE_SHIFT 26
+# define JUMP_MAX_SIZE ((sljit_uw)4)
+#endif /* SLJIT_CONFIG_PPC_64 */
+#endif /* SLJIT_CONFIG_PPC */
+
+#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
+# define IS_MOVABLE 0x004
+# define IS_JAL 0x008
+# define IS_CALL 0x010
+# define IS_BIT26_COND 0x020
+# define IS_BIT16_COND 0x040
+# define IS_BIT23_COND 0x080
+
+# define IS_COND (IS_BIT26_COND | IS_BIT16_COND | IS_BIT23_COND)
+
+# define PATCH_B 0x100
+# define PATCH_J 0x200
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+# define PATCH_ABS32 0x400
+# define PATCH_ABS48 0x800
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+ /* instruction types */
+# define MOVABLE_INS 0
+ /* 1 - 31 last destination register */
+ /* no destination (i.e: store) */
+# define UNMOVABLE_INS 32
+ /* FPU status register */
+# define FCSR_FCC 33
+#endif /* SLJIT_CONFIG_MIPS */
+
+#if (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
+# define IS_COND 0x0004
+# define IS_CALL 0x0008
+
+# define IS_COND16 0x0010
+# define PATCH_B 0x0020
+# define PATCH_J 0x0040
+# define PATCH_16 0x0080
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+# define PATCH_REL32 0x0100
+# define PATCH_ABS32 0x0200
+# define PATCH_ABS44 0x0400
+# define PATCH_ABS52 0x0800
+# define JUMP_SIZE_SHIFT 58
+# define JUMP_MAX_SIZE ((sljit_uw)12)
+#else /* !SLJIT_CONFIG_RISCV_64 */
+# define JUMP_SIZE_SHIFT 26
+# define JUMP_MAX_SIZE ((sljit_uw)4)
+#endif /* SLJIT_CONFIG_RISCV_64 */
+#endif /* SLJIT_CONFIG_RISCV */
+
+#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
+# define PATCH_POOL 0x004
+# define PATCH_IMM32 0x008
+#endif /* SLJIT_CONFIG_S390X */
+
+#if (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
+# define IS_COND 0x004
+# define IS_CALL 0x008
+
+# define PATCH_B 0x010
+# define PATCH_J 0x020
+
+# define PATCH_REL32 0x040
+# define PATCH_ABS32 0x080
+# define PATCH_ABS52 0x100
+# define JUMP_SIZE_SHIFT 58
+# define JUMP_MAX_SIZE ((sljit_uw)4)
+
+#endif /* SLJIT_CONFIG_LOONGARCH */
+
+/* Stack management. */
+
+#define GET_SAVED_REGISTERS_SIZE(scratches, saveds, extra) \
+ (((scratches < SLJIT_NUMBER_OF_SCRATCH_REGISTERS ? 0 : (scratches - SLJIT_NUMBER_OF_SCRATCH_REGISTERS)) + \
+ (saveds) + (sljit_s32)(extra)) * (sljit_s32)sizeof(sljit_sw))
+
+#define GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, type) \
+ (((fscratches < SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS ? 0 : (fscratches - SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS)) + \
+ (fsaveds)) * SSIZE_OF(type))
+
+#define ADJUST_LOCAL_OFFSET(p, i) \
+ if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
+ (i) += SLJIT_LOCALS_OFFSET;
+
+#endif /* !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) */
+
+/* Utils can still be used even if SLJIT_CONFIG_UNSUPPORTED is set. */
+#include "sljitUtils.c"
+
+#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
+#define SLJIT_CODE_TO_PTR(code) ((void*)((sljit_up)(code) & ~(sljit_up)0x1))
+#elif (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+#define SLJIT_CODE_TO_PTR(code) ((void*)(*(sljit_up*)code))
+#else /* !SLJIT_CONFIG_ARM_THUMB2 && !SLJIT_INDIRECT_CALL */
+#define SLJIT_CODE_TO_PTR(code) ((void*)(code))
+#endif /* SLJIT_CONFIG_ARM_THUMB2 || SLJIT_INDIRECT_CALL */
+
+#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
+
+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
+
+#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
+
+#if defined(__NetBSD__)
+#include "allocator_src/sljitProtExecAllocatorNetBSD.c"
+#else /* !__NetBSD__ */
+#include "allocator_src/sljitProtExecAllocatorPosix.c"
+#endif /* __NetBSD__ */
+
+#elif (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)
+
+#if defined(_WIN32)
+#include "allocator_src/sljitWXExecAllocatorWindows.c"
+#else /* !_WIN32 */
+#include "allocator_src/sljitWXExecAllocatorPosix.c"
+#endif /* _WIN32 */
+
+#else /* !SLJIT_PROT_EXECUTABLAE_ALLOCATOR && !SLJIT_WX_EXECUTABLE_ALLOCATOR */
+
+#if defined(_WIN32)
+#include "allocator_src/sljitExecAllocatorWindows.c"
+#elif defined(__APPLE__)
+#include "allocator_src/sljitExecAllocatorApple.c"
+#elif defined(__FreeBSD__)
+#include "allocator_src/sljitExecAllocatorFreeBSD.c"
+#else /* !_WIN32 && !__APPLE__ && !__FreeBSD__ */
+#include "allocator_src/sljitExecAllocatorPosix.c"
+#endif /* _WIN32 */
+
+#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */
+
+#else /* !SLJIT_EXECUTABLE_ALLOCATOR */
+
+#ifndef SLJIT_UPDATE_WX_FLAGS
+#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
+#endif /* SLJIT_UPDATE_WX_FLAGS */
+
+#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
+
+#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
+#define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr) + (exec_offset))
+#else /* !SLJIT_PROT_EXECUTABLE_ALLOCATOR */
+#define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr))
+#endif /* SLJIT_PROT_EXECUTABLE_ALLOCATOR */
+
+/* Argument checking features. */
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+
+/* Returns with error when an invalid argument is passed. */
+
+#define CHECK_ARGUMENT(x) \
+ do { \
+ if (SLJIT_UNLIKELY(!(x))) \
+ return 1; \
+ } while (0)
+
+#define CHECK_RETURN_TYPE sljit_s32
+#define CHECK_RETURN_OK return 0
+
+#define CHECK(x) \
+ do { \
+ if (SLJIT_UNLIKELY(x)) { \
+ compiler->error = SLJIT_ERR_BAD_ARGUMENT; \
+ return SLJIT_ERR_BAD_ARGUMENT; \
+ } \
+ } while (0)
+
+#define CHECK_PTR(x) \
+ do { \
+ if (SLJIT_UNLIKELY(x)) { \
+ compiler->error = SLJIT_ERR_BAD_ARGUMENT; \
+ return NULL; \
+ } \
+ } while (0)
+
+#define CHECK_REG_INDEX(x) \
+ do { \
+ if (SLJIT_UNLIKELY(x)) { \
+ return -2; \
+ } \
+ } while (0)
+
+#elif (defined SLJIT_DEBUG && SLJIT_DEBUG)
+
+/* Assertion failure occures if an invalid argument is passed. */
+#undef SLJIT_ARGUMENT_CHECKS
+#define SLJIT_ARGUMENT_CHECKS 1
+
+#define CHECK_ARGUMENT(x) SLJIT_ASSERT(x)
+#define CHECK_RETURN_TYPE void
+#define CHECK_RETURN_OK return
+#define CHECK(x) x
+#define CHECK_PTR(x) x
+#define CHECK_REG_INDEX(x) x
+
+#elif (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+
+/* Arguments are not checked. */
+#define CHECK_RETURN_TYPE void
+#define CHECK_RETURN_OK return
+#define CHECK(x) x
+#define CHECK_PTR(x) x
+#define CHECK_REG_INDEX(x) x
+
+#else /* !SLJIT_ARGUMENT_CHECKS && !SLJIT_DEBUG && !SLJIT_VERBOSE */
+
+/* Arguments are not checked. */
+#define CHECK(x)
+#define CHECK_PTR(x)
+#define CHECK_REG_INDEX(x)
+
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+/* --------------------------------------------------------------------- */
+/* Public functions */
+/* --------------------------------------------------------------------- */
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
+#define SLJIT_NEEDS_COMPILER_INIT 1
+static sljit_s32 compiler_initialized = 0;
+/* A thread safe initialization. */
+static void init_compiler(void);
+#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_RISCV */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data)
+{
+ struct sljit_compiler *compiler = (struct sljit_compiler*)SLJIT_MALLOC(sizeof(struct sljit_compiler), allocator_data);
+ if (!compiler)
+ return NULL;
+ SLJIT_ZEROMEM(compiler, sizeof(struct sljit_compiler));
+
+ SLJIT_COMPILE_ASSERT(
+ sizeof(sljit_s8) == 1 && sizeof(sljit_u8) == 1
+ && sizeof(sljit_s16) == 2 && sizeof(sljit_u16) == 2
+ && sizeof(sljit_s32) == 4 && sizeof(sljit_u32) == 4
+ && (sizeof(sljit_up) == 4 || sizeof(sljit_up) == 8)
+ && sizeof(sljit_up) <= sizeof(sljit_sw)
+ && sizeof(sljit_up) == sizeof(sljit_sp)
+ && (sizeof(sljit_sw) == 4 || sizeof(sljit_sw) == 8)
+ && (sizeof(sljit_uw) == sizeof(sljit_sw)),
+ invalid_integer_types);
+ SLJIT_COMPILE_ASSERT((SLJIT_REWRITABLE_JUMP & SLJIT_32) == 0
+ && (ALL_STATUS_FLAGS_MASK & SLJIT_32) == 0
+ && (SLJIT_REWRITABLE_JUMP & ALL_STATUS_FLAGS_MASK) == 0,
+ rewritable_jump_and_status_flag_bits_and_sljit_32_must_not_have_common_bits);
+ SLJIT_COMPILE_ASSERT((VARIABLE_FLAG_MASK & SLJIT_SET_Z) == 0,
+ rewritable_jump_and_status_flag_bits_must_not_have_common_bits);
+ SLJIT_COMPILE_ASSERT(!(SLJIT_EQUAL & 0x1) && !(SLJIT_LESS & 0x1) && !(SLJIT_F_EQUAL & 0x1) && !(SLJIT_JUMP & 0x1),
+ conditional_flags_must_be_even_numbers);
+
+ /* Only the non-zero members must be set. */
+ compiler->error = SLJIT_SUCCESS;
+
+ compiler->allocator_data = allocator_data;
+ compiler->buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, allocator_data);
+ compiler->abuf = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE, allocator_data);
+
+ if (!compiler->buf || !compiler->abuf) {
+ if (compiler->buf)
+ SLJIT_FREE(compiler->buf, allocator_data);
+ if (compiler->abuf)
+ SLJIT_FREE(compiler->abuf, allocator_data);
+ SLJIT_FREE(compiler, allocator_data);
+ return NULL;
+ }
+
+ compiler->buf->next = NULL;
+ compiler->buf->used_size = 0;
+ compiler->abuf->next = NULL;
+ compiler->abuf->used_size = 0;
+
+ compiler->scratches = -1;
+ compiler->saveds = -1;
+ compiler->fscratches = -1;
+ compiler->fsaveds = -1;
+#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ compiler->vscratches = -1;
+ compiler->vsaveds = -1;
+#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS || SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */
+ compiler->local_size = -1;
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ compiler->args_size = -1;
+#endif /* SLJIT_CONFIG_X86_32 */
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ compiler->cpool = (sljit_uw*)SLJIT_MALLOC(CPOOL_SIZE * sizeof(sljit_uw)
+ + CPOOL_SIZE * sizeof(sljit_u8), allocator_data);
+ if (!compiler->cpool) {
+ SLJIT_FREE(compiler->buf, allocator_data);
+ SLJIT_FREE(compiler->abuf, allocator_data);
+ SLJIT_FREE(compiler, allocator_data);
+ return NULL;
+ }
+ compiler->cpool_unique = (sljit_u8*)(compiler->cpool + CPOOL_SIZE);
+ compiler->cpool_diff = 0xffffffff;
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
+ compiler->delay_slot = UNMOVABLE_INS;
+#endif /* SLJIT_CONFIG_MIPS */
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ SLJIT_ASSERT(compiler->last_flags == 0 && compiler->logical_local_size == 0);
+ compiler->last_return = -1;
+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)
+ compiler->real_fscratches = -1;
+ compiler->real_fsaveds = -1;
+#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */
+ SLJIT_ASSERT(compiler->skip_checks == 0);
+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */
+
+#if (defined SLJIT_NEEDS_COMPILER_INIT && SLJIT_NEEDS_COMPILER_INIT)
+ if (!compiler_initialized) {
+ init_compiler();
+ compiler_initialized = 1;
+ }
+#endif /* SLJIT_NEEDS_COMPILER_INIT */
+
+ return compiler;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler)
+{
+ struct sljit_memory_fragment *buf;
+ struct sljit_memory_fragment *curr;
+ void *allocator_data = compiler->allocator_data;
+ SLJIT_UNUSED_ARG(allocator_data);
+
+ buf = compiler->buf;
+ while (buf) {
+ curr = buf;
+ buf = buf->next;
+ SLJIT_FREE(curr, allocator_data);
+ }
+
+ buf = compiler->abuf;
+ while (buf) {
+ curr = buf;
+ buf = buf->next;
+ SLJIT_FREE(curr, allocator_data);
+ }
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ SLJIT_FREE(compiler->cpool, allocator_data);
+#endif /* SLJIT_CONFIG_ARM_V6 */
+ SLJIT_FREE(compiler, allocator_data);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler)
+{
+ if (compiler->error == SLJIT_SUCCESS)
+ compiler->error = SLJIT_ERR_ALLOC_FAILED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data)
+{
+ SLJIT_UNUSED_ARG(exec_allocator_data);
+
+ SLJIT_FREE_EXEC(SLJIT_CODE_TO_PTR(code), exec_allocator_data);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label)
+{
+ if (SLJIT_LIKELY(!!jump) && SLJIT_LIKELY(!!label)) {
+ jump->flags &= (sljit_uw)~JUMP_ADDR;
+ jump->u.label = label;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target)
+{
+ if (SLJIT_LIKELY(!!jump)) {
+ jump->flags |= JUMP_ADDR;
+ jump->u.target = target;
+ }
+}
+
+#define SLJIT_CURRENT_FLAGS_ALL (SLJIT_CURRENT_FLAGS_32 | SLJIT_CURRENT_FLAGS_ADD \
+ | SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE | SLJIT_CURRENT_FLAGS_OP2CMPZ)
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)
+{
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(current_flags);
+
+#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)
+#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
+ if (current_flags & SLJIT_CURRENT_FLAGS_OP2CMPZ) {
+ current_flags |= SLJIT_SET_Z;
+ }
+#endif /* SLJIT_CONFIG_S390X */
+
+ compiler->status_flags_state = current_flags;
+#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->last_flags = 0;
+ if ((current_flags & ~(ALL_STATUS_FLAGS_MASK | SLJIT_CURRENT_FLAGS_ALL)) == 0) {
+ compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_32 | SLJIT_SET_Z));
+ }
+#endif /* SLJIT_ARGUMENT_CHECKS */
+}
+
+/* --------------------------------------------------------------------- */
+/* Private functions */
+/* --------------------------------------------------------------------- */
+
+static void* ensure_buf(struct sljit_compiler *compiler, sljit_uw size)
+{
+ sljit_u8 *ret;
+ struct sljit_memory_fragment *new_frag;
+
+ SLJIT_ASSERT(size <= 256);
+ if (compiler->buf->used_size + size <= (BUF_SIZE - (sljit_uw)SLJIT_OFFSETOF(struct sljit_memory_fragment, memory))) {
+ ret = compiler->buf->memory + compiler->buf->used_size;
+ compiler->buf->used_size += size;
+ return ret;
+ }
+ new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, compiler->allocator_data);
+ PTR_FAIL_IF_NULL(new_frag);
+ new_frag->next = compiler->buf;
+ compiler->buf = new_frag;
+ new_frag->used_size = size;
+ return new_frag->memory;
+}
+
+static void* ensure_abuf(struct sljit_compiler *compiler, sljit_uw size)
+{
+ sljit_u8 *ret;
+ struct sljit_memory_fragment *new_frag;
+
+ SLJIT_ASSERT(size <= 256);
+ if (compiler->abuf->used_size + size <= (ABUF_SIZE - (sljit_uw)SLJIT_OFFSETOF(struct sljit_memory_fragment, memory))) {
+ ret = compiler->abuf->memory + compiler->abuf->used_size;
+ compiler->abuf->used_size += size;
+ return ret;
+ }
+ new_frag = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE, compiler->allocator_data);
+ PTR_FAIL_IF_NULL(new_frag);
+ new_frag->next = compiler->abuf;
+ compiler->abuf = new_frag;
+ new_frag->used_size = size;
+ return new_frag->memory;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size)
+{
+ CHECK_ERROR_PTR();
+
+#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
+ if (size <= 0 || size > 128)
+ return NULL;
+ size = (size + 7) & ~7;
+#else /* !SLJIT_64BIT_ARCHITECTURE */
+ if (size <= 0 || size > 64)
+ return NULL;
+ size = (size + 3) & ~3;
+#endif /* SLJIT_64BIT_ARCHITECTURE */
+ return ensure_abuf(compiler, (sljit_uw)size);
+}
+
+static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler)
+{
+ struct sljit_memory_fragment *buf = compiler->buf;
+ struct sljit_memory_fragment *prev = NULL;
+ struct sljit_memory_fragment *tmp;
+
+ do {
+ tmp = buf->next;
+ buf->next = prev;
+ prev = buf;
+ buf = tmp;
+ } while (buf != NULL);
+
+ compiler->buf = prev;
+}
+
+static SLJIT_INLINE void* allocate_executable_memory(sljit_uw size, sljit_s32 options,
+ void *exec_allocator_data, sljit_sw *executable_offset)
+{
+ void *code;
+ struct sljit_generate_code_buffer *buffer;
+
+ if (SLJIT_LIKELY(!(options & SLJIT_GENERATE_CODE_BUFFER))) {
+ code = SLJIT_MALLOC_EXEC(size, exec_allocator_data);
+ *executable_offset = SLJIT_EXEC_OFFSET(code);
+ return code;
+ }
+
+ buffer = (struct sljit_generate_code_buffer*)exec_allocator_data;
+
+ if (size <= buffer->size) {
+ *executable_offset = buffer->executable_offset;
+ return buffer->buffer;
+ }
+
+ return NULL;
+}
+
+#define SLJIT_MAX_ADDRESS ~(sljit_uw)0
+
+#define SLJIT_GET_NEXT_SIZE(ptr) (ptr != NULL) ? ((ptr)->size) : SLJIT_MAX_ADDRESS
+#define SLJIT_GET_NEXT_ADDRESS(ptr) (ptr != NULL) ? ((ptr)->addr) : SLJIT_MAX_ADDRESS
+
+#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+
+#define SLJIT_NEXT_DEFINE_TYPES \
+ sljit_uw next_label_size; \
+ sljit_uw next_jump_addr; \
+ sljit_uw next_const_addr; \
+ sljit_uw next_min_addr
+
+#define SLJIT_NEXT_INIT_TYPES() \
+ next_label_size = SLJIT_GET_NEXT_SIZE(label); \
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump); \
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+
+#define SLJIT_GET_NEXT_MIN() \
+ next_min_addr = sljit_get_next_min(next_label_size, next_jump_addr, next_const_addr);
+
+static SLJIT_INLINE sljit_uw sljit_get_next_min(sljit_uw next_label_size,
+ sljit_uw next_jump_addr, sljit_uw next_const_addr)
+{
+ sljit_uw result = next_jump_addr;
+
+ SLJIT_ASSERT(result == SLJIT_MAX_ADDRESS || result != next_const_addr);
+
+ if (next_const_addr < result)
+ result = next_const_addr;
+
+ if (next_label_size < result)
+ result = next_label_size;
+
+ return result;
+}
+
+#endif /* !SLJIT_CONFIG_X86 */
+
+#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)
+
+static void update_float_register_count(struct sljit_compiler *compiler, sljit_s32 scratches, sljit_s32 saveds)
+{
+ sljit_s32 vscratches = ENTER_GET_VECTOR_REGS(scratches);
+ sljit_s32 vsaveds = ENTER_GET_VECTOR_REGS(saveds);
+
+ if (compiler->fscratches < vscratches)
+ compiler->fscratches = vscratches;
+
+ if (compiler->fsaveds < vsaveds)
+ compiler->fsaveds = vsaveds;
+
+ if (compiler->fsaveds + compiler->fscratches > SLJIT_NUMBER_OF_FLOAT_REGISTERS)
+ compiler->fscratches = SLJIT_NUMBER_OF_FLOAT_REGISTERS - compiler->fsaveds;
+}
+
+#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */
+
+static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 args,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ SLJIT_UNUSED_ARG(args);
+ SLJIT_UNUSED_ARG(local_size);
+
+ compiler->options = options;
+ compiler->scratches = ENTER_GET_REGS(scratches);
+ compiler->saveds = ENTER_GET_REGS(saveds);
+ /* These members may be copied to real_* members below. */
+ compiler->fscratches = ENTER_GET_FLOAT_REGS(scratches);
+ compiler->fsaveds = ENTER_GET_FLOAT_REGS(saveds);
+#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)
+ compiler->vscratches = ENTER_GET_VECTOR_REGS(scratches);
+ compiler->vsaveds = ENTER_GET_VECTOR_REGS(saveds);
+#else /* !SLJIT_SEPARATE_VECTOR_REGISTERS */
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ compiler->real_fscratches = compiler->fscratches;
+ compiler->real_fsaveds = compiler->fsaveds;
+ compiler->vscratches = ENTER_GET_VECTOR_REGS(scratches);
+ compiler->vsaveds = ENTER_GET_VECTOR_REGS(saveds);
+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */
+ update_float_register_count(compiler, scratches, saveds);
+#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS */
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->last_return = args & SLJIT_ARG_MASK;
+ compiler->logical_local_size = local_size;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+}
+
+static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compiler *compiler)
+{
+ label->next = NULL;
+ label->u.index = compiler->label_count++;
+ label->size = compiler->size;
+
+ if (compiler->last_label != NULL)
+ compiler->last_label->next = label;
+ else
+ compiler->labels = label;
+
+ compiler->last_label = label;
+}
+
+static SLJIT_INLINE void set_extended_label(struct sljit_extended_label *ext_label, struct sljit_compiler *compiler, sljit_uw type, sljit_uw data)
+{
+ set_label(&ext_label->label, compiler);
+ ext_label->index = ext_label->label.u.index;
+ ext_label->label.u.index = type;
+ ext_label->data = data;
+}
+
+static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_u32 flags)
+{
+ jump->next = NULL;
+ jump->flags = flags;
+ jump->u.label = NULL;
+
+ if (compiler->last_jump != NULL)
+ compiler->last_jump->next = jump;
+ else
+ compiler->jumps = jump;
+
+ compiler->last_jump = jump;
+}
+
+static SLJIT_INLINE void set_mov_addr(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_uw offset)
+{
+ jump->next = NULL;
+ jump->addr = compiler->size - offset;
+ jump->flags = JUMP_MOV_ADDR;
+ jump->u.label = NULL;
+ if (compiler->last_jump != NULL)
+ compiler->last_jump->next = jump;
+ else
+ compiler->jumps = jump;
+ compiler->last_jump = jump;
+}
+
+static SLJIT_INLINE void set_const(struct sljit_const *const_, struct sljit_compiler *compiler)
+{
+ const_->next = NULL;
+ const_->addr = compiler->size;
+ if (compiler->last_const != NULL)
+ compiler->last_const->next = const_;
+ else
+ compiler->consts = const_;
+ compiler->last_const = const_;
+}
+
+#define ADDRESSING_DEPENDS_ON(exp, reg) \
+ (((exp) & SLJIT_MEM) && (((exp) & REG_MASK) == reg || OFFS_REG(exp) == reg))
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+
+static sljit_s32 function_check_arguments(sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches)
+{
+ sljit_s32 word_arg_count, scratch_arg_end, saved_arg_count, float_arg_count, curr_type;
+
+ curr_type = (arg_types & SLJIT_ARG_FULL_MASK);
+
+ if (curr_type >= SLJIT_ARG_TYPE_F64) {
+ if (curr_type > SLJIT_ARG_TYPE_F32 || fscratches == 0)
+ return 0;
+ } else if (curr_type >= SLJIT_ARG_TYPE_W) {
+ if (scratches == 0)
+ return 0;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ word_arg_count = 0;
+ scratch_arg_end = 0;
+ saved_arg_count = 0;
+ float_arg_count = 0;
+ while (arg_types != 0) {
+ if (word_arg_count + float_arg_count >= 4)
+ return 0;
+
+ curr_type = (arg_types & SLJIT_ARG_MASK);
+
+ if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) {
+ if (saveds == -1 || curr_type < SLJIT_ARG_TYPE_W || curr_type > SLJIT_ARG_TYPE_P)
+ return 0;
+
+ word_arg_count++;
+ scratch_arg_end = word_arg_count;
+ } else {
+ if (curr_type < SLJIT_ARG_TYPE_W || curr_type > SLJIT_ARG_TYPE_F32)
+ return 0;
+
+ if (curr_type < SLJIT_ARG_TYPE_F64) {
+ word_arg_count++;
+ saved_arg_count++;
+ } else
+ float_arg_count++;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ if (saveds == -1)
+ return (word_arg_count <= scratches && float_arg_count <= fscratches);
+
+ return (saved_arg_count <= saveds && scratch_arg_end <= scratches && float_arg_count <= fscratches);
+}
+
+#define FUNCTION_CHECK_IS_REG(r) \
+ (((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) \
+ || ((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0) \
+ || ((r) >= SLJIT_TMP_REGISTER_BASE && (r) < (SLJIT_TMP_REGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_REGISTERS)))
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+#define CHECK_IF_VIRTUAL_REGISTER(p) ((p) <= SLJIT_S3 && (p) >= SLJIT_S8)
+#else /* !SLJIT_CONFIG_X86_32 */
+#define CHECK_IF_VIRTUAL_REGISTER(p) 0
+#endif /* SLJIT_CONFIG_X86_32 */
+
+static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
+{
+ if (compiler->scratches == -1)
+ return 0;
+
+ if (!(p & SLJIT_MEM))
+ return 0;
+
+ if (p == SLJIT_MEM1(SLJIT_SP))
+ return (i >= 0 && i < compiler->logical_local_size);
+
+ if (!(!(p & REG_MASK) || FUNCTION_CHECK_IS_REG(p & REG_MASK)))
+ return 0;
+
+ if (CHECK_IF_VIRTUAL_REGISTER(p & REG_MASK))
+ return 0;
+
+ if (p & OFFS_REG_MASK) {
+ if (!(p & REG_MASK))
+ return 0;
+
+ if (!(FUNCTION_CHECK_IS_REG(OFFS_REG(p))))
+ return 0;
+
+ if (CHECK_IF_VIRTUAL_REGISTER(OFFS_REG(p)))
+ return 0;
+
+ if ((i & ~0x3) != 0)
+ return 0;
+ }
+
+ return (p & ~(SLJIT_MEM | REG_MASK | OFFS_REG_MASK)) == 0;
+}
+
+#define FUNCTION_CHECK_SRC_MEM(p, i) \
+ CHECK_ARGUMENT(function_check_src_mem(compiler, p, i));
+
+static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
+{
+ if (compiler->scratches == -1)
+ return 0;
+
+ if (FUNCTION_CHECK_IS_REG(p))
+ return (i == 0);
+
+ if (p == SLJIT_IMM)
+ return 1;
+
+ return function_check_src_mem(compiler, p, i);
+}
+
+#define FUNCTION_CHECK_SRC(p, i) \
+ CHECK_ARGUMENT(function_check_src(compiler, p, i));
+
+static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
+{
+ if (compiler->scratches == -1)
+ return 0;
+
+ if (FUNCTION_CHECK_IS_REG(p))
+ return (i == 0);
+
+ return function_check_src_mem(compiler, p, i);
+}
+
+#define FUNCTION_CHECK_DST(p, i) \
+ CHECK_ARGUMENT(function_check_dst(compiler, p, i));
+
+#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
+ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+
+#define FUNCTION_CHECK_IS_FREG(fr, is_32) \
+ function_check_is_freg(compiler, (fr), (is_32))
+
+static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32);
+
+#define FUNCTION_FCHECK(p, i, is_32) \
+ CHECK_ARGUMENT(function_fcheck(compiler, (p), (i), (is_32)));
+
+static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 is_32)
+{
+ if (compiler->scratches == -1)
+ return 0;
+
+ if (FUNCTION_CHECK_IS_FREG(p, is_32))
+ return (i == 0);
+
+ return function_check_src_mem(compiler, p, i);
+}
+
+static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type);
+
+#define FUNCTION_CHECK_IS_VREG(vr, type) \
+ function_check_is_vreg(compiler, (vr), (type))
+
+#define FUNCTION_VCHECK(p, i, type) \
+ CHECK_ARGUMENT(function_vcheck(compiler, (p), (i), (type)))
+
+static sljit_s32 function_vcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 type)
+{
+ if (compiler->scratches == -1)
+ return 0;
+
+ if (FUNCTION_CHECK_IS_VREG(p, type))
+ return (i == 0);
+
+ return function_check_src_mem(compiler, p, i);
+}
+
+#else /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS_32 */
+
+#define FUNCTION_CHECK_IS_FREG(fr, is_32) \
+ function_check_is_freg(compiler, (fr))
+
+static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr)
+{
+ sljit_s32 fscratches, fsaveds;
+
+ if (compiler->scratches == -1)
+ return 0;
+
+#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+#else /* SLJIT_SEPARATE_VECTOR_REGISTERS */
+ fscratches = compiler->real_fscratches;
+ fsaveds = compiler->real_fsaveds;
+#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */
+
+ return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + fscratches))
+ || (fr > (SLJIT_FS0 - fsaveds) && fr <= SLJIT_FS0)
+ || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));
+}
+
+#define FUNCTION_FCHECK(p, i, is_32) \
+ CHECK_ARGUMENT(function_fcheck(compiler, (p), (i)));
+
+static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
+{
+ if (compiler->scratches == -1)
+ return 0;
+
+ if (function_check_is_freg(compiler, p))
+ return (i == 0);
+
+ return function_check_src_mem(compiler, p, i);
+}
+
+#define FUNCTION_CHECK_IS_VREG(vr, type) \
+ function_check_is_vreg(compiler, (vr))
+
+static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr)
+{
+ if (compiler->scratches == -1)
+ return 0;
+
+ return (vr >= SLJIT_VR0 && vr < (SLJIT_VR0 + compiler->vscratches))
+ || (vr > (SLJIT_VS0 - compiler->vsaveds) && vr <= SLJIT_VS0)
+ || (vr >= SLJIT_TMP_VREGISTER_BASE && vr < (SLJIT_TMP_VREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS));
+}
+
+#define FUNCTION_VCHECK(p, i, type) \
+ CHECK_ARGUMENT(function_vcheck(compiler, (p), (i)))
+
+static sljit_s32 function_vcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
+{
+ if (compiler->scratches == -1)
+ return 0;
+
+ if (function_check_is_vreg(compiler, p))
+ return (i == 0);
+
+ return function_check_src_mem(compiler, p, i);
+}
+
+#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */
+
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose)
+{
+ compiler->verbose = verbose;
+}
+
+#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
+#ifdef _WIN64
+#ifdef __GNUC__
+# define SLJIT_PRINT_D "ll"
+#else /* !__GNUC__ */
+# define SLJIT_PRINT_D "I64"
+#endif /* __GNUC__ */
+#else /* !_WIN64 */
+# define SLJIT_PRINT_D "l"
+#endif /* _WIN64 */
+#else /* !SLJIT_64BIT_ARCHITECTURE */
+# define SLJIT_PRINT_D ""
+#endif /* SLJIT_64BIT_ARCHITECTURE */
+
+static void sljit_verbose_reg(struct sljit_compiler *compiler, sljit_s32 r)
+{
+ if (r < (SLJIT_R0 + compiler->scratches))
+ fprintf(compiler->verbose, "r%d", r - SLJIT_R0);
+ else if (r < SLJIT_SP)
+ fprintf(compiler->verbose, "s%d", SLJIT_NUMBER_OF_REGISTERS - r);
+ else if (r == SLJIT_SP)
+ fprintf(compiler->verbose, "sp");
+ else
+ fprintf(compiler->verbose, "t%d", r - SLJIT_TMP_REGISTER_BASE);
+}
+
+static void sljit_verbose_freg(struct sljit_compiler *compiler, sljit_s32 r)
+{
+#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
+ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ if (r >= SLJIT_F64_SECOND(SLJIT_FR0)) {
+ fprintf(compiler->verbose, "^");
+ r -= SLJIT_F64_SECOND(0);
+ }
+#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */
+
+ if (r < (SLJIT_FR0 + compiler->fscratches))
+ fprintf(compiler->verbose, "fr%d", r - SLJIT_FR0);
+ else if (r < SLJIT_TMP_FREGISTER_BASE)
+ fprintf(compiler->verbose, "fs%d", SLJIT_NUMBER_OF_FLOAT_REGISTERS - r);
+ else
+ fprintf(compiler->verbose, "ft%d", r - SLJIT_TMP_FREGISTER_BASE);
+}
+
+static void sljit_verbose_vreg(struct sljit_compiler *compiler, sljit_s32 r)
+{
+#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
+ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ if (r >= SLJIT_F64_SECOND(SLJIT_VR0)) {
+ fprintf(compiler->verbose, "^");
+ r -= SLJIT_F64_SECOND(0);
+ }
+#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */
+
+ if (r < (SLJIT_VR0 + compiler->vscratches))
+ fprintf(compiler->verbose, "vr%d", r - SLJIT_VR0);
+ else if (r < SLJIT_TMP_VREGISTER_BASE)
+ fprintf(compiler->verbose, "vs%d", SLJIT_NUMBER_OF_VECTOR_REGISTERS - r);
+ else
+ fprintf(compiler->verbose, "vt%d", r - SLJIT_TMP_VREGISTER_BASE);
+}
+
+static void sljit_verbose_mem(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
+{
+ if (!(p & REG_MASK)) {
+ fprintf(compiler->verbose, "[%" SLJIT_PRINT_D "d]", i);
+ return;
+ }
+
+ fputc('[', compiler->verbose);
+ sljit_verbose_reg(compiler, (p) & REG_MASK);
+ if (p & OFFS_REG_MASK) {
+ fprintf(compiler->verbose, " + ");
+ sljit_verbose_reg(compiler, OFFS_REG(p));
+ if (i)
+ fprintf(compiler->verbose, " * %d", 1 << (i));
+ } else if (i)
+ fprintf(compiler->verbose, " + %" SLJIT_PRINT_D "d", (i));
+ fputc(']', compiler->verbose);
+}
+
+static void sljit_verbose_param(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
+{
+ if (p == SLJIT_IMM)
+ fprintf(compiler->verbose, "#%" SLJIT_PRINT_D "d", i);
+ else if (p & SLJIT_MEM)
+ sljit_verbose_mem(compiler, p, i);
+ else
+ sljit_verbose_reg(compiler, p);
+}
+
+static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
+{
+ if (p & SLJIT_MEM)
+ sljit_verbose_mem(compiler, p, i);
+ else
+ sljit_verbose_freg(compiler, p);
+}
+
+static void sljit_verbose_vparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
+{
+ if (p & SLJIT_MEM)
+ sljit_verbose_mem(compiler, p, i);
+ else
+ sljit_verbose_vreg(compiler, p);
+}
+
+static const char* op0_names[] = {
+ "breakpoint", "nop", "lmul.uw", "lmul.sw",
+ "divmod.u", "divmod.s", "div.u", "div.s",
+ "memory_barrier", "endbr", "skip_frames_before_return"
+};
+
+static const char* op1_names[] = {
+ "mov", "mov", "mov", "mov",
+ "mov", "mov", "mov", "mov",
+ "mov", "clz", "ctz", "rev",
+ "rev", "rev", "rev", "rev"
+};
+
+static const char* op1_types[] = {
+ "", ".u8", ".s8", ".u16",
+ ".s16", ".u32", ".s32", "32",
+ ".p", "", "", "",
+ ".u16", ".s16", ".u32", ".s32"
+};
+
+static const char* op2_names[] = {
+ "add", "addc", "sub", "subc",
+ "mul", "and", "or", "xor",
+ "shl", "mshl", "lshr", "mlshr",
+ "ashr", "mashr", "rotl", "rotr"
+};
+
+static const char* op2r_names[] = {
+ "muladd"
+};
+
+static const char* op_src_dst_names[] = {
+ "fast_return", "skip_frames_before_fast_return",
+ "prefetch_l1", "prefetch_l2",
+ "prefetch_l3", "prefetch_once",
+ "fast_enter", "get_return_address"
+};
+
+static const char* fop1_names[] = {
+ "mov", "conv", "conv", "conv",
+ "conv", "conv", "conv", "conv",
+ "cmp", "neg", "abs",
+};
+
+static const char* fop1_conv_types[] = {
+ "sw", "s32", "sw", "s32",
+ "uw", "u32"
+};
+
+static const char* fop2_names[] = {
+ "add", "sub", "mul", "div"
+};
+
+static const char* fop2r_names[] = {
+ "copysign"
+};
+
+static const char* simd_op2_names[] = {
+ "and", "or", "xor", "shuffle"
+};
+
+static const char* jump_names[] = {
+ "equal", "not_equal",
+ "less", "greater_equal",
+ "greater", "less_equal",
+ "sig_less", "sig_greater_equal",
+ "sig_greater", "sig_less_equal",
+ "overflow", "not_overflow",
+ "carry", "not_carry",
+ "atomic_stored", "atomic_not_stored",
+ "f_equal", "f_not_equal",
+ "f_less", "f_greater_equal",
+ "f_greater", "f_less_equal",
+ "unordered", "ordered",
+ "ordered_equal", "unordered_or_not_equal",
+ "ordered_less", "unordered_or_greater_equal",
+ "ordered_greater", "unordered_or_less_equal",
+ "unordered_or_equal", "ordered_not_equal",
+ "unordered_or_less", "ordered_greater_equal",
+ "unordered_or_greater", "ordered_less_equal",
+ "jump", "fast_call",
+ "call", "call_reg_arg"
+};
+
+static const char* call_arg_names[] = {
+ "void", "w", "32", "p", "f64", "f32"
+};
+
+static const char* op_addr_types[] = {
+ "mov_addr", "mov_abs_addr", "add_abs_addr"
+};
+
+#endif /* SLJIT_VERBOSE */
+
+/* --------------------------------------------------------------------- */
+/* Arch dependent */
+/* --------------------------------------------------------------------- */
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+
+#define SLJIT_SKIP_CHECKS(compiler) (compiler)->skip_checks = 1
+#define SLJIT_CHECK_OPCODE(op, flags) ((op) & ~(SLJIT_32 | ALL_STATUS_FLAGS_MASK | (flags)))
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ struct sljit_jump *jump;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(options);
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(compiler->size > 0);
+ CHECK_ARGUMENT((options & ~(SLJIT_GENERATE_CODE_BUFFER | SLJIT_GENERATE_CODE_NO_CONTEXT)) == 0);
+
+ jump = compiler->jumps;
+ while (jump) {
+ /* All jumps have target. */
+ CHECK_ARGUMENT((jump->flags & JUMP_ADDR) || jump->u.label != NULL);
+ jump = jump->next;
+ }
+#endif /* SLJIT_ARGUMENT_CHECKS */
+ CHECK_RETURN_OK;
+}
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+#define SLJIT_ENTER_CPU_SPECIFIC_OPTIONS (SLJIT_ENTER_USE_VEX)
+#else /* !SLJIT_CONFIG_X86 */
+#define SLJIT_ENTER_CPU_SPECIFIC_OPTIONS (0)
+#endif /* !SLJIT_CONFIG_X86 */
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ sljit_s32 real_scratches = ENTER_GET_REGS(scratches);
+ sljit_s32 real_saveds = ENTER_GET_REGS(saveds);
+ sljit_s32 real_fscratches = ENTER_GET_FLOAT_REGS(scratches);
+ sljit_s32 real_fsaveds = ENTER_GET_FLOAT_REGS(saveds);
+ sljit_s32 real_vscratches = ENTER_GET_VECTOR_REGS(scratches);
+ sljit_s32 real_vsaveds = ENTER_GET_VECTOR_REGS(saveds);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+ SLJIT_UNUSED_ARG(compiler);
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ if (options & SLJIT_ENTER_REG_ARG) {
+ CHECK_ARGUMENT(!(options & ~(0x3 | SLJIT_ENTER_REG_ARG | SLJIT_ENTER_CPU_SPECIFIC_OPTIONS)));
+ } else {
+ CHECK_ARGUMENT((options & ~SLJIT_ENTER_CPU_SPECIFIC_OPTIONS) == 0);
+ }
+ CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);
+ CHECK_ARGUMENT((scratches & ~0xffffff) == 0 && (saveds & ~0xffffff) == 0);
+ CHECK_ARGUMENT(real_scratches >= 0 && real_scratches <= SLJIT_NUMBER_OF_REGISTERS);
+ CHECK_ARGUMENT(real_saveds >= 0 && real_saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);
+ CHECK_ARGUMENT(real_scratches + real_saveds <= SLJIT_NUMBER_OF_REGISTERS);
+ CHECK_ARGUMENT(real_fscratches >= 0 && real_fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
+ CHECK_ARGUMENT(real_fsaveds >= 0 && real_fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS);
+ CHECK_ARGUMENT(real_fscratches + real_fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
+ CHECK_ARGUMENT(real_vscratches >= 0 && real_vscratches <= SLJIT_NUMBER_OF_VECTOR_REGISTERS);
+ CHECK_ARGUMENT(real_vsaveds >= 0 && real_vsaveds <= SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS);
+ CHECK_ARGUMENT(real_vscratches + real_vsaveds <= SLJIT_NUMBER_OF_VECTOR_REGISTERS);
+ CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
+ CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) <= SLJIT_ARG_TYPE_F32);
+ CHECK_ARGUMENT(function_check_arguments(arg_types, real_scratches,
+ (options & SLJIT_ENTER_REG_ARG) ? 0 : real_saveds, real_fscratches));
+
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " enter ret[%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ if (arg_types) {
+ fprintf(compiler->verbose, "], args[");
+ do {
+ fprintf(compiler->verbose, "%s%s", call_arg_names[arg_types & SLJIT_ARG_MASK],
+ (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? "_r" : "");
+ arg_types >>= SLJIT_ARG_SHIFT;
+ if (arg_types)
+ fprintf(compiler->verbose, ",");
+ } while (arg_types);
+ }
+
+ fprintf(compiler->verbose, "],");
+
+ if (options & SLJIT_ENTER_REG_ARG) {
+ if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
+ fprintf(compiler->verbose, " opt:reg_arg(%d),", SLJIT_KEPT_SAVEDS_COUNT(options));
+ else
+ fprintf(compiler->verbose, " opt:reg_arg,");
+ }
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+ if (options & SLJIT_ENTER_USE_VEX) {
+ fprintf(compiler->verbose, " opt:use_vex,");
+ }
+#endif /* !SLJIT_CONFIG_X86 */
+
+ fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, vscratches:%d, vsaveds:%d, local_size:%d\n",
+ ENTER_GET_REGS(scratches), ENTER_GET_REGS(saveds), ENTER_GET_FLOAT_REGS(scratches), ENTER_GET_FLOAT_REGS(saveds),
+ ENTER_GET_VECTOR_REGS(scratches), ENTER_GET_VECTOR_REGS(saveds), local_size);
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ sljit_s32 real_scratches = ENTER_GET_REGS(scratches);
+ sljit_s32 real_saveds = ENTER_GET_REGS(saveds);
+ sljit_s32 real_fscratches = ENTER_GET_FLOAT_REGS(scratches);
+ sljit_s32 real_fsaveds = ENTER_GET_FLOAT_REGS(saveds);
+ sljit_s32 real_vscratches = ENTER_GET_VECTOR_REGS(scratches);
+ sljit_s32 real_vsaveds = ENTER_GET_VECTOR_REGS(saveds);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+ SLJIT_UNUSED_ARG(compiler);
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ if (options & SLJIT_ENTER_REG_ARG) {
+ CHECK_ARGUMENT(!(options & ~(0x3 | SLJIT_ENTER_REG_ARG | SLJIT_ENTER_CPU_SPECIFIC_OPTIONS)));
+ } else {
+ CHECK_ARGUMENT((options & ~SLJIT_ENTER_CPU_SPECIFIC_OPTIONS) == 0);
+ }
+ CHECK_ARGUMENT(SLJIT_KEPT_SAVEDS_COUNT(options) <= 3 && SLJIT_KEPT_SAVEDS_COUNT(options) <= saveds);
+ CHECK_ARGUMENT((scratches & ~0xffffff) == 0 && (saveds & ~0xffffff) == 0);
+ CHECK_ARGUMENT(real_scratches >= 0 && real_scratches <= SLJIT_NUMBER_OF_REGISTERS);
+ CHECK_ARGUMENT(real_saveds >= 0 && real_saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);
+ CHECK_ARGUMENT(real_scratches + real_saveds <= SLJIT_NUMBER_OF_REGISTERS);
+ CHECK_ARGUMENT(real_fscratches >= 0 && real_fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
+ CHECK_ARGUMENT(real_fsaveds >= 0 && real_fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS);
+ CHECK_ARGUMENT(real_fscratches + real_fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
+ CHECK_ARGUMENT(real_vscratches >= 0 && real_vscratches <= SLJIT_NUMBER_OF_VECTOR_REGISTERS);
+ CHECK_ARGUMENT(real_vsaveds >= 0 && real_vsaveds <= SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS);
+ CHECK_ARGUMENT(real_vscratches + real_vsaveds <= SLJIT_NUMBER_OF_VECTOR_REGISTERS);
+ CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
+ CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64);
+ CHECK_ARGUMENT(function_check_arguments(arg_types, real_scratches,
+ (options & SLJIT_ENTER_REG_ARG) ? 0 : real_saveds, real_fscratches));
+
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " set_context ret[%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ if (arg_types) {
+ fprintf(compiler->verbose, "], args[");
+ do {
+ fprintf(compiler->verbose, "%s%s", call_arg_names[arg_types & SLJIT_ARG_MASK],
+ (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? "_r" : "");
+ arg_types >>= SLJIT_ARG_SHIFT;
+ if (arg_types)
+ fprintf(compiler->verbose, ",");
+ } while (arg_types);
+ }
+
+ fprintf(compiler->verbose, "],");
+
+ if (options & SLJIT_ENTER_REG_ARG) {
+ if (SLJIT_KEPT_SAVEDS_COUNT(options) > 0)
+ fprintf(compiler->verbose, " opt:reg_arg(%d),", SLJIT_KEPT_SAVEDS_COUNT(options));
+ else
+ fprintf(compiler->verbose, " opt:reg_arg,");
+ }
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+ if (options & SLJIT_ENTER_USE_VEX) {
+ fprintf(compiler->verbose, " opt:use_vex,");
+ }
+#endif /* !SLJIT_CONFIG_X86 */
+
+ fprintf(compiler->verbose, " scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, vscratches:%d, vsaveds:%d, local_size:%d\n",
+ ENTER_GET_REGS(scratches), ENTER_GET_REGS(saveds), ENTER_GET_FLOAT_REGS(scratches), ENTER_GET_FLOAT_REGS(saveds),
+ ENTER_GET_VECTOR_REGS(scratches), ENTER_GET_VECTOR_REGS(saveds), local_size);
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+#undef SLJIT_ENTER_CPU_SPECIFIC_OPTIONS
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(compiler->last_return == SLJIT_ARG_TYPE_RET_VOID);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " return_void\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(compiler->scratches >= 0);
+
+ switch (compiler->last_return) {
+ case SLJIT_ARG_TYPE_W:
+ CHECK_ARGUMENT(op >= SLJIT_MOV && op <= SLJIT_MOV_S32);
+ break;
+ case SLJIT_ARG_TYPE_32:
+ CHECK_ARGUMENT(op == SLJIT_MOV32 || (op >= SLJIT_MOV32_U8 && op <= SLJIT_MOV32_S16));
+ break;
+ case SLJIT_ARG_TYPE_P:
+ CHECK_ARGUMENT(op == SLJIT_MOV_P);
+ break;
+ case SLJIT_ARG_TYPE_F64:
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+ CHECK_ARGUMENT(op == SLJIT_MOV_F64);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+ CHECK_ARGUMENT(op == SLJIT_MOV_F32);
+ break;
+ default:
+ /* Context not initialized, void, etc. */
+ CHECK_ARGUMENT(0);
+ break;
+ }
+
+ if (SLJIT_CHECK_OPCODE(op, 0) < SLJIT_MOV_F64) {
+ FUNCTION_CHECK_SRC(src, srcw);
+ } else {
+ FUNCTION_FCHECK(src, srcw, op & SLJIT_32);
+ }
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ if (GET_OPCODE(op) < SLJIT_MOV_F64) {
+ fprintf(compiler->verbose, " return%s%s ", !(op & SLJIT_32) ? "" : "32",
+ op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);
+ sljit_verbose_param(compiler, src, srcw);
+ } else {
+ fprintf(compiler->verbose, " return%s ", !(op & SLJIT_32) ? ".f64" : ".f32");
+ sljit_verbose_fparam(compiler, src, srcw);
+ }
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_to(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ FUNCTION_CHECK_SRC(src, srcw);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " return_to ");
+ sljit_verbose_param(compiler, src, srcw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LMUL_SW)
+ || ((op & ~SLJIT_32) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_32) <= SLJIT_DIV_SW)
+ || (op >= SLJIT_MEMORY_BARRIER && op <= SLJIT_SKIP_FRAMES_BEFORE_RETURN));
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) < SLJIT_LMUL_UW || SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_MEMORY_BARRIER || compiler->scratches >= 2);
+ if ((SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_LMUL_UW && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_DIV_SW) || op == SLJIT_SKIP_FRAMES_BEFORE_RETURN)
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose))
+ {
+ fprintf(compiler->verbose, " %s", op0_names[GET_OPCODE(op) - SLJIT_OP0_BASE]);
+ if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) {
+ fprintf(compiler->verbose, (op & SLJIT_32) ? "32" : "w");
+ }
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_MOV && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_REV_S32);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ case SLJIT_MOV_P:
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+ /* Nothing allowed */
+ CHECK_ARGUMENT(!(op & (SLJIT_32 | ALL_STATUS_FLAGS_MASK)));
+ break;
+ default:
+ /* Only SLJIT_32 is allowed. */
+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));
+ break;
+ }
+
+ FUNCTION_CHECK_DST(dst, dstw);
+ FUNCTION_CHECK_SRC(src, srcw);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE],
+ !(op & SLJIT_32) ? "" : "32", op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);
+
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src, srcw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 mem_reg)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_ATOMIC));
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | ALL_STATUS_FLAGS_MASK) >= SLJIT_MOV
+ && SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | ALL_STATUS_FLAGS_MASK) <= SLJIT_MOV_P);
+ CHECK_ARGUMENT((op & (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS)) != (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS));
+
+ /* All arguments must be valid registers. */
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(mem_reg) && !CHECK_IF_VIRTUAL_REGISTER(mem_reg));
+
+ if (GET_OPCODE(op) < SLJIT_MOV_U8 || GET_OPCODE(op) > SLJIT_MOV_S16) {
+ /* Nothing allowed. */
+ CHECK_ARGUMENT(!(op & SLJIT_32));
+ }
+
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ if (op & SLJIT_ATOMIC_TEST)
+ CHECK_RETURN_OK;
+ if (sljit_emit_atomic_load(compiler, op | SLJIT_ATOMIC_TEST, dst_reg, mem_reg)) {
+ fprintf(compiler->verbose, " # atomic_load: unsupported form, no instructions are emitted\n");
+ CHECK_RETURN_OK;
+ }
+
+ fprintf(compiler->verbose, " atomic_load");
+ if (op & SLJIT_ATOMIC_USE_CAS)
+ fprintf(compiler->verbose, "_cas");
+ if (op & SLJIT_ATOMIC_USE_LS)
+ fprintf(compiler->verbose, "_ls");
+
+ fprintf(compiler->verbose, "%s%s ", !(op & SLJIT_32) ? "" : "32",
+ op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);
+ sljit_verbose_reg(compiler, dst_reg);
+ fprintf(compiler->verbose, ", [");
+ sljit_verbose_reg(compiler, mem_reg);
+ fprintf(compiler->verbose, "]\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src_reg,
+ sljit_s32 mem_reg,
+ sljit_s32 temp_reg)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_ATOMIC));
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | SLJIT_SET_Z) >= SLJIT_MOV
+ && SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | SLJIT_SET_Z) <= SLJIT_MOV_P);
+ CHECK_ARGUMENT((op & (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS)) != (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS));
+
+ /* All arguments must be valid registers. */
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src_reg));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(mem_reg) && !CHECK_IF_VIRTUAL_REGISTER(mem_reg));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(temp_reg) && (src_reg != temp_reg || (op & SLJIT_ATOMIC_USE_LS)));
+
+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE_MASK(op) == SLJIT_ATOMIC_STORED);
+
+ if (GET_OPCODE(op) < SLJIT_MOV_U8 || GET_OPCODE(op) > SLJIT_MOV_S16) {
+ /* Nothing allowed. */
+ CHECK_ARGUMENT(!(op & SLJIT_32));
+ }
+
+ compiler->last_flags = GET_FLAG_TYPE_MASK(op) | (op & SLJIT_32);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ if (op & SLJIT_ATOMIC_TEST)
+ CHECK_RETURN_OK;
+ if (sljit_emit_atomic_store(compiler, op | SLJIT_ATOMIC_TEST, src_reg, mem_reg, temp_reg)) {
+ fprintf(compiler->verbose, " # atomic_store: unsupported form, no instructions are emitted\n");
+ CHECK_RETURN_OK;
+ }
+
+ fprintf(compiler->verbose, " atomic_store");
+ if (op & SLJIT_ATOMIC_USE_CAS)
+ fprintf(compiler->verbose, "_cas");
+ if (op & SLJIT_ATOMIC_USE_LS)
+ fprintf(compiler->verbose, "_ls");
+
+ fprintf(compiler->verbose, "%s%s%s ", !(op & SLJIT_32) ? "" : "32",
+ op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & VARIABLE_FLAG_MASK) ? "" : ".stored");
+ sljit_verbose_reg(compiler, src_reg);
+ fprintf(compiler->verbose, ", [");
+ sljit_verbose_reg(compiler, mem_reg);
+ fprintf(compiler->verbose, "], ");
+ sljit_verbose_reg(compiler, temp_reg);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+
+static sljit_s32 check_sljit_emit_op2_operation(struct sljit_compiler *compiler, sljit_s32 op)
+{
+ switch (GET_OPCODE(op)) {
+ case SLJIT_AND:
+ case SLJIT_OR:
+ case SLJIT_XOR:
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ return !(op & VARIABLE_FLAG_MASK);
+ case SLJIT_MUL:
+ return !(op & SLJIT_SET_Z) && (!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);
+ case SLJIT_ADD:
+ return !(op & VARIABLE_FLAG_MASK)
+ || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)
+ || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+ case SLJIT_SUB:
+ return !(op & VARIABLE_FLAG_MASK)
+ || (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_OVERFLOW)
+ || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
+ case SLJIT_ADDC:
+ case SLJIT_SUBC:
+ return (!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY))
+ && (compiler->last_flags & 0xff) == GET_FLAG_TYPE(SLJIT_SET_CARRY)
+ && (op & SLJIT_32) == (compiler->last_flags & SLJIT_32);
+ break;
+ case SLJIT_ROTL:
+ case SLJIT_ROTR:
+ return !(op & ALL_STATUS_FLAGS_MASK);
+ }
+
+ /* Operation type should be checked earlier. */
+ SLJIT_UNREACHABLE();
+ return 1;
+}
+
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 unset,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_ADD && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_ROTR);
+ CHECK_ARGUMENT(check_sljit_emit_op2_operation(compiler, op));
+
+ if (unset) {
+ CHECK_ARGUMENT(HAS_FLAGS(op));
+ } else {
+ FUNCTION_CHECK_DST(dst, dstw);
+ }
+ FUNCTION_CHECK_SRC(src1, src1w);
+ FUNCTION_CHECK_SRC(src2, src2w);
+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32",
+ !(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".",
+ !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]);
+ if (unset)
+ fprintf(compiler->verbose, "unset");
+ else
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src1, src1w);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src2, src2w);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT((op | SLJIT_32) == SLJIT_MULADD32);
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));
+ FUNCTION_CHECK_SRC(src1, src1w);
+ FUNCTION_CHECK_SRC(src2, src2w);
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s%s ", op2r_names[GET_OPCODE(op) - SLJIT_OP2R_BASE], !(op & SLJIT_32) ? "" : "32");
+
+ sljit_verbose_reg(compiler, dst_reg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src1, src1w);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src2, src2w);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1_reg,
+ sljit_s32 src2_reg,
+ sljit_s32 src3, sljit_sw src3w)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) == SLJIT_SHL || SLJIT_CHECK_OPCODE(op, 0) == SLJIT_LSHR
+ || SLJIT_CHECK_OPCODE(op, 0) == SLJIT_MSHL || SLJIT_CHECK_OPCODE(op, 0) == SLJIT_MLSHR);
+ CHECK_ARGUMENT((op & ~(0xff | SLJIT_32 | SLJIT_SHIFT_INTO_NON_ZERO)) == 0);
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src1_reg));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src2_reg));
+ FUNCTION_CHECK_SRC(src3, src3w);
+ CHECK_ARGUMENT(dst_reg != src2_reg);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s%s.into%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32",
+ (op & SLJIT_SHIFT_INTO_NON_ZERO) ? ".nz" : "");
+
+ sljit_verbose_reg(compiler, dst_reg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_reg(compiler, src1_reg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_reg(compiler, src2_reg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src3, src3w);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ SLJIT_UNUSED_ARG(shift_arg);
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT((op & ~SLJIT_SRC2_UNDEFINED) == (SLJIT_ADD | SLJIT_SHL_IMM));
+ FUNCTION_CHECK_DST(dst, dstw);
+ FUNCTION_CHECK_SRC(src1, src1w);
+ FUNCTION_CHECK_SRC(src2, src2w);
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s.shl_imm%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],
+ (op & SLJIT_SRC2_UNDEFINED) ? ".src2und" : "");
+
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src1, src1w);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src2, src2w);
+ fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", shift_arg);
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(op >= SLJIT_FAST_RETURN && op <= SLJIT_PREFETCH_ONCE);
+ FUNCTION_CHECK_SRC(src, srcw);
+
+ if (op == SLJIT_FAST_RETURN || op == SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN) {
+ CHECK_ARGUMENT(src != SLJIT_IMM);
+ compiler->last_flags = 0;
+ } else if (op >= SLJIT_PREFETCH_L1 && op <= SLJIT_PREFETCH_ONCE) {
+ CHECK_ARGUMENT(src & SLJIT_MEM);
+ }
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s ", op_src_dst_names[op - SLJIT_OP_SRC_DST_BASE]);
+ sljit_verbose_param(compiler, src, srcw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(op >= SLJIT_FAST_ENTER && op <= SLJIT_GET_RETURN_ADDRESS);
+ FUNCTION_CHECK_DST(dst, dstw);
+
+ if (op == SLJIT_FAST_ENTER)
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s ", op_src_dst_names[op - SLJIT_OP_SRC_DST_BASE]);
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
+{
+ SLJIT_UNUSED_ARG(type);
+ SLJIT_UNUSED_ARG(reg);
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ if (type == SLJIT_GP_REGISTER) {
+ CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_REGISTERS)
+ || (reg >= SLJIT_TMP_REGISTER_BASE && reg < (SLJIT_TMP_REGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_REGISTERS)));
+ }
+#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)
+ else if (((type >> 12) == 0 || ((type >> 12) >= 3 && (type >> 12) <= 6))) {
+ CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_VECTOR_REGISTERS)
+ || (reg >= SLJIT_TMP_VREGISTER_BASE && reg < (SLJIT_TMP_VREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS)));
+ }
+#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS */
+ else {
+ CHECK_ARGUMENT(type == SLJIT_FLOAT_REGISTER || ((type >> 12) == 0 || ((type >> 12) >= 3 && (type >> 12) <= 6) || (type & (3 << 12)) || (type & (4 << 12)) || (type & (5 << 12)) || (type & (6 << 12))));
+ CHECK_ARGUMENT((reg > 0 && reg <= SLJIT_NUMBER_OF_FLOAT_REGISTERS)
+ || (reg >= SLJIT_TMP_FREGISTER_BASE && reg < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)));
+ }
+#endif /* SLJIT_ARGUMENT_CHECKS */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_u32 size)
+{
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ sljit_u32 i;
+#endif /* SLJIT_VERBOSE */
+
+ SLJIT_UNUSED_ARG(compiler);
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(instruction);
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+ CHECK_ARGUMENT(size > 0 && size < 16);
+#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
+ CHECK_ARGUMENT((size == 2 && (((sljit_sw)instruction) & 0x1) == 0)
+ || (size == 4 && (((sljit_sw)instruction) & 0x3) == 0));
+#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
+ CHECK_ARGUMENT(size == 2 || size == 4 || size == 6);
+#else /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM_THUMB2 && !SLJIT_CONFIG_RISCV && !SLJIT_CONFIG_S390X */
+ CHECK_ARGUMENT(size == 4 && (((sljit_sw)instruction) & 0x3) == 0);
+#endif /* SLJIT_CONFIG_X86 */
+
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " op_custom");
+ for (i = 0; i < size; i++)
+ fprintf(compiler->verbose, " 0x%x", ((sljit_u8*)instruction)[i]);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_MOV_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_ABS_F64);
+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));
+ FUNCTION_FCHECK(src, srcw, op & SLJIT_32);
+ FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
+ fprintf(compiler->verbose, " %s%s ", fop1_names[SLJIT_CONV_F64_FROM_F32 - SLJIT_FOP1_BASE],
+ (op & SLJIT_32) ? ".f32.from.f64" : ".f64.from.f32");
+ else
+ fprintf(compiler->verbose, " %s%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
+ (op & SLJIT_32) ? ".f32" : ".f64");
+
+ sljit_verbose_fparam(compiler, dst, dstw);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_fparam(compiler, src, srcw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & SLJIT_32);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) == SLJIT_CMP_F64);
+ CHECK_ARGUMENT(!(op & SLJIT_SET_Z));
+ CHECK_ARGUMENT((op & VARIABLE_FLAG_MASK)
+ || (GET_FLAG_TYPE(op) >= SLJIT_F_EQUAL && GET_FLAG_TYPE(op) <= SLJIT_ORDERED_LESS_EQUAL));
+ FUNCTION_FCHECK(src1, src1w, op & SLJIT_32);
+ FUNCTION_FCHECK(src2, src2w, op & SLJIT_32);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s%s", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_32) ? ".f32" : ".f64");
+ if (op & VARIABLE_FLAG_MASK) {
+ fprintf(compiler->verbose, ".%s", jump_names[GET_FLAG_TYPE(op)]);
+ }
+ fprintf(compiler->verbose, " ");
+ sljit_verbose_fparam(compiler, src1, src1w);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_fparam(compiler, src2, src2w);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));
+ FUNCTION_FCHECK(src, srcw, op & SLJIT_32);
+ FUNCTION_CHECK_DST(dst, dstw);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
+ fop1_conv_types[GET_OPCODE(op) - SLJIT_CONV_SW_FROM_F64],
+ (op & SLJIT_32) ? ".f32" : ".f64");
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_fparam(compiler, src, srcw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));
+ FUNCTION_CHECK_SRC(src, srcw);
+ FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s%s.from.%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
+ (op & SLJIT_32) ? ".f32" : ".f64",
+ fop1_conv_types[GET_OPCODE(op) - SLJIT_CONV_SW_FROM_F64]);
+ sljit_verbose_fparam(compiler, dst, dstw);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src, srcw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_ADD_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_DIV_F64);
+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));
+ FUNCTION_FCHECK(src1, src1w, op & SLJIT_32);
+ FUNCTION_FCHECK(src2, src2w, op & SLJIT_32);
+ FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s%s ", fop2_names[GET_OPCODE(op) - SLJIT_FOP2_BASE], (op & SLJIT_32) ? ".f32" : ".f64");
+ sljit_verbose_fparam(compiler, dst, dstw);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_fparam(compiler, src1, src1w);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_fparam(compiler, src2, src2w);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) == SLJIT_COPYSIGN_F64);
+ FUNCTION_FCHECK(src1, src1w, op & SLJIT_32);
+ FUNCTION_FCHECK(src2, src2w, op & SLJIT_32);
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, op & SLJIT_32));
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s%s ", fop2r_names[GET_OPCODE(op) - SLJIT_FOP2R_BASE], (op & SLJIT_32) ? ".f32" : ".f64");
+ sljit_verbose_freg(compiler, dst_freg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_fparam(compiler, src1, src1w);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_fparam(compiler, src2, src2w);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fset32(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f32 value)
+{
+ SLJIT_UNUSED_ARG(value);
+
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 1));
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " fset32 ");
+ sljit_verbose_freg(compiler, freg);
+ fprintf(compiler->verbose, ", %f\n", value);
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value)
+{
+ SLJIT_UNUSED_ARG(value);
+
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, 0));
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " fset64 ");
+ sljit_verbose_freg(compiler, freg);
+ fprintf(compiler->verbose, ", %f\n", value);
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_COPY_TO_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_COPY_FROM_F64);
+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, op & SLJIT_32));
+
+#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
+#else /* !SLJIT_64BIT_ARCHITECTURE */
+ switch (op) {
+ case SLJIT_COPY32_TO_F32:
+ case SLJIT_COPY32_FROM_F32:
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
+ break;
+ case SLJIT_COPY_TO_F64:
+ case SLJIT_COPY_FROM_F64:
+ if (reg & REG_PAIR_MASK) {
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_FIRST(reg)));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_SECOND(reg)));
+
+ if (op == SLJIT_COPY_TO_F64)
+ break;
+
+ CHECK_ARGUMENT(REG_PAIR_FIRST(reg) != REG_PAIR_SECOND(reg));
+ break;
+ }
+
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
+ break;
+ }
+#endif /* SLJIT_64BIT_ARCHITECTURE */
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " copy%s_%s_f%s ", (op & SLJIT_32) ? "32" : "",
+ GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? "to" : "from", (op & SLJIT_32) ? "32" : "64");
+
+ sljit_verbose_freg(compiler, freg);
+
+ if (reg & REG_PAIR_MASK) {
+ fprintf(compiler->verbose, ", {");
+ sljit_verbose_reg(compiler, REG_PAIR_FIRST(reg));
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_reg(compiler, REG_PAIR_SECOND(reg));
+ fprintf(compiler->verbose, "}\n");
+ } else {
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_reg(compiler, reg);
+ fprintf(compiler->verbose, "\n");
+ }
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compiler *compiler)
+{
+ SLJIT_UNUSED_ARG(compiler);
+
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose))
+ fprintf(compiler->verbose, "label:\n");
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(buffers);
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(alignment >= SLJIT_LABEL_ALIGN_1 && alignment <= SLJIT_LABEL_ALIGN_16);
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, "label.al%d:%s", 1 << alignment, buffers == NULL ? "\n" : " [");
+
+ if (buffers != NULL) {
+ fprintf(compiler->verbose, "%ld", (long int)buffers->size);
+ buffers = buffers->next;
+
+ while (buffers != NULL) {
+ fprintf(compiler->verbose, ", %ld", (long int)buffers->size);
+ buffers = buffers->next;
+ }
+
+ fprintf(compiler->verbose, "]\n");
+ }
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
+ || (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM)
+#define CHECK_UNORDERED(type, last_flags) \
+ ((((type) & 0xfe) == SLJIT_ORDERED) && \
+ ((last_flags) & 0xff) >= SLJIT_UNORDERED && ((last_flags) & 0xff) <= SLJIT_ORDERED_LESS_EQUAL)
+#else /* !SLJIT_CONFIG_X86 || SLJIT_CONFIG_ARM */
+#define CHECK_UNORDERED(type, last_flags) 0
+#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_ARM */
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP)));
+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_FAST_CALL);
+
+ if ((type & 0xff) < SLJIT_JUMP) {
+ if ((type & 0xff) <= SLJIT_NOT_ZERO)
+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
+ else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {
+ CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY);
+ compiler->last_flags &= ~SLJIT_SET_Z;
+ } else
+ CHECK_ARGUMENT((type & 0xfe) == (compiler->last_flags & 0xff)
+ || CHECK_UNORDERED(type, compiler->last_flags));
+ }
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose))
+ fprintf(compiler->verbose, " jump%s %s\n", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",
+ jump_names[type & 0xff]);
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_CALL_RETURN)));
+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_CALL && (type & 0xff) <= SLJIT_CALL_REG_ARG);
+ CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));
+
+ if (type & SLJIT_CALL_RETURN) {
+ CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);
+
+ if (compiler->options & SLJIT_ENTER_REG_ARG) {
+ CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL_REG_ARG);
+ } else {
+ CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG);
+ }
+ }
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s%s%s ret[%s", jump_names[type & 0xff],
+ !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",
+ !(type & SLJIT_CALL_RETURN) ? "" : ".ret",
+ call_arg_names[arg_types & SLJIT_ARG_MASK]);
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ if (arg_types) {
+ fprintf(compiler->verbose, "], args[");
+ do {
+ fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);
+ arg_types >>= SLJIT_ARG_SHIFT;
+ if (arg_types)
+ fprintf(compiler->verbose, ",");
+ } while (arg_types);
+ }
+ fprintf(compiler->verbose, "]\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32)));
+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_SIG_LESS_EQUAL);
+ FUNCTION_CHECK_SRC(src1, src1w);
+ FUNCTION_CHECK_SRC(src2, src2w);
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " cmp%s%s %s, ", (type & SLJIT_32) ? "32" : "",
+ !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]);
+ sljit_verbose_param(compiler, src1, src1w);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src2, src2w);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32)));
+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_F_EQUAL && (type & 0xff) <= SLJIT_ORDERED_LESS_EQUAL);
+ FUNCTION_FCHECK(src1, src1w, type & SLJIT_32);
+ FUNCTION_FCHECK(src2, src2w, type & SLJIT_32);
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " fcmp%s%s %s, ", (type & SLJIT_32) ? ".f32" : ".f64",
+ !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", jump_names[type & 0xff]);
+ sljit_verbose_fparam(compiler, src1, src1w);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_fparam(compiler, src2, src2w);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2cmpz(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ SLJIT_COMPILE_ASSERT((SLJIT_JUMP_IF_ZERO == SLJIT_SET_Z) && (SLJIT_JUMP_IF_NON_ZERO == 0),
+ incorrect_values_for_sljit_jump_zero_or_non_zero);
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, SLJIT_REWRITABLE_JUMP) >= SLJIT_ADD && SLJIT_CHECK_OPCODE(op, SLJIT_REWRITABLE_JUMP) <= SLJIT_ROTR);
+ /* Not all opcodes allow setting zero flags. */
+ CHECK_ARGUMENT(check_sljit_emit_op2_operation(compiler, ((op | SLJIT_SET_Z) & ~SLJIT_REWRITABLE_JUMP)));
+ FUNCTION_CHECK_DST(dst, dstw);
+ FUNCTION_CHECK_SRC(src1, src1w);
+ FUNCTION_CHECK_SRC(src2, src2w);
+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & SLJIT_32);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " cmp%sz.%s%s%s%s%s ", (op & SLJIT_JUMP_IF_ZERO) ? "" : "n",
+ op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32",
+ !(op & VARIABLE_FLAG_MASK) ? "" : ".", !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op & ~SLJIT_REWRITABLE_JUMP)],
+ !(op & SLJIT_REWRITABLE_JUMP) ? "" : ".r");
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src1, src1w);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src2, src2w);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 src, sljit_sw srcw)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(type >= SLJIT_JUMP && type <= SLJIT_FAST_CALL);
+ FUNCTION_CHECK_SRC(src, srcw);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " ijump.%s ", jump_names[type]);
+ sljit_verbose_param(compiler, src, srcw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types,
+ sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_CALL_RETURN)));
+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_CALL && (type & 0xff) <= SLJIT_CALL_REG_ARG);
+ CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));
+ FUNCTION_CHECK_SRC(src, srcw);
+
+ if (type & SLJIT_CALL_RETURN) {
+ CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);
+
+ if (compiler->options & SLJIT_ENTER_REG_ARG) {
+ CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL_REG_ARG);
+ } else {
+ CHECK_ARGUMENT((type & 0xff) != SLJIT_CALL_REG_ARG);
+ }
+ }
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " i%s%s ret[%s", jump_names[type & 0xff],
+ !(type & SLJIT_CALL_RETURN) ? "" : ".ret",
+ call_arg_names[arg_types & SLJIT_ARG_MASK]);
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ if (arg_types) {
+ fprintf(compiler->verbose, "], args[");
+ do {
+ fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);
+ arg_types >>= SLJIT_ARG_SHIFT;
+ if (arg_types)
+ fprintf(compiler->verbose, ",");
+ } while (arg_types);
+ }
+ fprintf(compiler->verbose, "], ");
+ sljit_verbose_param(compiler, src, srcw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 type)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(type >= SLJIT_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL);
+ CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV32
+ || (SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_AND && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_XOR));
+ CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));
+
+ if (type <= SLJIT_NOT_ZERO)
+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
+ else
+ CHECK_ARGUMENT((type & 0xfe) == (compiler->last_flags & 0xff)
+ || CHECK_UNORDERED(type, compiler->last_flags));
+
+ FUNCTION_CHECK_DST(dst, dstw);
+
+ if (GET_OPCODE(op) >= SLJIT_ADD)
+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " flags.%s%s%s ",
+ GET_OPCODE(op) < SLJIT_OP2_BASE ? "mov" : op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],
+ GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_32) ? "32" : ""),
+ !(op & SLJIT_SET_Z) ? "" : ".z");
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, ", %s\n", jump_names[type]);
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_reg)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ sljit_s32 cond = type & ~(SLJIT_32 | SLJIT_COMPARE_SELECT);
+ CHECK_ARGUMENT((type & SLJIT_COMPARE_SELECT) ? (cond >= SLJIT_LESS && cond <= SLJIT_SET_SIG_LESS_EQUAL)
+ : (cond >= SLJIT_EQUAL && cond <= SLJIT_ORDERED_LESS_EQUAL));
+ CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1);
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));
+ FUNCTION_CHECK_SRC(src1, src1w);
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src2_reg));
+
+ if (!(type & SLJIT_COMPARE_SELECT)) {
+ if (cond <= SLJIT_NOT_ZERO)
+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
+ else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {
+ CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY);
+ compiler->last_flags &= ~SLJIT_SET_Z;
+ } else
+ CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff)
+ || CHECK_UNORDERED(cond, compiler->last_flags));
+ } else
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %sselect%s %s, ",
+ !(type & SLJIT_COMPARE_SELECT) ? "" : "cmp_",
+ !(type & SLJIT_32) ? "" : "32",
+ jump_names[type & ~SLJIT_32]);
+ sljit_verbose_reg(compiler, dst_reg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src1, src1w);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_reg(compiler, src2_reg);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_freg)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ sljit_s32 cond = type & ~SLJIT_32;
+
+ CHECK_ARGUMENT(cond >= SLJIT_EQUAL && cond <= SLJIT_ORDERED_LESS_EQUAL);
+
+ CHECK_ARGUMENT(compiler->fscratches != -1 && compiler->fsaveds != -1);
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(dst_freg, type & SLJIT_32));
+ FUNCTION_FCHECK(src1, src1w, type & SLJIT_32);
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(src2_freg, type & SLJIT_32));
+
+ if (cond <= SLJIT_NOT_ZERO)
+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
+ else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {
+ CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY);
+ compiler->last_flags = 0;
+ } else
+ CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff)
+ || CHECK_UNORDERED(cond, compiler->last_flags));
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " fselect%s %s, ",
+ !(type & SLJIT_32) ? "" : "32",
+ jump_names[type & ~SLJIT_32]);
+ sljit_verbose_freg(compiler, dst_freg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_fparam(compiler, src1, src1w);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_freg(compiler, src2_freg);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ sljit_s32 allowed_flags;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ if (type & SLJIT_MEM_UNALIGNED) {
+ CHECK_ARGUMENT(!(type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)));
+ } else if (type & SLJIT_MEM_ALIGNED_16) {
+ CHECK_ARGUMENT(!(type & SLJIT_MEM_ALIGNED_32));
+ } else {
+ CHECK_ARGUMENT((reg & REG_PAIR_MASK) || (type & SLJIT_MEM_ALIGNED_32));
+ }
+
+ allowed_flags = SLJIT_MEM_UNALIGNED;
+
+ switch (type & 0xff) {
+ case SLJIT_MOV_P:
+ case SLJIT_MOV:
+ allowed_flags |= SLJIT_MEM_ALIGNED_32;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ allowed_flags |= SLJIT_MEM_ALIGNED_16;
+ break;
+ }
+
+ CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | allowed_flags)) == 0);
+
+ if (reg & REG_PAIR_MASK) {
+ CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV);
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_FIRST(reg)));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(REG_PAIR_SECOND(reg)));
+ CHECK_ARGUMENT(REG_PAIR_FIRST(reg) != REG_PAIR_SECOND(reg));
+ } else {
+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);
+ CHECK_ARGUMENT(!(type & SLJIT_32) || ((type & 0xff) >= SLJIT_MOV_U8 && (type & 0xff) <= SLJIT_MOV_S16));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
+ }
+
+ FUNCTION_CHECK_SRC_MEM(mem, memw);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ if ((type & 0xff) == SLJIT_MOV32)
+ fprintf(compiler->verbose, " %s32",
+ (type & SLJIT_MEM_STORE) ? "store" : "load");
+ else
+ fprintf(compiler->verbose, " %s%s%s",
+ (type & SLJIT_MEM_STORE) ? "store" : "load",
+ !(type & SLJIT_32) ? "" : "32", op1_types[(type & 0xff) - SLJIT_OP1_BASE]);
+
+ if (type & SLJIT_MEM_UNALIGNED)
+ fprintf(compiler->verbose, ".unal");
+ else if (type & SLJIT_MEM_ALIGNED_16)
+ fprintf(compiler->verbose, ".al16");
+ else if (type & SLJIT_MEM_ALIGNED_32)
+ fprintf(compiler->verbose, ".al32");
+
+ if (reg & REG_PAIR_MASK) {
+ fprintf(compiler->verbose, " {");
+ sljit_verbose_reg(compiler, REG_PAIR_FIRST(reg));
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_reg(compiler, REG_PAIR_SECOND(reg));
+ fprintf(compiler->verbose, "}, ");
+ } else {
+ fprintf(compiler->verbose, " ");
+ sljit_verbose_reg(compiler, reg);
+ fprintf(compiler->verbose, ", ");
+ }
+ sljit_verbose_param(compiler, mem, memw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);
+ CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_POST)) == 0);
+ CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg);
+
+ FUNCTION_CHECK_SRC_MEM(mem, memw);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ if (type & SLJIT_MEM_SUPP)
+ CHECK_RETURN_OK;
+ if (sljit_emit_mem_update(compiler, type | SLJIT_MEM_SUPP, reg, mem, memw) == SLJIT_ERR_UNSUPPORTED) {
+ fprintf(compiler->verbose, " # mem: unsupported form, no instructions are emitted\n");
+ CHECK_RETURN_OK;
+ }
+
+ if ((type & 0xff) == SLJIT_MOV32)
+ fprintf(compiler->verbose, " %s32.%s ",
+ (type & SLJIT_MEM_STORE) ? "store" : "load",
+ (type & SLJIT_MEM_POST) ? "post" : "pre");
+ else
+ fprintf(compiler->verbose, " %s%s%s.%s ",
+ (type & SLJIT_MEM_STORE) ? "store" : "load",
+ !(type & SLJIT_32) ? "" : "32",
+ op1_types[(type & 0xff) - SLJIT_OP1_BASE],
+ (type & SLJIT_MEM_POST) ? "post" : "pre");
+
+ sljit_verbose_reg(compiler, reg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, mem, memw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 freg,
+ sljit_s32 mem, sljit_sw memw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+ CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);
+
+ if (type & SLJIT_MEM_UNALIGNED) {
+ CHECK_ARGUMENT(!(type & (SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)));
+ } else if (type & SLJIT_MEM_ALIGNED_16) {
+ CHECK_ARGUMENT(!(type & SLJIT_MEM_ALIGNED_32));
+ } else {
+ CHECK_ARGUMENT(type & SLJIT_MEM_ALIGNED_32);
+ CHECK_ARGUMENT(!(type & SLJIT_32));
+ }
+
+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, type & SLJIT_32));
+ FUNCTION_CHECK_SRC_MEM(mem, memw);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s.%s",
+ (type & SLJIT_MEM_STORE) ? "store" : "load",
+ !(type & SLJIT_32) ? "f64" : "f32");
+
+ if (type & SLJIT_MEM_UNALIGNED)
+ printf(".unal");
+ else if (type & SLJIT_MEM_ALIGNED_16)
+ printf(".al16");
+ else if (type & SLJIT_MEM_ALIGNED_32)
+ printf(".al32");
+
+ fprintf(compiler->verbose, " ");
+ sljit_verbose_freg(compiler, freg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, mem, memw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 freg,
+ sljit_s32 mem, sljit_sw memw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
+ CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);
+ CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_POST)) == 0);
+ FUNCTION_CHECK_SRC_MEM(mem, memw);
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, type & SLJIT_32));
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ if (type & SLJIT_MEM_SUPP)
+ CHECK_RETURN_OK;
+ if (sljit_emit_fmem_update(compiler, type | SLJIT_MEM_SUPP, freg, mem, memw) == SLJIT_ERR_UNSUPPORTED) {
+ fprintf(compiler->verbose, " # fmem: unsupported form, no instructions are emitted\n");
+ CHECK_RETURN_OK;
+ }
+
+ fprintf(compiler->verbose, " %s.%s.%s ",
+ (type & SLJIT_MEM_STORE) ? "store" : "load",
+ !(type & SLJIT_32) ? "f64" : "f32",
+ (type & SLJIT_MEM_POST) ? "post" : "pre");
+
+ sljit_verbose_freg(compiler, freg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, mem, memw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));
+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK2(SLJIT_SIMD_STORE)) == 0);
+ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));
+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) <= SLJIT_SIMD_GET_REG_SIZE(type));
+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) <= (srcdst & SLJIT_MEM) ? SLJIT_SIMD_GET_REG_SIZE(type) : 0);
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type));
+ FUNCTION_VCHECK(srcdst, srcdstw, type);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ if (type & SLJIT_SIMD_TEST)
+ CHECK_RETURN_OK;
+ if (sljit_emit_simd_mov(compiler, type | SLJIT_SIMD_TEST, vreg, srcdst, srcdstw) == SLJIT_ERR_UNSUPPORTED) {
+ fprintf(compiler->verbose, " # simd_mem: unsupported form, no instructions are emitted\n");
+ CHECK_RETURN_OK;
+ }
+
+ fprintf(compiler->verbose, " simd_%s.%d.%s%d",
+ (type & SLJIT_SIMD_STORE) ? "store" : "load",
+ (8 << SLJIT_SIMD_GET_REG_SIZE(type)),
+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",
+ (8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));
+
+ if ((type & 0x3f000000) == SLJIT_SIMD_MEM_UNALIGNED)
+ fprintf(compiler->verbose, ".unal ");
+ else
+ fprintf(compiler->verbose, ".al%d ", (8 << SLJIT_SIMD_GET_ELEM2_SIZE(type)));
+
+ sljit_verbose_vreg(compiler, vreg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_vparam(compiler, srcdst, srcdstw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));
+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) == 0);
+ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));
+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type));
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (src == SLJIT_IMM) {
+ CHECK_ARGUMENT(srcw == 0);
+ } else {
+ FUNCTION_FCHECK(src, srcw, SLJIT_SIMD_GET_ELEM_SIZE(type) == 2);
+ }
+ } else if (src != SLJIT_IMM) {
+ FUNCTION_CHECK_DST(src, srcw);
+ }
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ if (type & SLJIT_SIMD_TEST)
+ CHECK_RETURN_OK;
+ if (sljit_emit_simd_replicate(compiler, type | SLJIT_SIMD_TEST, vreg, src, srcw) == SLJIT_ERR_UNSUPPORTED) {
+ fprintf(compiler->verbose, " # simd_dup: unsupported form, no instructions are emitted\n");
+ CHECK_RETURN_OK;
+ }
+
+ fprintf(compiler->verbose, " simd_replicate.%d.%s%d ",
+ (8 << SLJIT_SIMD_GET_REG_SIZE(type)),
+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",
+ (8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));
+
+ sljit_verbose_vreg(compiler, vreg);
+ fprintf(compiler->verbose, ", ");
+ if (type & SLJIT_SIMD_FLOAT)
+ sljit_verbose_fparam(compiler, src, srcw);
+ else
+ sljit_verbose_param(compiler, src, srcw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg, sljit_s32 lane_index,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));
+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO | SLJIT_SIMD_LANE_SIGNED | SLJIT_32)) == 0);
+ CHECK_ARGUMENT((type & (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO)) != (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_ZERO));
+ CHECK_ARGUMENT((type & (SLJIT_SIMD_STORE | SLJIT_SIMD_LANE_SIGNED)) != SLJIT_SIMD_LANE_SIGNED);
+ CHECK_ARGUMENT(!(type & SLJIT_SIMD_FLOAT) || !(type & (SLJIT_SIMD_LANE_SIGNED | SLJIT_32)));
+ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));
+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));
+ CHECK_ARGUMENT(!(type & SLJIT_32) || SLJIT_SIMD_GET_ELEM_SIZE(type) <= 2);
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type));
+ CHECK_ARGUMENT(lane_index >= 0 && lane_index < (1 << (SLJIT_SIMD_GET_REG_SIZE(type) - SLJIT_SIMD_GET_ELEM_SIZE(type))));
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ FUNCTION_FCHECK(srcdst, srcdstw, SLJIT_SIMD_GET_ELEM_SIZE(type) == 2);
+ } else if ((type & SLJIT_SIMD_STORE) || srcdst != SLJIT_IMM) {
+ FUNCTION_CHECK_DST(srcdst, srcdstw);
+ }
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ if (type & SLJIT_SIMD_TEST)
+ CHECK_RETURN_OK;
+ if (sljit_emit_simd_lane_mov(compiler, type | SLJIT_SIMD_TEST, vreg, lane_index, srcdst, srcdstw) == SLJIT_ERR_UNSUPPORTED) {
+ fprintf(compiler->verbose, " # simd_move_lane: unsupported form, no instructions are emitted\n");
+ CHECK_RETURN_OK;
+ }
+
+ fprintf(compiler->verbose, " simd_%s_lane%s%s%s.%d.%s%d ",
+ (type & SLJIT_SIMD_STORE) ? "store" : "load",
+ (type & SLJIT_32) ? "32" : "",
+ (type & SLJIT_SIMD_LANE_ZERO) ? "_z" : "",
+ (type & SLJIT_SIMD_LANE_SIGNED) ? "_s" : "",
+ (8 << SLJIT_SIMD_GET_REG_SIZE(type)),
+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",
+ (8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));
+
+ sljit_verbose_vreg(compiler, vreg);
+ fprintf(compiler->verbose, "[%d], ", lane_index);
+ if (type & SLJIT_SIMD_FLOAT)
+ sljit_verbose_fparam(compiler, srcdst, srcdstw);
+ else
+ sljit_verbose_param(compiler, srcdst, srcdstw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_s32 src_lane_index)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));
+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(0)) == 0);
+ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));
+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(src, type));
+ CHECK_ARGUMENT(src_lane_index >= 0 && src_lane_index < (1 << (SLJIT_SIMD_GET_REG_SIZE(type) - SLJIT_SIMD_GET_ELEM_SIZE(type))));
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ if (type & SLJIT_SIMD_TEST)
+ CHECK_RETURN_OK;
+ if (sljit_emit_simd_lane_replicate(compiler, type | SLJIT_SIMD_TEST, vreg, src, src_lane_index) == SLJIT_ERR_UNSUPPORTED) {
+ fprintf(compiler->verbose, " # simd_lane_replicate: unsupported form, no instructions are emitted\n");
+ CHECK_RETURN_OK;
+ }
+
+ fprintf(compiler->verbose, " simd_lane_replicate.%d.%s%d ",
+ (8 << SLJIT_SIMD_GET_REG_SIZE(type)),
+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",
+ (8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));
+
+ sljit_verbose_vreg(compiler, vreg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_vreg(compiler, src);
+ fprintf(compiler->verbose, "[%d]\n", src_lane_index);
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));
+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK2(SLJIT_SIMD_EXTEND_SIGNED)) == 0);
+ CHECK_ARGUMENT((type & (SLJIT_SIMD_EXTEND_SIGNED | SLJIT_SIMD_FLOAT)) != (SLJIT_SIMD_EXTEND_SIGNED | SLJIT_SIMD_FLOAT));
+ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));
+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));
+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_ELEM2_SIZE(type));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type));
+ FUNCTION_VCHECK(src, srcw, type);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ if (type & SLJIT_SIMD_TEST)
+ CHECK_RETURN_OK;
+ if (sljit_emit_simd_extend(compiler, type | SLJIT_SIMD_TEST, vreg, src, srcw) == SLJIT_ERR_UNSUPPORTED) {
+ fprintf(compiler->verbose, " # simd_extend: unsupported form, no instructions are emitted\n");
+ CHECK_RETURN_OK;
+ }
+
+ fprintf(compiler->verbose, " simd_load_extend%s.%d.%s%d.%s%d ",
+ (type & SLJIT_SIMD_EXTEND_SIGNED) ? "_s" : "",
+ (8 << SLJIT_SIMD_GET_REG_SIZE(type)),
+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",
+ (8 << SLJIT_SIMD_GET_ELEM2_SIZE(type)),
+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",
+ (8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));
+
+ sljit_verbose_vreg(compiler, vreg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_vparam(compiler, src, srcw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 dst, sljit_sw dstw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));
+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK(SLJIT_32)) == SLJIT_SIMD_STORE);
+ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));
+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) < SLJIT_SIMD_GET_REG_SIZE(type));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(vreg, type));
+ FUNCTION_CHECK_DST(dst, dstw);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ if (type & SLJIT_SIMD_TEST)
+ CHECK_RETURN_OK;
+ if (sljit_emit_simd_sign(compiler, type | SLJIT_SIMD_TEST, vreg, dst, dstw) == SLJIT_ERR_UNSUPPORTED) {
+ fprintf(compiler->verbose, " # simd_sign: unsupported form, no instructions are emitted\n");
+ CHECK_RETURN_OK;
+ }
+
+ fprintf(compiler->verbose, " simd_store_sign%s.%d.%s%d ",
+ (type & SLJIT_32) ? "32" : "",
+ (8 << SLJIT_SIMD_GET_REG_SIZE(type)),
+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",
+ (8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));
+
+ sljit_verbose_vreg(compiler, vreg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_SIMD));
+ CHECK_ARGUMENT((type & SLJIT_SIMD_TYPE_MASK2(0)) >= SLJIT_SIMD_OP2_AND && (type & SLJIT_SIMD_TYPE_MASK2(0)) <= SLJIT_SIMD_OP2_SHUFFLE);
+ CHECK_ARGUMENT(SLJIT_SIMD_CHECK_REG(type));
+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM_SIZE(type) <= SLJIT_SIMD_GET_REG_SIZE(type));
+ CHECK_ARGUMENT(SLJIT_SIMD_GET_OPCODE(type) != SLJIT_SIMD_OP2_SHUFFLE || (SLJIT_SIMD_GET_ELEM_SIZE(type) == 0 && !(type & SLJIT_SIMD_FLOAT)));
+ CHECK_ARGUMENT(SLJIT_SIMD_GET_ELEM2_SIZE(type) <= (src2 & SLJIT_MEM) ? SLJIT_SIMD_GET_REG_SIZE(type) : 0);
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(dst_vreg, type));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_VREG(src1_vreg, type));
+ FUNCTION_VCHECK(src2, src2w, type);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ if (type & SLJIT_SIMD_TEST)
+ CHECK_RETURN_OK;
+ if (sljit_emit_simd_op2(compiler, type | SLJIT_SIMD_TEST, dst_vreg, src1_vreg, src2, src2w) == SLJIT_ERR_UNSUPPORTED) {
+ fprintf(compiler->verbose, " # simd_op2: unsupported form, no instructions are emitted\n");
+ CHECK_RETURN_OK;
+ }
+
+ fprintf(compiler->verbose, " simd_%s.%d.%s%d",
+ simd_op2_names[SLJIT_SIMD_GET_OPCODE(type) - 1],
+ (8 << SLJIT_SIMD_GET_REG_SIZE(type)),
+ (type & SLJIT_SIMD_FLOAT) ? "f" : "",
+ (8 << SLJIT_SIMD_GET_ELEM_SIZE(type)));
+
+ if ((type & 0x3f000000) != SLJIT_SIMD_MEM_UNALIGNED)
+ fprintf(compiler->verbose, ".al%d", (8 << SLJIT_SIMD_GET_ELEM2_SIZE(type)));
+
+ fprintf(compiler->verbose, " ");
+ sljit_verbose_vreg(compiler, dst_vreg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_vreg(compiler, src1_vreg);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_vparam(compiler, src2, src2w);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
+{
+ /* Any offset is allowed. */
+ SLJIT_UNUSED_ARG(offset);
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ FUNCTION_CHECK_DST(dst, dstw);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " local_base ");
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", offset);
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
+{
+ SLJIT_UNUSED_ARG(init_value);
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV_S32
+ || op == SLJIT_MOV32 || (op | SLJIT_32) == SLJIT_MOV32_U8);
+ FUNCTION_CHECK_DST(dst, dstw);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " const%s%s ",
+ !(op & SLJIT_32) ? "" : "32", op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", init_value);
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(op == SLJIT_MOV_ADDR || op == SLJIT_MOV_ABS_ADDR || op == SLJIT_ADD_ABS_ADDR);
+ FUNCTION_CHECK_DST(dst, dstw);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s ", op_addr_types[op]);
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
+#else /* !SLJIT_ARGUMENT_CHECKS && !SLJIT_VERBOSE */
+
+#define SLJIT_SKIP_CHECKS(compiler)
+
+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_VERBOSE */
+
+#define SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw) \
+ SLJIT_COMPILE_ASSERT(!(SLJIT_CONV_SW_FROM_F64 & 0x1) && !(SLJIT_CONV_F64_FROM_SW & 0x1) && !(SLJIT_CONV_F64_FROM_UW & 0x1), \
+ invalid_float_opcodes); \
+ if (GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CMP_F64) { \
+ if (GET_OPCODE(op) == SLJIT_CMP_F64) { \
+ CHECK(check_sljit_emit_fop1_cmp(compiler, op, dst, dstw, src, srcw)); \
+ ADJUST_LOCAL_OFFSET(dst, dstw); \
+ ADJUST_LOCAL_OFFSET(src, srcw); \
+ return sljit_emit_fop1_cmp(compiler, op, dst, dstw, src, srcw); \
+ } \
+ if ((GET_OPCODE(op) | 0x1) == SLJIT_CONV_S32_FROM_F64) { \
+ CHECK(check_sljit_emit_fop1_conv_sw_from_f64(compiler, op, dst, dstw, src, srcw)); \
+ ADJUST_LOCAL_OFFSET(dst, dstw); \
+ ADJUST_LOCAL_OFFSET(src, srcw); \
+ return sljit_emit_fop1_conv_sw_from_f64(compiler, op, dst, dstw, src, srcw); \
+ } \
+ if ((GET_OPCODE(op) | 0x1) == SLJIT_CONV_F64_FROM_S32) { \
+ CHECK(check_sljit_emit_fop1_conv_f64_from_w(compiler, op, dst, dstw, src, srcw)); \
+ ADJUST_LOCAL_OFFSET(dst, dstw); \
+ ADJUST_LOCAL_OFFSET(src, srcw); \
+ return sljit_emit_fop1_conv_f64_from_sw(compiler, op, dst, dstw, src, srcw); \
+ } \
+ CHECK(check_sljit_emit_fop1_conv_f64_from_w(compiler, op, dst, dstw, src, srcw)); \
+ ADJUST_LOCAL_OFFSET(dst, dstw); \
+ ADJUST_LOCAL_OFFSET(src, srcw); \
+ return sljit_emit_fop1_conv_f64_from_uw(compiler, op, dst, dstw, src, srcw); \
+ } \
+ CHECK(check_sljit_emit_fop1(compiler, op, dst, dstw, src, srcw)); \
+ ADJUST_LOCAL_OFFSET(dst, dstw); \
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6))
+
+static sljit_s32 sljit_emit_mem_unaligned(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ SLJIT_SKIP_CHECKS(compiler);
+
+ if (type & SLJIT_MEM_STORE)
+ return sljit_emit_op1(compiler, type & (0xff | SLJIT_32), mem, memw, reg, 0);
+ return sljit_emit_op1(compiler, type & (0xff | SLJIT_32), reg, 0, mem, memw);
+}
+
+#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) */
+
+#if (!(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) || (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)) \
+ && !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)
+
+static sljit_s32 sljit_emit_fmem_unaligned(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 freg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ SLJIT_SKIP_CHECKS(compiler);
+
+ if (type & SLJIT_MEM_STORE)
+ return sljit_emit_fop1(compiler, type & (0xff | SLJIT_32), mem, memw, freg, 0);
+ return sljit_emit_fop1(compiler, type & (0xff | SLJIT_32), freg, 0, mem, memw);
+}
+
+#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) && !SLJIT_CONFIG_ARM */
+
+static void sljit_reset_read_only_buffers(struct sljit_read_only_buffer *buffers)
+{
+ while (buffers != NULL) {
+ buffers->u.label = NULL;
+ buffers = buffers->next;
+ }
+}
+
+/* CPU description section */
+
+#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
+#define SLJIT_CPUINFO_PART1 " 32bit ("
+#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
+#define SLJIT_CPUINFO_PART1 " 64bit ("
+#else /* !SLJIT_32BIT_ARCHITECTURE && !SLJIT_64BIT_ARCHITECTURE */
+#error "Internal error: CPU type info missing"
+#endif /* SLJIT_32BIT_ARCHITECTURE */
+
+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
+#define SLJIT_CPUINFO_PART2 "little endian + "
+#elif (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN)
+#define SLJIT_CPUINFO_PART2 "big endian + "
+#else /* !SLJIT_LITTLE_ENDIAN && !SLJIT_BIG_ENDIAN */
+#error "Internal error: CPU type info missing"
+#endif /* SLJIT_LITTLE_ENDIAN */
+
+#if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED)
+#define SLJIT_CPUINFO_PART3 "unaligned)"
+#else /* !SLJIT_UNALIGNED */
+#define SLJIT_CPUINFO_PART3 "aligned)"
+#endif /* SLJIT_UNALIGNED */
+
+#define SLJIT_CPUINFO SLJIT_CPUINFO_PART1 SLJIT_CPUINFO_PART2 SLJIT_CPUINFO_PART3
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+# include "sljitNativeX86_common.c"
+#elif (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+# include "sljitNativeARM_32.c"
+#elif (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+# include "sljitNativeARM_32.c"
+#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
+# include "sljitNativeARM_T2_32.c"
+#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
+# include "sljitNativeARM_64.c"
+#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
+# include "sljitNativePPC_common.c"
+#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
+# include "sljitNativeMIPS_common.c"
+#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
+# include "sljitNativeRISCV_common.c"
+#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
+# include "sljitNativeS390X.c"
+#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
+# include "sljitNativeLOONGARCH_64.c"
+#elif (defined SLJIT_CONFIG_ALPHA && SLJIT_CONFIG_ALPHA)
+# include "sljitNativeALPHA_64.c"
+#endif /* SLJIT_CONFIG_X86 */
+
+#include "sljitSerialize.c"
+
+static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
+ /* At the moment the pointer size is always equal to sljit_sw. May be changed in the future. */
+ if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_P))
+ return SLJIT_SUCCESS;
+#else /* !SLJIT_64BIT_ARCHITECTURE */
+ if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P))
+ return SLJIT_SUCCESS;
+#endif /* SLJIT_64BIT_ARCHITECTURE */
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);
+}
+
+#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
+ && !((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && defined __SOFTFP__)
+
+static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
+{
+ if (src == SLJIT_FR0)
+ return SLJIT_SUCCESS;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw);
+}
+
+#endif /* !SLJIT_CONFIG_X86_32 && !(SLJIT_CONFIG_ARM_32 && __SOFTFP__) */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return(compiler, op, src, srcw));
+
+ if (GET_OPCODE(op) < SLJIT_MOV_F64) {
+ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+ } else {
+ FAIL_IF(emit_fmov_before_return(compiler, op, src, srcw));
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_return_void(compiler);
+}
+
+#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
+ && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
+ && !(defined(SLJIT_CONFIG_LOONGARCH_64) && SLJIT_CONFIG_LOONGARCH_64)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fop2r(compiler, op, dst_freg, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_fop2(compiler, op, dst_freg, 0, src1, src1w, src2, src2w);
+}
+
+#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_S390X && !SLJIT_CONFIG_LOONGARCH_64 */
+
+#if !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
+ && !(defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
+ && !(defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ /* Default compare for most architectures. */
+ sljit_s32 flags, tmp_src, condition;
+ sljit_sw tmp_srcw;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
+
+ condition = type & 0xff;
+#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
+ if ((condition == SLJIT_EQUAL || condition == SLJIT_NOT_EQUAL)) {
+ if (src1 == SLJIT_IMM && !src1w) {
+ src1 = src2;
+ src1w = src2w;
+ src2 = SLJIT_IMM;
+ src2w = 0;
+ }
+ if (src2 == SLJIT_IMM && !src2w)
+ return emit_cmp_to0(compiler, type, src1, src1w);
+ }
+#endif /* SLJIT_CONFIG_ARM_64 */
+
+ if (SLJIT_UNLIKELY(src1 == SLJIT_IMM && src2 != SLJIT_IMM)) {
+ /* Immediate is preferred as second argument by most architectures. */
+ switch (condition) {
+ case SLJIT_LESS:
+ condition = SLJIT_GREATER;
+ break;
+ case SLJIT_GREATER_EQUAL:
+ condition = SLJIT_LESS_EQUAL;
+ break;
+ case SLJIT_GREATER:
+ condition = SLJIT_LESS;
+ break;
+ case SLJIT_LESS_EQUAL:
+ condition = SLJIT_GREATER_EQUAL;
+ break;
+ case SLJIT_SIG_LESS:
+ condition = SLJIT_SIG_GREATER;
+ break;
+ case SLJIT_SIG_GREATER_EQUAL:
+ condition = SLJIT_SIG_LESS_EQUAL;
+ break;
+ case SLJIT_SIG_GREATER:
+ condition = SLJIT_SIG_LESS;
+ break;
+ case SLJIT_SIG_LESS_EQUAL:
+ condition = SLJIT_SIG_GREATER_EQUAL;
+ break;
+ }
+
+ type = condition | (type & (SLJIT_32 | SLJIT_REWRITABLE_JUMP));
+ tmp_src = src1;
+ src1 = src2;
+ src2 = tmp_src;
+ tmp_srcw = src1w;
+ src1w = src2w;
+ src2w = tmp_srcw;
+ }
+
+ if (condition <= SLJIT_NOT_ZERO)
+ flags = SLJIT_SET_Z;
+ else
+ flags = (condition & 0xfe) << VARIABLE_FLAG_SHIFT;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ PTR_FAIL_IF(sljit_emit_op2u(compiler,
+ SLJIT_SUB | flags | (type & SLJIT_32), src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_jump(compiler, condition | (type & (SLJIT_REWRITABLE_JUMP | SLJIT_32)));
+}
+
+#endif /* !SLJIT_CONFIG_MIPS */
+
+#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
+{
+ switch (type) {
+ case SLJIT_UNORDERED_OR_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ return 1;
+ }
+
+ return 0;
+}
+
+#endif /* SLJIT_CONFIG_ARM */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xfe) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_32), src1, src1w, src2, src2w);
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_jump(compiler, type);
+}
+
+#if !(defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
+ && !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
+ && !(defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op2cmpz(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_op2cmpz(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ PTR_FAIL_IF(sljit_emit_op2(compiler, ((op | SLJIT_SET_Z) & ~SLJIT_REWRITABLE_JUMP), dst, dstw, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_jump(compiler, ((op & SLJIT_JUMP_IF_ZERO) ? SLJIT_ZERO : SLJIT_NOT_ZERO) | (op & SLJIT_REWRITABLE_JUMP));
+}
+
+#else /* SLJIT_CONFIG_RISCV || SLJIT_CONFIG_MIPS || SLJIT_CONFIG_LOONGARCH */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op2cmpz(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 reg;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_op2cmpz(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ PTR_FAIL_IF(sljit_emit_op2(compiler, (op & ~(SLJIT_SET_Z | SLJIT_REWRITABLE_JUMP)), dst, dstw, src1, src1w, src2, src2w));
+
+ /* When dst is a memory operand, its value is stored in SLJIT_TMP_DEST_FREG. */
+ reg = FAST_IS_REG(dst) ? dst : SLJIT_TMP_DEST_REG;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_cmp(compiler, ((op & SLJIT_JUMP_IF_ZERO) ? SLJIT_ZERO : SLJIT_NOT_ZERO) | (op & (SLJIT_32 | SLJIT_REWRITABLE_JUMP)), reg, 0, SLJIT_IMM, 0);
+}
+
+#endif /* !SLJIT_CONFIG_RISCV && !SLJIT_CONFIG_MIPS && !SLJIT_CONFIG_LOONGARCH */
+
+#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
+ && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));
+ SLJIT_UNUSED_ARG(type);
+ SLJIT_UNUSED_ARG(reg);
+ SLJIT_UNUSED_ARG(mem);
+ SLJIT_UNUSED_ARG(memw);
+
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+#endif /* !SLJIT_CONFIG_ARM && !SLJIT_CONFIG_PPC */
+
+#if !(defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
+ && !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
+ && !(defined SLJIT_CONFIG_ALPHA && SLJIT_CONFIG_ALPHA)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 freg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
+
+ return sljit_emit_fmem_unaligned(compiler, type, freg, mem, memw);
+}
+
+#endif /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS && !SLJIT_CONFIG_ALPHA */
+
+#if !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
+ && !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 freg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw));
+ SLJIT_UNUSED_ARG(type);
+ SLJIT_UNUSED_ARG(freg);
+ SLJIT_UNUSED_ARG(mem);
+ SLJIT_UNUSED_ARG(memw);
+
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+#endif /* !SLJIT_CONFIG_ARM_64 && !SLJIT_CONFIG_PPC */
+
+#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
+ && !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
+ && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
+ && !(defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
+ && !(defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw));
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(type);
+ SLJIT_UNUSED_ARG(vreg);
+ SLJIT_UNUSED_ARG(srcdst);
+ SLJIT_UNUSED_ARG(srcdstw);
+
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw));
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(type);
+ SLJIT_UNUSED_ARG(vreg);
+ SLJIT_UNUSED_ARG(src);
+ SLJIT_UNUSED_ARG(srcw);
+
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg, sljit_s32 lane_index,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw));
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(type);
+ SLJIT_UNUSED_ARG(vreg);
+ SLJIT_UNUSED_ARG(lane_index);
+ SLJIT_UNUSED_ARG(srcdst);
+ SLJIT_UNUSED_ARG(srcdstw);
+
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_s32 src_lane_index)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index));
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(type);
+ SLJIT_UNUSED_ARG(vreg);
+ SLJIT_UNUSED_ARG(src);
+ SLJIT_UNUSED_ARG(src_lane_index);
+
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw));
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(type);
+ SLJIT_UNUSED_ARG(vreg);
+ SLJIT_UNUSED_ARG(src);
+ SLJIT_UNUSED_ARG(srcw);
+
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw));
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(type);
+ SLJIT_UNUSED_ARG(vreg);
+ SLJIT_UNUSED_ARG(dst);
+ SLJIT_UNUSED_ARG(dstw);
+
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(type);
+ SLJIT_UNUSED_ARG(dst_vreg);
+ SLJIT_UNUSED_ARG(src1_vreg);
+ SLJIT_UNUSED_ARG(src2);
+ SLJIT_UNUSED_ARG(src2w);
+
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM && !SLJIT_CONFIG_S390X && !SLJIT_CONFIG_LOONGARCH */
+
+#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
+ && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));
+
+ ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);
+
+ SLJIT_SKIP_CHECKS(compiler);
+
+ if (offset != 0)
+ return sljit_emit_op2(compiler, SLJIT_ADD, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
+ return sljit_emit_op1(compiler, SLJIT_MOV, dst, dstw, SLJIT_SP, 0);
+}
+
+#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM_64 */
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_read_only_buffer_start_writing(sljit_uw addr, sljit_uw size, sljit_sw executable_offset)
+{
+ SLJIT_UNUSED_ARG(size);
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + size), 0);
+ return SLJIT_ADD_EXEC_OFFSET(addr, -executable_offset);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_read_only_buffer_end_writing(sljit_uw addr, sljit_uw size, sljit_sw executable_offset)
+{
+ SLJIT_UNUSED_ARG(addr);
+ SLJIT_UNUSED_ARG(size);
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + size), 1);
+ SLJIT_CACHE_FLUSH((void*)addr, (void*)(addr + size));
+}
+
+#endif /* !SLJIT_CONFIG_UNSUPPORTED */
diff --git a/deps/sljit/sljit_src/sljitLir.h b/deps/sljit/sljit_src/sljitLir.h
new file mode 100644
index 0000000..019ad60
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitLir.h
@@ -0,0 +1,2769 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SLJIT_LIR_H_
+#define SLJIT_LIR_H_
+
+/*
+ ------------------------------------------------------------------------
+ Stack-Less JIT compiler for multiple architectures (x86, ARM, PowerPC)
+ ------------------------------------------------------------------------
+
+ Short description
+ Advantages:
+ - The execution can be continued from any LIR instruction. In other
+ words, it is possible to jump to any label from anywhere, even from
+ a code fragment, which is compiled later, as long as the compiling
+ context is the same. See sljit_emit_enter for more details.
+ - Supports self modifying code: target of any jump and call
+ instructions and some constant values can be dynamically modified
+ during runtime. See SLJIT_REWRITABLE_JUMP.
+ - although it is not suggested to do it frequently
+ - can be used for inline caching: save an important value once
+ in the instruction stream
+ - A fixed stack space can be allocated for local variables
+ - The compiler is thread-safe
+ - The compiler is highly configurable through preprocessor macros.
+ You can disable unneeded features (multithreading in single
+ threaded applications), and you can use your own system functions
+ (including memory allocators). See sljitConfig.h.
+ Disadvantages:
+ - The compiler is more like a platform independent assembler, so
+ there is no built-in variable management. Registers and stack must
+ be managed manually (the name of the compiler refers to this).
+ In practice:
+ - This approach is very effective for interpreters
+ - One of the saved registers typically points to a stack interface
+ - It can jump to any exception handler anytime (even if it belongs
+ to another function)
+ - Hot paths can be modified during runtime reflecting the changes
+ of the fastest execution path of the dynamic language
+ - SLJIT supports complex memory addressing modes
+ - mainly position and context independent code (except some cases)
+
+ For valgrind users:
+ - pass --smc-check=all argument to valgrind, since JIT is a "self-modifying code"
+*/
+
+#if (defined SLJIT_HAVE_CONFIG_PRE && SLJIT_HAVE_CONFIG_PRE)
+#include "sljitConfigPre.h"
+#endif /* SLJIT_HAVE_CONFIG_PRE */
+
+#include "sljitConfigCPU.h"
+#include "sljitConfig.h"
+
+/* The following header file defines useful macros for fine tuning
+SLJIT based code generators. They are listed in the beginning
+of sljitConfigInternal.h */
+
+#include "sljitConfigInternal.h"
+
+#if (defined SLJIT_HAVE_CONFIG_POST && SLJIT_HAVE_CONFIG_POST)
+#include "sljitConfigPost.h"
+#endif /* SLJIT_HAVE_CONFIG_POST */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Version numbers. */
+#define SLJIT_MAJOR_VERSION 0
+#define SLJIT_MINOR_VERSION 95
+
+/* --------------------------------------------------------------------- */
+/* Error codes */
+/* --------------------------------------------------------------------- */
+
+/* Indicates no error. */
+#define SLJIT_SUCCESS 0
+/* After the call of sljit_generate_code(), the error code of the compiler
+ is set to this value to avoid further code generation.
+ The complier should be freed after sljit_generate_code(). */
+#define SLJIT_ERR_COMPILED 1
+/* Cannot allocate non-executable memory. */
+#define SLJIT_ERR_ALLOC_FAILED 2
+/* Cannot allocate executable memory.
+ Only sljit_generate_code() returns with this error code. */
+#define SLJIT_ERR_EX_ALLOC_FAILED 3
+/* Unsupported instruction form. */
+#define SLJIT_ERR_UNSUPPORTED 4
+/* An invalid argument is passed to any SLJIT function. */
+#define SLJIT_ERR_BAD_ARGUMENT 5
+
+/* --------------------------------------------------------------------- */
+/* Registers */
+/* --------------------------------------------------------------------- */
+
+/*
+ Scratch (R) registers: registers which may not preserve their values
+ across function calls.
+
+ Saved (S) registers: registers which preserve their values across
+ function calls.
+
+ The scratch and saved register sets overlap. The last scratch register
+ is the first saved register, the one before the last is the second saved
+ register, and so on.
+
+ For example, in an architecture with only five registers (A-E), if two
+ are scratch and three saved registers, they will be defined as follows:
+
+ A | R0 | | R0 always represent scratch register A
+ B | R1 | | R1 always represent scratch register B
+ C | [R2] | S2 | R2 and S2 represent the same physical register C
+ D | [R3] | S1 | R3 and S1 represent the same physical register D
+ E | [R4] | S0 | R4 and S0 represent the same physical register E
+
+ Note: SLJIT_NUMBER_OF_SCRATCH_REGISTERS will be 2 and
+ SLJIT_NUMBER_OF_SAVED_REGISTERS will be 3.
+
+ Note: For all supported architectures SLJIT_NUMBER_OF_REGISTERS >= 12
+ and SLJIT_NUMBER_OF_SAVED_REGISTERS >= 6. However, 6 registers
+ are virtual on x86-32. See below.
+
+ The purpose of this definition is convenience: saved registers can
+ be used as extra scratch registers. For example, building in the
+ previous example, four registers can be specified as scratch registers
+ and the fifth one as saved register, allowing any user code which requires
+ four scratch registers to run unmodified. The SLJIT compiler automatically
+ saves the content of the two extra scratch register on the stack. Scratch
+ registers can also be preserved by saving their value on the stack but
+ that needs to be done manually.
+
+ Note: To emphasize that registers assigned to R2-R4 are saved
+ registers, they are enclosed by square brackets.
+
+ Note: sljit_emit_enter and sljit_set_context define whether a register
+ is S or R register. E.g: if in the previous example 3 scratches and
+ 1 saved are mapped by sljit_emit_enter, the allowed register set
+ will be: R0-R2 and S0. Although S2 is mapped to the same register
+ than R2, it is not available in that configuration. Furthermore
+ the S1 register cannot be used at all.
+*/
+
+/* Scratch registers. */
+#define SLJIT_R0 1
+#define SLJIT_R1 2
+#define SLJIT_R2 3
+/* Note: on x86-32, R3 - R6 (same as S3 - S6) are emulated (they
+ are allocated on the stack). These registers are called virtual
+ and cannot be used for memory addressing (cannot be part of
+ any SLJIT_MEM1, SLJIT_MEM2 construct). There is no such
+ limitation on other CPUs. See sljit_get_register_index(). */
+#define SLJIT_R3 4
+#define SLJIT_R4 5
+#define SLJIT_R5 6
+#define SLJIT_R6 7
+#define SLJIT_R7 8
+#define SLJIT_R8 9
+#define SLJIT_R9 10
+/* All R registers provided by the architecture can be accessed by SLJIT_R(i)
+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_REGISTERS. */
+#define SLJIT_R(i) (1 + (i))
+
+/* Saved registers. */
+#define SLJIT_S0 (SLJIT_NUMBER_OF_REGISTERS)
+#define SLJIT_S1 (SLJIT_NUMBER_OF_REGISTERS - 1)
+#define SLJIT_S2 (SLJIT_NUMBER_OF_REGISTERS - 2)
+/* Note: on x86-32, S3 - S6 (same as R3 - R6) are emulated (they
+ are allocated on the stack). These registers are called virtual
+ and cannot be used for memory addressing (cannot be part of
+ any SLJIT_MEM1, SLJIT_MEM2 construct). There is no such
+ limitation on other CPUs. See sljit_get_register_index(). */
+#define SLJIT_S3 (SLJIT_NUMBER_OF_REGISTERS - 3)
+#define SLJIT_S4 (SLJIT_NUMBER_OF_REGISTERS - 4)
+#define SLJIT_S5 (SLJIT_NUMBER_OF_REGISTERS - 5)
+#define SLJIT_S6 (SLJIT_NUMBER_OF_REGISTERS - 6)
+#define SLJIT_S7 (SLJIT_NUMBER_OF_REGISTERS - 7)
+#define SLJIT_S8 (SLJIT_NUMBER_OF_REGISTERS - 8)
+#define SLJIT_S9 (SLJIT_NUMBER_OF_REGISTERS - 9)
+/* All S registers provided by the architecture can be accessed by SLJIT_S(i)
+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_REGISTERS. */
+#define SLJIT_S(i) (SLJIT_NUMBER_OF_REGISTERS - (i))
+
+/* Registers >= SLJIT_FIRST_SAVED_REG are saved registers. */
+#define SLJIT_FIRST_SAVED_REG (SLJIT_S0 - SLJIT_NUMBER_OF_SAVED_REGISTERS + 1)
+
+/* The SLJIT_SP provides direct access to the linear stack space allocated by
+ sljit_emit_enter. It can only be used in the following form: SLJIT_MEM1(SLJIT_SP).
+ The immediate offset is extended by the relative stack offset automatically.
+ sljit_get_local_base can be used to obtain the real address of a value. */
+#define SLJIT_SP (SLJIT_NUMBER_OF_REGISTERS + 1)
+
+/* Return with machine word. */
+
+#define SLJIT_RETURN_REG SLJIT_R0
+
+/* --------------------------------------------------------------------- */
+/* Floating point registers */
+/* --------------------------------------------------------------------- */
+
+/* Each floating point register can store a 32 or a 64 bit precision
+ value. The FR and FS register sets overlap in the same way as R
+ and S register sets. See above. */
+
+/* Floating point scratch registers. */
+#define SLJIT_FR0 1
+#define SLJIT_FR1 2
+#define SLJIT_FR2 3
+#define SLJIT_FR3 4
+#define SLJIT_FR4 5
+#define SLJIT_FR5 6
+#define SLJIT_FR6 7
+#define SLJIT_FR7 8
+#define SLJIT_FR8 9
+#define SLJIT_FR9 10
+/* All FR registers provided by the architecture can be accessed by SLJIT_FR(i)
+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_FLOAT_REGISTERS. */
+#define SLJIT_FR(i) (1 + (i))
+
+/* Floating point saved registers. */
+#define SLJIT_FS0 (SLJIT_NUMBER_OF_FLOAT_REGISTERS)
+#define SLJIT_FS1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 1)
+#define SLJIT_FS2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 2)
+#define SLJIT_FS3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 3)
+#define SLJIT_FS4 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 4)
+#define SLJIT_FS5 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 5)
+#define SLJIT_FS6 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 6)
+#define SLJIT_FS7 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 7)
+#define SLJIT_FS8 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 8)
+#define SLJIT_FS9 (SLJIT_NUMBER_OF_FLOAT_REGISTERS - 9)
+/* All FS registers provided by the architecture can be accessed by SLJIT_FS(i)
+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS. */
+#define SLJIT_FS(i) (SLJIT_NUMBER_OF_FLOAT_REGISTERS - (i))
+
+/* Float registers >= SLJIT_FIRST_SAVED_FLOAT_REG are saved registers. */
+#define SLJIT_FIRST_SAVED_FLOAT_REG (SLJIT_FS0 - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS + 1)
+
+/* Return with floating point arg. */
+
+#define SLJIT_RETURN_FREG SLJIT_FR0
+
+/* --------------------------------------------------------------------- */
+/* Vector registers */
+/* --------------------------------------------------------------------- */
+
+/* Vector registers are storage areas, which are used for Single Instruction
+ Multiple Data (SIMD) computations. The VR and VS register sets overlap
+ in the same way as R and S register sets. See above.
+
+ The storage space of vector registers often overlap with floating point
+ registers. In this case setting the value of SLJIT_VR(i) destroys the
+ value of SLJIT_FR(i) and vice versa. See SLJIT_SEPARATE_VECTOR_REGISTERS
+ macro. */
+
+/* Vector scratch registers. */
+#define SLJIT_VR0 1
+#define SLJIT_VR1 2
+#define SLJIT_VR2 3
+#define SLJIT_VR3 4
+#define SLJIT_VR4 5
+#define SLJIT_VR5 6
+#define SLJIT_VR6 7
+#define SLJIT_VR7 8
+#define SLJIT_VR8 9
+#define SLJIT_VR9 10
+/* All VR registers provided by the architecture can be accessed by SLJIT_VR(i)
+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_VECTOR_REGISTERS. */
+#define SLJIT_VR(i) (1 + (i))
+
+/* Vector saved registers. */
+#define SLJIT_VS0 (SLJIT_NUMBER_OF_VECTOR_REGISTERS)
+#define SLJIT_VS1 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 1)
+#define SLJIT_VS2 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 2)
+#define SLJIT_VS3 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 3)
+#define SLJIT_VS4 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 4)
+#define SLJIT_VS5 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 5)
+#define SLJIT_VS6 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 6)
+#define SLJIT_VS7 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 7)
+#define SLJIT_VS8 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 8)
+#define SLJIT_VS9 (SLJIT_NUMBER_OF_VECTOR_REGISTERS - 9)
+/* All VS registers provided by the architecture can be accessed by SLJIT_VS(i)
+ The i parameter must be >= 0 and < SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS. */
+#define SLJIT_VS(i) (SLJIT_NUMBER_OF_VECTOR_REGISTERS - (i))
+
+/* Vector registers >= SLJIT_FIRST_SAVED_VECTOR_REG are saved registers. */
+#define SLJIT_FIRST_SAVED_VECTOR_REG (SLJIT_VS0 - SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS + 1)
+
+/* --------------------------------------------------------------------- */
+/* Argument type definitions */
+/* --------------------------------------------------------------------- */
+
+/* The following argument type definitions are used by sljit_emit_enter,
+ sljit_set_context, sljit_emit_call, and sljit_emit_icall functions.
+
+ For sljit_emit_call and sljit_emit_icall, the first integer argument
+ must be placed into SLJIT_R0, the second one into SLJIT_R1, and so on.
+ Similarly the first floating point argument must be placed into SLJIT_FR0,
+ the second one into SLJIT_FR1, and so on.
+
+ For sljit_emit_enter, the integer arguments can be stored in scratch
+ or saved registers. Scratch registers are identified by a _R suffix.
+
+ If only saved registers are used, then the allocation mirrors what is
+ done for the "call" functions but using saved registers, meaning that
+ the first integer argument goes to SLJIT_S0, the second one goes into
+ SLJIT_S1, and so on.
+
+ If scratch registers are used, then the way the integer registers are
+ allocated changes so that SLJIT_S0, SLJIT_S1, etc; will be assigned
+ only for the arguments not using scratch registers, while SLJIT_R
+ will be used for the ones using scratch registers.
+
+ Furthermore, the index (shown as "n" above) that will be used for the
+ scratch register depends on how many previous integer registers
+ (scratch or saved) were used already, starting with SLJIT_R0.
+ Eventhough some indexes will be likely skipped, they still need to be
+ accounted for in the scratches parameter of sljit_emit_enter. See below
+ for some examples.
+
+ The floating point arguments always use scratch registers (but not the
+ _R suffix like the integer arguments) and must use SLJIT_FR0, SLJIT_FR1,
+ just like in the "call" functions.
+
+ Note: the mapping for scratch registers is part of the compiler context
+ and therefore a new context after sljit_emit_call/sljit_emit_icall
+ could remove access to some scratch registers that were used as
+ arguments.
+
+ Example function definition:
+ sljit_f32 SLJIT_FUNC example_c_callback(void *arg_a,
+ sljit_f64 arg_b, sljit_u32 arg_c, sljit_f32 arg_d);
+
+ Argument type definition:
+ SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_F32)
+ | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_P, 1) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_F64, 2)
+ | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_32, 3) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_F32, 4)
+
+ Short form of argument type definition:
+ SLJIT_ARGS4(F32, P, F64, 32, F32)
+
+ Argument passing:
+ arg_a must be placed in SLJIT_R0
+ arg_b must be placed in SLJIT_FR0
+ arg_c must be placed in SLJIT_R1
+ arg_d must be placed in SLJIT_FR1
+
+ Examples for argument processing by sljit_emit_enter:
+ SLJIT_ARGS4V(P, 32_R, F32, W)
+ Arguments are placed into: SLJIT_S0, SLJIT_R1, SLJIT_FR0, SLJIT_S1
+ The type of the result is void.
+
+ SLJIT_ARGS4(F32, W, W_R, W, W_R)
+ Arguments are placed into: SLJIT_S0, SLJIT_R1, SLJIT_S1, SLJIT_R3
+ The type of the result is sljit_f32.
+
+ SLJIT_ARGS4(P, W, F32, P_R)
+ Arguments are placed into: SLJIT_FR0, SLJIT_S0, SLJIT_FR1, SLJIT_R1
+ The type of the result is pointer.
+
+ Note: it is recommended to pass the scratch arguments first
+ followed by the saved arguments:
+
+ SLJIT_ARGS4(W, W_R, W_R, W, W)
+ Arguments are placed into: SLJIT_R0, SLJIT_R1, SLJIT_S0, SLJIT_S1
+ The type of the result is sljit_sw / sljit_uw.
+*/
+
+/* The following flag is only allowed for the integer arguments of
+ sljit_emit_enter. When the flag is set, the integer argument is
+ stored in a scratch register instead of a saved register. */
+#define SLJIT_ARG_TYPE_SCRATCH_REG 0x8
+
+/* No return value, only supported by SLJIT_ARG_RETURN. */
+#define SLJIT_ARG_TYPE_RET_VOID 0
+/* Machine word sized integer argument or result. */
+#define SLJIT_ARG_TYPE_W 1
+#define SLJIT_ARG_TYPE_W_R (SLJIT_ARG_TYPE_W | SLJIT_ARG_TYPE_SCRATCH_REG)
+/* 32 bit integer argument or result. */
+#define SLJIT_ARG_TYPE_32 2
+#define SLJIT_ARG_TYPE_32_R (SLJIT_ARG_TYPE_32 | SLJIT_ARG_TYPE_SCRATCH_REG)
+/* Pointer sized integer argument or result. */
+#define SLJIT_ARG_TYPE_P 3
+#define SLJIT_ARG_TYPE_P_R (SLJIT_ARG_TYPE_P | SLJIT_ARG_TYPE_SCRATCH_REG)
+/* 64 bit floating point argument or result. */
+#define SLJIT_ARG_TYPE_F64 4
+/* 32 bit floating point argument or result. */
+#define SLJIT_ARG_TYPE_F32 5
+
+#define SLJIT_ARG_SHIFT 4
+#define SLJIT_ARG_RETURN(type) (type)
+#define SLJIT_ARG_VALUE(type, idx) ((type) << ((idx) * SLJIT_ARG_SHIFT))
+
+/* Simplified argument list definitions.
+
+ The following definition:
+ SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_W) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_F32, 1)
+
+ can be shortened to:
+ SLJIT_ARGS1(W, F32)
+
+ Another example where no value is returned:
+ SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_RET_VOID) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_W_R, 1)
+
+ can be shortened to:
+ SLJIT_ARGS1V(W_R)
+*/
+
+#define SLJIT_ARG_TO_TYPE(type) SLJIT_ARG_TYPE_ ## type
+
+#define SLJIT_ARGS0(ret) \
+ SLJIT_ARG_RETURN(SLJIT_ARG_TO_TYPE(ret))
+#define SLJIT_ARGS0V() \
+ SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_RET_VOID)
+
+#define SLJIT_ARGS1(ret, arg1) \
+ (SLJIT_ARGS0(ret) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg1), 1))
+#define SLJIT_ARGS1V(arg1) \
+ (SLJIT_ARGS0V() | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg1), 1))
+
+#define SLJIT_ARGS2(ret, arg1, arg2) \
+ (SLJIT_ARGS1(ret, arg1) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg2), 2))
+#define SLJIT_ARGS2V(arg1, arg2) \
+ (SLJIT_ARGS1V(arg1) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg2), 2))
+
+#define SLJIT_ARGS3(ret, arg1, arg2, arg3) \
+ (SLJIT_ARGS2(ret, arg1, arg2) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg3), 3))
+#define SLJIT_ARGS3V(arg1, arg2, arg3) \
+ (SLJIT_ARGS2V(arg1, arg2) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg3), 3))
+
+#define SLJIT_ARGS4(ret, arg1, arg2, arg3, arg4) \
+ (SLJIT_ARGS3(ret, arg1, arg2, arg3) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg4), 4))
+#define SLJIT_ARGS4V(arg1, arg2, arg3, arg4) \
+ (SLJIT_ARGS3V(arg1, arg2, arg3) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg4), 4))
+
+/* --------------------------------------------------------------------- */
+/* Main structures and functions */
+/* --------------------------------------------------------------------- */
+
+/*
+ The following structures are private, and can be changed in the
+ future. Keeping them here allows code inlining.
+*/
+
+struct sljit_memory_fragment {
+ struct sljit_memory_fragment *next;
+ sljit_uw used_size;
+ /* Must be aligned to sljit_sw. */
+ sljit_u8 memory[1];
+};
+
+struct sljit_label {
+ struct sljit_label *next;
+ union {
+ sljit_uw index;
+ sljit_uw addr;
+ } u;
+ /* The maximum size difference. */
+ sljit_uw size;
+};
+
+struct sljit_jump {
+ struct sljit_jump *next;
+ sljit_uw addr;
+ /* Architecture dependent flags. */
+ sljit_uw flags;
+ union {
+ sljit_uw target;
+ struct sljit_label *label;
+ } u;
+};
+
+struct sljit_const {
+ struct sljit_const *next;
+ sljit_uw addr;
+};
+
+struct sljit_generate_code_buffer {
+ void *buffer;
+ sljit_uw size;
+ sljit_sw executable_offset;
+};
+
+struct sljit_read_only_buffer {
+ struct sljit_read_only_buffer *next;
+ sljit_uw size;
+ /* Label can be replaced by address after sljit_generate_code. */
+ union {
+ struct sljit_label *label;
+ sljit_uw addr;
+ } u;
+};
+
+struct sljit_compiler {
+ sljit_s32 error;
+ sljit_s32 options;
+
+ struct sljit_label *labels;
+ struct sljit_jump *jumps;
+ struct sljit_const *consts;
+ struct sljit_label *last_label;
+ struct sljit_jump *last_jump;
+ struct sljit_const *last_const;
+
+ void *allocator_data;
+ void *user_data;
+ struct sljit_memory_fragment *buf;
+ struct sljit_memory_fragment *abuf;
+
+ /* Number of labels created by the compiler. */
+ sljit_uw label_count;
+ /* Available scratch registers. */
+ sljit_s32 scratches;
+ /* Available saved registers. */
+ sljit_s32 saveds;
+ /* Available float scratch registers. */
+ sljit_s32 fscratches;
+ /* Available float saved registers. */
+ sljit_s32 fsaveds;
+#if (defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_DEBUG && SLJIT_DEBUG) \
+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ /* Available vector scratch registers. */
+ sljit_s32 vscratches;
+ /* Available vector saved registers. */
+ sljit_s32 vsaveds;
+#endif /* SLJIT_SEPARATE_VECTOR_REGISTERS || SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG || SLJIT_VERBOSE */
+ /* Local stack size. */
+ sljit_s32 local_size;
+ /* Maximum code size. */
+ sljit_uw size;
+ /* Relative offset of the executable mapping from the writable mapping. */
+ sljit_sw executable_offset;
+ /* Executable size for statistical purposes. */
+ sljit_uw executable_size;
+
+#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)
+ sljit_s32 status_flags_state;
+#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ sljit_s32 args_size;
+#endif /* SLJIT_CONFIG_X86_32 */
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ /* Temporary fields. */
+ sljit_s32 mode32;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ /* Constant pool handling. */
+ sljit_uw *cpool;
+ sljit_u8 *cpool_unique;
+ sljit_uw cpool_diff;
+ sljit_uw cpool_fill;
+ /* Other members. */
+ /* Contains pointer, "ldr pc, [...]" pairs. */
+ sljit_uw patches;
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+ /* Temporary fields. */
+ sljit_uw shift_imm;
+#endif /* SLJIT_CONFIG_ARM_V6 || SLJIT_CONFIG_ARM_V6 */
+
+#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)
+ sljit_uw args_size;
+#endif /* SLJIT_CONFIG_ARM_32 && __SOFTFP__ */
+
+#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
+ /* Temporary fields. */
+ sljit_u32 imm;
+#endif /* SLJIT_CONFIG_PPC */
+
+#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
+ sljit_s32 delay_slot;
+ /* Temporary fields. */
+ sljit_s32 cache_arg;
+ sljit_sw cache_argw;
+#endif /* SLJIT_CONFIG_MIPS */
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ sljit_uw args_size;
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+#if (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
+ /* Temporary fields. */
+ sljit_s32 cache_arg;
+ sljit_sw cache_argw;
+#endif /* SLJIT_CONFIG_RISCV */
+
+#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
+ /* Need to allocate register save area to make calls. */
+ /* Temporary fields. */
+ sljit_s32 mode;
+#endif /* SLJIT_CONFIG_S390X */
+
+#if (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
+ /* Temporary fields. */
+ sljit_s32 cache_arg;
+ sljit_sw cache_argw;
+#endif /* SLJIT_CONFIG_LOONGARCH */
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ FILE* verbose;
+#endif /* SLJIT_VERBOSE */
+
+ /* Note: SLJIT_DEBUG enables SLJIT_ARGUMENT_CHECKS. */
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ /* Flags specified by the last arithmetic instruction.
+ It contains the type of the variable flag. */
+ sljit_s32 last_flags;
+ /* Return value type set by entry functions. */
+ sljit_s32 last_return;
+ /* Local size passed to entry functions. */
+ sljit_s32 logical_local_size;
+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_DEBUG && SLJIT_DEBUG) \
+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+#if !(defined SLJIT_SEPARATE_VECTOR_REGISTERS && SLJIT_SEPARATE_VECTOR_REGISTERS)
+ /* Available float scratch registers. */
+ sljit_s32 real_fscratches;
+ /* Available float saved registers. */
+ sljit_s32 real_fsaveds;
+#endif /* !SLJIT_SEPARATE_VECTOR_REGISTERS */
+
+ /* Trust arguments when an API function is called.
+ Used internally for calling API functions. */
+ sljit_s32 skip_checks;
+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG || SLJIT_VERBOSE */
+};
+
+/* --------------------------------------------------------------------- */
+/* Main functions */
+/* --------------------------------------------------------------------- */
+
+/* Creates an SLJIT compiler. The allocator_data is required by some
+ custom memory managers. This pointer is passed to SLJIT_MALLOC
+ and SLJIT_FREE macros. Most allocators (including the default
+ one) ignores this value, and it is recommended to pass NULL
+ as a dummy value for allocator_data.
+
+ Returns NULL if failed. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data);
+
+/* Frees everything except the compiled machine code. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler);
+
+/* Returns the current error code. If an error occurres, future calls
+ which uses the same compiler argument returns early with the same
+ error code. Thus there is no need for checking the error after every
+ call, it is enough to do it after the code is compiled. Removing
+ these checks increases the performance of the compiling process. */
+static SLJIT_INLINE sljit_s32 sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; }
+
+/* Sets the compiler error code to SLJIT_ERR_ALLOC_FAILED except
+ if an error was detected before. After the error code is set
+ the compiler behaves as if the allocation failure happened
+ during an SLJIT function call. This can greatly simplify error
+ checking, since it is enough to check the compiler status
+ after the code is compiled. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler);
+
+/* Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit,
+ and <= 128 bytes on 64 bit architectures. The memory area is owned by the
+ compiler, and freed by sljit_free_compiler. The returned pointer is
+ sizeof(sljit_sw) aligned. Excellent for allocating small blocks during
+ compiling, and no need to worry about freeing them. The size is enough
+ to contain at most 16 pointers. If the size is outside of the range,
+ the function will return with NULL. However, this return value does not
+ indicate that there is no more memory (does not set the current error code
+ of the compiler to out-of-memory status). */
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_s32 size);
+
+/* Returns the allocator data passed to sljit_create_compiler. */
+static SLJIT_INLINE void* sljit_compiler_get_allocator_data(struct sljit_compiler *compiler) { return compiler->allocator_data; }
+/* Sets/get the user data for a compiler. */
+static SLJIT_INLINE void sljit_compiler_set_user_data(struct sljit_compiler *compiler, void *user_data) { compiler->user_data = user_data; }
+static SLJIT_INLINE void* sljit_compiler_get_user_data(struct sljit_compiler *compiler) { return compiler->user_data; }
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+/* Passing NULL disables verbose. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *compiler, FILE* verbose);
+#endif /* SLJIT_VERBOSE */
+
+/* Option bits for sljit_generate_code. */
+
+/* The exec_allocator_data points to a pre-allocated
+ buffer which type is sljit_generate_code_buffer. */
+#define SLJIT_GENERATE_CODE_BUFFER 0x1
+
+/* When SLJIT_INDIRECT_CALL is defined, no function context is
+created for the generated code (see sljit_set_function_context),
+so the returned pointer cannot be directly called from C code.
+The flag is ignored when SLJIT_INDIRECT_CALL is not defined. */
+#define SLJIT_GENERATE_CODE_NO_CONTEXT 0x2
+
+/* Create executable code from the instruction stream. This is the final step
+ of the code generation, and no more instructions can be emitted after this call.
+
+ options is the combination of SLJIT_GENERATE_CODE_* bits
+ exec_allocator_data is passed to SLJIT_MALLOC_EXEC and
+ SLJIT_MALLOC_FREE functions */
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data);
+
+/* Free executable code. */
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data);
+
+/* When the protected executable allocator is used the JIT code is mapped
+ twice. The first mapping has read/write and the second mapping has read/exec
+ permissions. This function returns with the relative offset of the executable
+ mapping using the writable mapping as the base after the machine code is
+ successfully generated. The returned value is always 0 for the normal executable
+ allocator, since it uses only one mapping with read/write/exec permissions.
+ Dynamic code modifications requires this value.
+
+ Before a successful code generation, this function returns with 0. */
+static SLJIT_INLINE sljit_sw sljit_get_executable_offset(struct sljit_compiler *compiler) { return compiler->executable_offset; }
+
+/* The executable memory consumption of the generated code can be retrieved by
+ this function. The returned value can be used for statistical purposes.
+
+ Before a successful code generation, this function returns with 0. */
+static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; }
+
+/* Returns with non-zero if the feature or limitation type passed as its
+ argument is present on the current CPU. The return value is one, if a
+ feature is fully supported, and it is two, if partially supported.
+
+ Some features (e.g. floating point operations) require hardware (CPU)
+ support while others (e.g. move with update) are emulated if not available.
+ However, even when a feature is emulated, specialized code paths may be
+ faster than the emulation. Some limitations are emulated as well so their
+ general case is supported but it has extra performance costs.
+
+ Note: sljitConfigInternal.h also provides several feature detection macros. */
+
+/* [Not emulated] Floating-point support is available. */
+#define SLJIT_HAS_FPU 0
+/* [Limitation] Some registers are virtual registers. */
+#define SLJIT_HAS_VIRTUAL_REGISTERS 1
+/* [Emulated] Has zero register (setting a memory location to zero is efficient). */
+#define SLJIT_HAS_ZERO_REGISTER 2
+/* [Emulated] Count leading zero is supported. */
+#define SLJIT_HAS_CLZ 3
+/* [Emulated] Count trailing zero is supported. */
+#define SLJIT_HAS_CTZ 4
+/* [Emulated] Reverse the order of bytes is supported. */
+#define SLJIT_HAS_REV 5
+/* [Emulated] Rotate left/right is supported. */
+#define SLJIT_HAS_ROT 6
+/* [Emulated] Conditional move is supported. */
+#define SLJIT_HAS_CMOV 7
+/* [Emulated] Prefetch instruction is available (emulated as a nop). */
+#define SLJIT_HAS_PREFETCH 8
+/* [Emulated] Copy from/to f32 operation is available (see sljit_emit_fcopy). */
+#define SLJIT_HAS_COPY_F32 9
+/* [Emulated] Copy from/to f64 operation is available (see sljit_emit_fcopy). */
+#define SLJIT_HAS_COPY_F64 10
+/* [Not emulated] The 64 bit floating point registers can be used as
+ two separate 32 bit floating point registers (e.g. ARM32). The
+ second 32 bit part can be accessed by SLJIT_F64_SECOND. */
+#define SLJIT_HAS_F64_AS_F32_PAIR 11
+/* [Not emulated] Some SIMD operations are supported by the compiler. */
+#define SLJIT_HAS_SIMD 12
+/* [Not emulated] SIMD registers are mapped to a pair of double precision
+ floating point registers. E.g. passing either SLJIT_FR0 or SLJIT_FR1 to
+ a simd operation represents the same 128 bit register, and both SLJIT_FR0
+ and SLJIT_FR1 are overwritten. */
+#define SLJIT_SIMD_REGS_ARE_PAIRS 13
+/* [Not emulated] Atomic support is available. */
+#define SLJIT_HAS_ATOMIC 14
+/* [Not emulated] Memory barrier support is available. */
+#define SLJIT_HAS_MEMORY_BARRIER 15
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+/* [Not emulated] AVX support is available on x86. */
+#define SLJIT_HAS_AVX 100
+/* [Not emulated] AVX2 support is available on x86. */
+#define SLJIT_HAS_AVX2 101
+#endif /* SLJIT_CONFIG_X86 */
+
+#if (defined SLJIT_CONFIG_LOONGARCH)
+/* [Not emulated] LASX support is available on LoongArch */
+#define SLJIT_HAS_LASX 201
+#endif /* SLJIT_CONFIG_LOONGARCH */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type);
+
+/* If type is between SLJIT_ORDERED_EQUAL and SLJIT_ORDERED_LESS_EQUAL,
+ sljit_cmp_info returns with:
+ zero - if the cpu supports the floating point comparison type
+ one - if the comparison requires two machine instructions
+ two - if the comparison requires more than two machine instructions
+
+ When the result is non-zero, it is recommended to avoid
+ using the specified comparison type if it is easy to do so.
+
+ Otherwise it returns zero. */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type);
+
+/* The following functions generate machine code. If there is no
+ error, they return with SLJIT_SUCCESS, otherwise they return
+ with an error code. */
+
+/*
+ The executable code is a callable function from the viewpoint
+ of the C language. Function calls must conform with the ABI
+ (Application Binary Interface) of the target platform, which
+ specify the purpose of machine registers and stack handling
+ among other things. The sljit_emit_enter function emits the
+ necessary instructions for setting up an entry point for the
+ executable code. This is often called as function prologue.
+
+ The "options" argument can be used to pass configuration options
+ to the sljit compiler which affects the generated code, until
+ another sljit_emit_enter or sljit_set_context is called. The
+ available options are listed before sljit_emit_enter.
+
+ The function argument list is specified by the SLJIT_ARGSx
+ (SLJIT_ARGS0 .. SLJIT_ARGS4) macros. Currently maximum four
+ arguments are supported. See the description of SLJIT_ARGSx
+ macros about argument passing.
+
+ The register set used by the function must be declared as well.
+ The number of scratch and saved registers available to the
+ function must be passed to sljit_emit_enter. Only R registers
+ between R0 and "scratches" argument can be used later. E.g.
+ if "scratches" is set to two, the scratch register set will
+ be limited to SLJIT_R0 and SLJIT_R1. The S registers are
+ declared in a similar manner, but their count is specified
+ by "saveds" argument. The floating point scratch and saved
+ registers can be set by using "scratches" and "saveds" argument
+ as well, but their value must be passed to the SLJIT_ENTER_FLOAT
+ macro, see below.
+
+ The sljit_emit_enter is also capable of allocating a stack
+ space for local data. The "local_size" argument contains the
+ size in bytes of this local area, and it can be accessed using
+ SLJIT_MEM1(SLJIT_SP). The memory area between SLJIT_SP (inclusive)
+ and SLJIT_SP + local_size (exclusive) can be modified freely
+ until the function returns. The alocated stack space is an
+ uninitialized memory area.
+
+ Floating point scratch and saved registers must be specified
+ by the SLJIT_ENTER_FLOAT macro, which result value should be
+ combined with scratches / saveds argument.
+
+ Examples:
+ To use three scratch and four floating point scratch
+ registers, the "scratches" argument must be set to:
+ 3 | SLJIT_ENTER_FLOAT(4)
+
+ To use six saved and five floating point saved
+ registers, the "saveds" argument must be set to:
+ 6 | SLJIT_ENTER_FLOAT(5)
+
+ Note: the following conditions must met:
+ 0 <= scratches <= SLJIT_NUMBER_OF_REGISTERS
+ 0 <= saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS
+ scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS
+
+ 0 <= float scratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS
+ 0 <= float saveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS
+ float scratches + float saveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS
+
+ Note: the compiler can use saved registers as scratch registers,
+ but the opposite is not supported
+
+ Note: every call of sljit_emit_enter and sljit_set_context
+ overwrites the previous context.
+*/
+
+/* The following options are available for sljit_emit_enter. */
+
+/* Saved registers between SLJIT_S0 and SLJIT_S(n - 1) (inclusive)
+ are not saved / restored on function enter / return. Instead,
+ these registers can be used to pass / return data (such as
+ global / local context pointers) across function calls. The
+ value of n must be between 1 and 3. This option is only
+ supported by SLJIT_ENTER_REG_ARG calling convention. */
+#define SLJIT_ENTER_KEEP(n) (n)
+
+/* The compiled function uses an SLJIT specific register argument
+ calling convention. This is a lightweight function call type where
+ both the caller and the called functions must be compiled by
+ SLJIT. The type argument of the call must be SLJIT_CALL_REG_ARG
+ and all arguments must be stored in scratch registers. */
+#define SLJIT_ENTER_REG_ARG 0x00000004
+
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+/* Use VEX prefix for all SIMD operations on x86. */
+#define SLJIT_ENTER_USE_VEX 0x00010000
+#endif /* !SLJIT_CONFIG_X86 */
+
+/* Macros for other sljit_emit_enter arguments. */
+
+/* Floating point scratch and saved registers can be
+ specified by SLJIT_ENTER_FLOAT. */
+#define SLJIT_ENTER_FLOAT(regs) ((regs) << 8)
+
+/* Vector scratch and saved registers can be specified
+ by SLJIT_ENTER_VECTOR. */
+#define SLJIT_ENTER_VECTOR(regs) ((regs) << 16)
+
+/* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */
+#define SLJIT_MAX_LOCAL_SIZE 1048576
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size);
+
+/* The SLJIT compiler has a current context (which contains the local
+ stack space size, number of used registers, etc.) which is initialized
+ by sljit_emit_enter. Several functions (such as sljit_emit_return)
+ requires this context to be able to generate the appropriate code.
+ However, some code fragments (compiled separately) may have no
+ normal entry point so their context is unknown to the compiler.
+
+ sljit_set_context and sljit_emit_enter have the same arguments,
+ but sljit_set_context does not generate any machine code.
+
+ Note: every call of sljit_emit_enter and sljit_set_context overwrites
+ the previous context. */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size);
+
+/* Return to the caller function. The sljit_emit_return_void function
+ does not return with any value. The sljit_emit_return function returns
+ with a single value loaded from its source operand. The load operation
+ can be between SLJIT_MOV and SLJIT_MOV_P (see sljit_emit_op1) and
+ SLJIT_MOV_F32/SLJIT_MOV_F64 (see sljit_emit_fop1) depending on the
+ return value specified by sljit_emit_enter/sljit_set_context. */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler);
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src, sljit_sw srcw);
+
+/* Restores the saved registers and free the stack area, then the execution
+ continues from the address specified by the source operand. This
+ operation is similar to sljit_emit_return, but it ignores the return
+ address. The code where the exection continues should use the same context
+ as the caller function (see sljit_set_context). A word (pointer) value
+ can be passed in the SLJIT_RETURN_REG register. This function can be used
+ to jump to exception handlers. */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw);
+
+/*
+ Source and destination operands for arithmetical instructions
+ imm - a simple immediate value (cannot be used as a destination)
+ reg - any of the available registers (immediate argument must be 0)
+ [imm] - absolute memory address
+ [reg+imm] - indirect memory address
+ [reg+(reg< 0 && (arg) < SLJIT_IMM)
+#define SLJIT_IS_MEM(arg) ((arg) & SLJIT_MEM)
+#define SLJIT_IS_MEM0(arg) ((arg) == SLJIT_MEM)
+#define SLJIT_IS_MEM1(arg) ((arg) > SLJIT_MEM && (arg) < (SLJIT_MEM << 1))
+#define SLJIT_IS_MEM2(arg) (((arg) & SLJIT_MEM) && (arg) >= (SLJIT_MEM << 1))
+#define SLJIT_IS_IMM(arg) ((arg) == SLJIT_IMM)
+#define SLJIT_IS_REG_PAIR(arg) (!((arg) & SLJIT_MEM) && (arg) >= (SLJIT_MEM << 1))
+
+/* Macros for extracting registers from operands. */
+/* Support operands which contains a single register or
+ constructed using SLJIT_MEM1, SLJIT_MEM2, or SLJIT_REG_PAIR. */
+#define SLJIT_EXTRACT_REG(arg) ((arg) & 0x7f)
+/* Support operands which constructed using SLJIT_MEM2, or SLJIT_REG_PAIR. */
+#define SLJIT_EXTRACT_SECOND_REG(arg) ((arg) >> 8)
+
+/* Sets 32 bit operation mode on 64 bit CPUs. This option is ignored on
+ 32 bit CPUs. When this option is set for an arithmetic operation, only
+ the lower 32 bits of the input registers are used, and the CPU status
+ flags are set according to the 32 bit result. Although the higher 32 bit
+ of the input and the result registers are not defined by SLJIT, it might
+ be defined by the CPU architecture (e.g. MIPS). To satisfy these CPU
+ requirements all source registers must be the result of those operations
+ where this option was also set. Memory loads read 32 bit values rather
+ than 64 bit ones. In other words 32 bit and 64 bit operations cannot be
+ mixed. The only exception is SLJIT_MOV32 which source register can hold
+ any 32 or 64 bit value, and it is converted to a 32 bit compatible format
+ first. When the source and destination registers are the same, this
+ conversion is free (no instructions are emitted) on most CPUs. A 32 bit
+ value can also be converted to a 64 bit value by SLJIT_MOV_S32
+ (sign extension) or SLJIT_MOV_U32 (zero extension).
+
+ As for floating-point operations, this option sets 32 bit single
+ precision mode. Similar to the integer operations, all register arguments
+ must be the result of those operations where this option was also set.
+
+ Note: memory addressing always uses 64 bit values on 64 bit systems so
+ the result of a 32 bit operation must not be used with SLJIT_MEMx
+ macros.
+
+ This option is part of the instruction name, so there is no need to
+ manually set it. E.g:
+
+ SLJIT_ADD32 == (SLJIT_ADD | SLJIT_32) */
+#define SLJIT_32 0x100
+
+/* Many CPUs (x86, ARM, PPC) have status flag bits which can be set according
+ to the result of an operation. Other CPUs (MIPS) do not have status
+ flag bits, and results must be stored in registers. To cover both
+ architecture types efficiently only two flags are defined by SLJIT:
+
+ * Zero (equal) flag: it is set if the result is zero
+ * Variable flag: its value is defined by the arithmetic operation
+
+ SLJIT instructions can set any or both of these flags. The value of
+ these flags is undefined if the instruction does not specify their
+ value. The description of each instruction contains the list of
+ allowed flag types.
+
+ Note: the logical or operation can be used to set flags.
+
+ Example: SLJIT_ADD can set the Z, OVERFLOW, CARRY flags hence
+
+ sljit_op2(..., SLJIT_ADD, ...)
+ Both the zero and variable flags are undefined so they can
+ have any value after the operation is completed.
+
+ sljit_op2(..., SLJIT_ADD | SLJIT_SET_Z, ...)
+ Sets the zero flag if the result is zero, clears it otherwise.
+ The variable flag is undefined.
+
+ sljit_op2(..., SLJIT_ADD | SLJIT_SET_OVERFLOW, ...)
+ Sets the variable flag if an integer overflow occurs, clears
+ it otherwise. The zero flag is undefined.
+
+ sljit_op2(..., SLJIT_ADD | SLJIT_SET_Z | SLJIT_SET_CARRY, ...)
+ Sets the zero flag if the result is zero, clears it otherwise.
+ Sets the variable flag if unsigned overflow (carry) occurs,
+ clears it otherwise.
+
+ Certain instructions (e.g. SLJIT_MOV) does not modify flags, so
+ status flags are unchanged.
+
+ Example:
+
+ sljit_op2(..., SLJIT_ADD | SLJIT_SET_Z, ...)
+ sljit_op1(..., SLJIT_MOV, ...)
+ Zero flag is set according to the result of SLJIT_ADD.
+
+ sljit_op2(..., SLJIT_ADD | SLJIT_SET_Z, ...)
+ sljit_op2(..., SLJIT_ADD, ...)
+ Zero flag has unknown value.
+
+ These flags can be used for code optimization. E.g. a fast loop can be
+ implemented by decreasing a counter register and set the zero flag
+ using a single instruction. The zero register can be used by a
+ conditional jump to restart the loop. A single comparison can set a
+ zero and less flags to check if a value is less, equal, or greater
+ than another value.
+
+ Motivation: although some CPUs can set a large number of flag bits,
+ usually their values are ignored or only a few of them are used. Emulating
+ a large number of flags on systems without a flag register is complicated
+ so SLJIT instructions must specify the flag they want to use and only
+ that flag is computed. The last arithmetic instruction can be repeated if
+ multiple flags need to be checked.
+*/
+
+/* Set Zero status flag. */
+#define SLJIT_SET_Z 0x0200
+/* Set the variable status flag if condition is true.
+ See comparison types (e.g. SLJIT_SET_LESS, SLJIT_SET_F_EQUAL). */
+#define SLJIT_SET(condition) ((condition) << 10)
+
+/* Starting index of opcodes for sljit_emit_op0. */
+#define SLJIT_OP0_BASE 0
+
+/* Flags: - (does not modify flags)
+ Triggers a trap that could be intercepted by a debugger
+ Note: might not be supported by all architectures,
+ It falls back to SLJIT_NOP in those cases. */
+#define SLJIT_BREAKPOINT (SLJIT_OP0_BASE + 0)
+/* Flags: - (does not modify flags)
+ Note: may or may not cause an extra cycle wait
+ it can even decrease the runtime in a few cases. */
+#define SLJIT_NOP (SLJIT_OP0_BASE + 1)
+/* Flags: - (may destroy flags)
+ Unsigned multiplication of SLJIT_R0 and SLJIT_R1.
+ Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */
+#define SLJIT_LMUL_UW (SLJIT_OP0_BASE + 2)
+/* Flags: - (may destroy flags)
+ Signed multiplication of SLJIT_R0 and SLJIT_R1.
+ Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */
+#define SLJIT_LMUL_SW (SLJIT_OP0_BASE + 3)
+/* Flags: - (may destroy flags)
+ Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.
+ The result is placed into SLJIT_R0 and the remainder into SLJIT_R1.
+ Note: if SLJIT_R1 is 0, the behaviour is undefined. */
+#define SLJIT_DIVMOD_UW (SLJIT_OP0_BASE + 4)
+#define SLJIT_DIVMOD_U32 (SLJIT_DIVMOD_UW | SLJIT_32)
+/* Flags: - (may destroy flags)
+ Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
+ The result is placed into SLJIT_R0 and the remainder into SLJIT_R1.
+ Note: if SLJIT_R1 is 0, the behaviour is undefined.
+ Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00),
+ the behaviour is undefined. */
+#define SLJIT_DIVMOD_SW (SLJIT_OP0_BASE + 5)
+#define SLJIT_DIVMOD_S32 (SLJIT_DIVMOD_SW | SLJIT_32)
+/* Flags: - (may destroy flags)
+ Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.
+ The result is placed into SLJIT_R0. SLJIT_R1 preserves its value.
+ Note: if SLJIT_R1 is 0, the behaviour is undefined. */
+#define SLJIT_DIV_UW (SLJIT_OP0_BASE + 6)
+#define SLJIT_DIV_U32 (SLJIT_DIV_UW | SLJIT_32)
+/* Flags: - (may destroy flags)
+ Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
+ The result is placed into SLJIT_R0. SLJIT_R1 preserves its value.
+ Note: if SLJIT_R1 is 0, the behaviour is undefined.
+ Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00),
+ the behaviour is undefined. */
+#define SLJIT_DIV_SW (SLJIT_OP0_BASE + 7)
+#define SLJIT_DIV_S32 (SLJIT_DIV_SW | SLJIT_32)
+/* Flags: - (does not modify flags)
+ May return with SLJIT_ERR_UNSUPPORTED if SLJIT_HAS_MEMORY_BARRIER
+ feature is not supported (calling sljit_has_cpu_feature() with
+ this feature option returns with 0). */
+#define SLJIT_MEMORY_BARRIER (SLJIT_OP0_BASE + 8)
+/* Flags: - (does not modify flags)
+ ENDBR32 instruction for x86-32 and ENDBR64 instruction for x86-64
+ when Intel Control-flow Enforcement Technology (CET) is enabled.
+ No instructions are emitted for other architectures. */
+#define SLJIT_ENDBR (SLJIT_OP0_BASE + 9)
+/* Flags: - (may destroy flags)
+ Skip stack frames before return when Intel Control-flow
+ Enforcement Technology (CET) is enabled. No instructions
+ are emitted for other architectures. */
+#define SLJIT_SKIP_FRAMES_BEFORE_RETURN (SLJIT_OP0_BASE + 10)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op);
+
+/* Starting index of opcodes for sljit_emit_op1. */
+#define SLJIT_OP1_BASE 32
+
+/* The MOV instruction transfers data from source to destination.
+
+ MOV instruction suffixes:
+
+ U8 - unsigned 8 bit data transfer
+ S8 - signed 8 bit data transfer
+ U16 - unsigned 16 bit data transfer
+ S16 - signed 16 bit data transfer
+ U32 - unsigned int (32 bit) data transfer
+ S32 - signed int (32 bit) data transfer
+ P - pointer (sljit_up) data transfer
+*/
+
+/* Flags: - (does not modify flags) */
+#define SLJIT_MOV (SLJIT_OP1_BASE + 0)
+/* Flags: - (does not modify flags) */
+#define SLJIT_MOV_U8 (SLJIT_OP1_BASE + 1)
+#define SLJIT_MOV32_U8 (SLJIT_MOV_U8 | SLJIT_32)
+/* Flags: - (does not modify flags) */
+#define SLJIT_MOV_S8 (SLJIT_OP1_BASE + 2)
+#define SLJIT_MOV32_S8 (SLJIT_MOV_S8 | SLJIT_32)
+/* Flags: - (does not modify flags) */
+#define SLJIT_MOV_U16 (SLJIT_OP1_BASE + 3)
+#define SLJIT_MOV32_U16 (SLJIT_MOV_U16 | SLJIT_32)
+/* Flags: - (does not modify flags) */
+#define SLJIT_MOV_S16 (SLJIT_OP1_BASE + 4)
+#define SLJIT_MOV32_S16 (SLJIT_MOV_S16 | SLJIT_32)
+/* Flags: - (does not modify flags)
+ Note: no SLJIT_MOV32_U32 form, since it is the same as SLJIT_MOV32 */
+#define SLJIT_MOV_U32 (SLJIT_OP1_BASE + 5)
+/* Flags: - (does not modify flags)
+ Note: no SLJIT_MOV32_S32 form, since it is the same as SLJIT_MOV32 */
+#define SLJIT_MOV_S32 (SLJIT_OP1_BASE + 6)
+/* Flags: - (does not modify flags) */
+#define SLJIT_MOV32 (SLJIT_OP1_BASE + 7)
+/* Flags: - (does not modify flags)
+ Note: loads a pointer sized data, useful on x32 mode (a 64 bit mode
+ on x86-64 which uses 32 bit pointers) or similar compiling modes */
+#define SLJIT_MOV_P (SLJIT_OP1_BASE + 8)
+/* Count leading zeroes
+ Flags: - (may destroy flags)
+ Note: immediate source argument is not supported */
+#define SLJIT_CLZ (SLJIT_OP1_BASE + 9)
+#define SLJIT_CLZ32 (SLJIT_CLZ | SLJIT_32)
+/* Count trailing zeroes
+ Flags: - (may destroy flags)
+ Note: immediate source argument is not supported */
+#define SLJIT_CTZ (SLJIT_OP1_BASE + 10)
+#define SLJIT_CTZ32 (SLJIT_CTZ | SLJIT_32)
+/* Reverse the order of bytes
+ Flags: - (may destroy flags)
+ Note: converts between little and big endian formats
+ Note: immediate source argument is not supported */
+#define SLJIT_REV (SLJIT_OP1_BASE + 11)
+#define SLJIT_REV32 (SLJIT_REV | SLJIT_32)
+/* Reverse the order of bytes in the lower 16 bit and extend as unsigned
+ Flags: - (may destroy flags)
+ Note: converts between little and big endian formats
+ Note: immediate source argument is not supported */
+#define SLJIT_REV_U16 (SLJIT_OP1_BASE + 12)
+#define SLJIT_REV32_U16 (SLJIT_REV_U16 | SLJIT_32)
+/* Reverse the order of bytes in the lower 16 bit and extend as signed
+ Flags: - (may destroy flags)
+ Note: converts between little and big endian formats
+ Note: immediate source argument is not supported */
+#define SLJIT_REV_S16 (SLJIT_OP1_BASE + 13)
+#define SLJIT_REV32_S16 (SLJIT_REV_S16 | SLJIT_32)
+/* Reverse the order of bytes in the lower 32 bit and extend as unsigned
+ Flags: - (may destroy flags)
+ Note: converts between little and big endian formats
+ Note: immediate source argument is not supported */
+#define SLJIT_REV_U32 (SLJIT_OP1_BASE + 14)
+/* Reverse the order of bytes in the lower 32 bit and extend as signed
+ Flags: - (may destroy flags)
+ Note: converts between little and big endian formats
+ Note: immediate source argument is not supported */
+#define SLJIT_REV_S32 (SLJIT_OP1_BASE + 15)
+
+/* The following unary operations are supported by using sljit_emit_op2:
+ - binary not: SLJIT_XOR with immedate -1 as src1 or src2
+ - negate: SLJIT_SUB with immedate 0 as src1
+ Note: these operations are optimized by the compiler if the
+ target CPU has specialized instruction forms for them. */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw);
+
+/* Starting index of opcodes for sljit_emit_op2. */
+#define SLJIT_OP2_BASE 64
+
+/* Flags: Z | OVERFLOW | CARRY */
+#define SLJIT_ADD (SLJIT_OP2_BASE + 0)
+#define SLJIT_ADD32 (SLJIT_ADD | SLJIT_32)
+/* Flags: CARRY */
+#define SLJIT_ADDC (SLJIT_OP2_BASE + 1)
+#define SLJIT_ADDC32 (SLJIT_ADDC | SLJIT_32)
+/* Flags: Z | LESS | GREATER_EQUAL | GREATER | LESS_EQUAL
+ SIG_LESS | SIG_GREATER_EQUAL | SIG_GREATER
+ SIG_LESS_EQUAL | OVERFLOW | CARRY */
+#define SLJIT_SUB (SLJIT_OP2_BASE + 2)
+#define SLJIT_SUB32 (SLJIT_SUB | SLJIT_32)
+/* Flags: CARRY */
+#define SLJIT_SUBC (SLJIT_OP2_BASE + 3)
+#define SLJIT_SUBC32 (SLJIT_SUBC | SLJIT_32)
+/* Note: integer mul
+ Flags: OVERFLOW */
+#define SLJIT_MUL (SLJIT_OP2_BASE + 4)
+#define SLJIT_MUL32 (SLJIT_MUL | SLJIT_32)
+/* Flags: Z */
+#define SLJIT_AND (SLJIT_OP2_BASE + 5)
+#define SLJIT_AND32 (SLJIT_AND | SLJIT_32)
+/* Flags: Z */
+#define SLJIT_OR (SLJIT_OP2_BASE + 6)
+#define SLJIT_OR32 (SLJIT_OR | SLJIT_32)
+/* Flags: Z */
+#define SLJIT_XOR (SLJIT_OP2_BASE + 7)
+#define SLJIT_XOR32 (SLJIT_XOR | SLJIT_32)
+/* Flags: Z
+ Let bit_length be the length of the shift operation: 32 or 64.
+ If src2 is immediate, src2w is masked by (bit_length - 1).
+ Otherwise, if the content of src2 is outside the range from 0
+ to bit_length - 1, the result is undefined. */
+#define SLJIT_SHL (SLJIT_OP2_BASE + 8)
+#define SLJIT_SHL32 (SLJIT_SHL | SLJIT_32)
+/* Flags: Z
+ Same as SLJIT_SHL, except the the second operand is
+ always masked by the length of the shift operation. */
+#define SLJIT_MSHL (SLJIT_OP2_BASE + 9)
+#define SLJIT_MSHL32 (SLJIT_MSHL | SLJIT_32)
+/* Flags: Z
+ Let bit_length be the length of the shift operation: 32 or 64.
+ If src2 is immediate, src2w is masked by (bit_length - 1).
+ Otherwise, if the content of src2 is outside the range from 0
+ to bit_length - 1, the result is undefined. */
+#define SLJIT_LSHR (SLJIT_OP2_BASE + 10)
+#define SLJIT_LSHR32 (SLJIT_LSHR | SLJIT_32)
+/* Flags: Z
+ Same as SLJIT_LSHR, except the the second operand is
+ always masked by the length of the shift operation. */
+#define SLJIT_MLSHR (SLJIT_OP2_BASE + 11)
+#define SLJIT_MLSHR32 (SLJIT_MLSHR | SLJIT_32)
+/* Flags: Z
+ Let bit_length be the length of the shift operation: 32 or 64.
+ If src2 is immediate, src2w is masked by (bit_length - 1).
+ Otherwise, if the content of src2 is outside the range from 0
+ to bit_length - 1, the result is undefined. */
+#define SLJIT_ASHR (SLJIT_OP2_BASE + 12)
+#define SLJIT_ASHR32 (SLJIT_ASHR | SLJIT_32)
+/* Flags: Z
+ Same as SLJIT_ASHR, except the the second operand is
+ always masked by the length of the shift operation. */
+#define SLJIT_MASHR (SLJIT_OP2_BASE + 13)
+#define SLJIT_MASHR32 (SLJIT_MASHR | SLJIT_32)
+/* Flags: - (may destroy flags)
+ Let bit_length be the length of the rotate operation: 32 or 64.
+ The second operand is always masked by (bit_length - 1). */
+#define SLJIT_ROTL (SLJIT_OP2_BASE + 14)
+#define SLJIT_ROTL32 (SLJIT_ROTL | SLJIT_32)
+/* Flags: - (may destroy flags)
+ Let bit_length be the length of the rotate operation: 32 or 64.
+ The second operand is always masked by (bit_length - 1). */
+#define SLJIT_ROTR (SLJIT_OP2_BASE + 15)
+#define SLJIT_ROTR32 (SLJIT_ROTR | SLJIT_32)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w);
+
+/* The sljit_emit_op2u function is the same as sljit_emit_op2
+ except the result is discarded. */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w);
+
+/* Starting index of opcodes for sljit_emit_op2r. */
+#define SLJIT_OP2R_BASE 96
+
+/* Flags: - (may destroy flags) */
+#define SLJIT_MULADD (SLJIT_OP2R_BASE + 0)
+#define SLJIT_MULADD32 (SLJIT_MULADD | SLJIT_32)
+
+/* Similar to sljit_emit_fop2, except the destination is always a register. */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w);
+
+/* Emit a left or right shift operation, where the bits shifted
+ in comes from a separate source operand. All operands are
+ interpreted as unsigned integers.
+
+ In the followings the value_mask variable is 31 for 32 bit
+ operations and word_size - 1 otherwise.
+
+ op must be one of the following operations:
+ SLJIT_SHL or SLJIT_SHL32:
+ dst_reg = src1_reg << src3_reg
+ dst_reg |= ((src2_reg >> 1) >> (src3 ^ value_mask))
+ SLJIT_MSHL or SLJIT_MSHL32:
+ src3 &= value_mask
+ perform the SLJIT_SHL or SLJIT_SHL32 operation
+ SLJIT_LSHR or SLJIT_LSHR32:
+ dst_reg = src1_reg >> src3_reg
+ dst_reg |= ((src2_reg << 1) << (src3 ^ value_mask))
+ SLJIT_MLSHR or SLJIT_MLSHR32:
+ src3 &= value_mask
+ perform the SLJIT_LSHR or SLJIT_LSHR32 operation
+
+ op can be combined (or'ed) with SLJIT_SHIFT_INTO_NON_ZERO
+
+ dst_reg specifies the destination register, where dst_reg
+ and src2_reg cannot be the same registers
+ src1_reg specifies the source register
+ src2_reg specifies the register which is shifted into src1_reg
+ src3 / src3w contains the shift amount
+
+ Note: a rotate operation is performed if src1_reg and
+ src2_reg are the same registers
+
+ Flags: - (may destroy flags) */
+
+/* The src3 operand contains a non-zero value. Improves
+ the generated code on certain architectures, which
+ provides a small performance improvement. */
+#define SLJIT_SHIFT_INTO_NON_ZERO 0x200
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1_reg,
+ sljit_s32 src2_reg,
+ sljit_s32 src3, sljit_sw src3w);
+
+/* The following options are used by sljit_emit_op2_shift. */
+
+/* The src2 argument is shifted left by an immedate value. */
+#define SLJIT_SHL_IMM (1 << 9)
+/* When src2 argument is a register, its value is undefined after the operation. */
+#define SLJIT_SRC2_UNDEFINED (1 << 10)
+
+/* Emits an addition operation, where the second argument is shifted by a value.
+
+ op must be SLJIT_ADD | SLJIT_SHL_IMM, where the immedate value is stored in shift_arg
+
+ Flags: - (may destroy flags) */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg);
+
+/* Starting index of opcodes for sljit_emit_op_src
+ and sljit_emit_op_dst. */
+#define SLJIT_OP_SRC_DST_BASE 112
+
+/* Fast return, see SLJIT_FAST_CALL for more details.
+ Note: src cannot be an immedate value
+ Flags: - (does not modify flags) */
+#define SLJIT_FAST_RETURN (SLJIT_OP_SRC_DST_BASE + 0)
+/* Skip stack frames before fast return.
+ Note: src cannot be an immedate value
+ Flags: may destroy flags. */
+#define SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN (SLJIT_OP_SRC_DST_BASE + 1)
+/* Prefetch value into the level 1 data cache
+ Note: if the target CPU does not support data prefetch,
+ no instructions are emitted.
+ Note: this instruction never fails, even if the memory address is invalid.
+ Flags: - (does not modify flags) */
+#define SLJIT_PREFETCH_L1 (SLJIT_OP_SRC_DST_BASE + 2)
+/* Prefetch value into the level 2 data cache
+ Note: same as SLJIT_PREFETCH_L1 if the target CPU
+ does not support this instruction form.
+ Note: this instruction never fails, even if the memory address is invalid.
+ Flags: - (does not modify flags) */
+#define SLJIT_PREFETCH_L2 (SLJIT_OP_SRC_DST_BASE + 3)
+/* Prefetch value into the level 3 data cache
+ Note: same as SLJIT_PREFETCH_L2 if the target CPU
+ does not support this instruction form.
+ Note: this instruction never fails, even if the memory address is invalid.
+ Flags: - (does not modify flags) */
+#define SLJIT_PREFETCH_L3 (SLJIT_OP_SRC_DST_BASE + 4)
+/* Prefetch a value which is only used once (and can be discarded afterwards)
+ Note: same as SLJIT_PREFETCH_L1 if the target CPU
+ does not support this instruction form.
+ Note: this instruction never fails, even if the memory address is invalid.
+ Flags: - (does not modify flags) */
+#define SLJIT_PREFETCH_ONCE (SLJIT_OP_SRC_DST_BASE + 5)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src, sljit_sw srcw);
+
+/* Fast enter, see SLJIT_FAST_CALL for more details.
+ Flags: - (does not modify flags) */
+#define SLJIT_FAST_ENTER (SLJIT_OP_SRC_DST_BASE + 6)
+
+/* Copies the return address into dst. The return address is the
+ address where the execution continues after the called function
+ returns (see: sljit_emit_return / sljit_emit_return_void).
+ Flags: - (does not modify flags) */
+#define SLJIT_GET_RETURN_ADDRESS (SLJIT_OP_SRC_DST_BASE + 7)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw);
+
+/* Starting index of opcodes for sljit_emit_fop1. */
+#define SLJIT_FOP1_BASE 144
+
+/* Flags: - (does not modify flags) */
+#define SLJIT_MOV_F64 (SLJIT_FOP1_BASE + 0)
+#define SLJIT_MOV_F32 (SLJIT_MOV_F64 | SLJIT_32)
+/* Convert opcodes: CONV[DST_TYPE].FROM[SRC_TYPE]
+ SRC/DST TYPE can be: F64, F32, S32, SW
+ Rounding mode when the destination is SW or S32: round towards zero. */
+/* Flags: - (may destroy flags) */
+#define SLJIT_CONV_F64_FROM_F32 (SLJIT_FOP1_BASE + 1)
+#define SLJIT_CONV_F32_FROM_F64 (SLJIT_CONV_F64_FROM_F32 | SLJIT_32)
+/* Flags: - (may destroy flags) */
+#define SLJIT_CONV_SW_FROM_F64 (SLJIT_FOP1_BASE + 2)
+#define SLJIT_CONV_SW_FROM_F32 (SLJIT_CONV_SW_FROM_F64 | SLJIT_32)
+/* Flags: - (may destroy flags) */
+#define SLJIT_CONV_S32_FROM_F64 (SLJIT_FOP1_BASE + 3)
+#define SLJIT_CONV_S32_FROM_F32 (SLJIT_CONV_S32_FROM_F64 | SLJIT_32)
+/* Flags: - (may destroy flags) */
+#define SLJIT_CONV_F64_FROM_SW (SLJIT_FOP1_BASE + 4)
+#define SLJIT_CONV_F32_FROM_SW (SLJIT_CONV_F64_FROM_SW | SLJIT_32)
+/* Flags: - (may destroy flags) */
+#define SLJIT_CONV_F64_FROM_S32 (SLJIT_FOP1_BASE + 5)
+#define SLJIT_CONV_F32_FROM_S32 (SLJIT_CONV_F64_FROM_S32 | SLJIT_32)
+/* Flags: - (may destroy flags) */
+#define SLJIT_CONV_F64_FROM_UW (SLJIT_FOP1_BASE + 6)
+#define SLJIT_CONV_F32_FROM_UW (SLJIT_CONV_F64_FROM_UW | SLJIT_32)
+/* Flags: - (may destroy flags) */
+#define SLJIT_CONV_F64_FROM_U32 (SLJIT_FOP1_BASE + 7)
+#define SLJIT_CONV_F32_FROM_U32 (SLJIT_CONV_F64_FROM_U32 | SLJIT_32)
+/* Note: dst is the left and src is the right operand for SLJIT_CMP_F32/64.
+ Flags: EQUAL_F | LESS_F | GREATER_EQUAL_F | GREATER_F | LESS_EQUAL_F */
+#define SLJIT_CMP_F64 (SLJIT_FOP1_BASE + 8)
+#define SLJIT_CMP_F32 (SLJIT_CMP_F64 | SLJIT_32)
+/* Flags: - (may destroy flags) */
+#define SLJIT_NEG_F64 (SLJIT_FOP1_BASE + 9)
+#define SLJIT_NEG_F32 (SLJIT_NEG_F64 | SLJIT_32)
+/* Flags: - (may destroy flags) */
+#define SLJIT_ABS_F64 (SLJIT_FOP1_BASE + 10)
+#define SLJIT_ABS_F32 (SLJIT_ABS_F64 | SLJIT_32)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw);
+
+/* Starting index of opcodes for sljit_emit_fop2. */
+#define SLJIT_FOP2_BASE 176
+
+/* Flags: - (may destroy flags) */
+#define SLJIT_ADD_F64 (SLJIT_FOP2_BASE + 0)
+#define SLJIT_ADD_F32 (SLJIT_ADD_F64 | SLJIT_32)
+/* Flags: - (may destroy flags) */
+#define SLJIT_SUB_F64 (SLJIT_FOP2_BASE + 1)
+#define SLJIT_SUB_F32 (SLJIT_SUB_F64 | SLJIT_32)
+/* Flags: - (may destroy flags) */
+#define SLJIT_MUL_F64 (SLJIT_FOP2_BASE + 2)
+#define SLJIT_MUL_F32 (SLJIT_MUL_F64 | SLJIT_32)
+/* Flags: - (may destroy flags) */
+#define SLJIT_DIV_F64 (SLJIT_FOP2_BASE + 3)
+#define SLJIT_DIV_F32 (SLJIT_DIV_F64 | SLJIT_32)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w);
+
+/* Starting index of opcodes for sljit_emit_fop2r. */
+#define SLJIT_FOP2R_BASE 192
+
+/* Flags: - (may destroy flags) */
+#define SLJIT_COPYSIGN_F64 (SLJIT_FOP2R_BASE + 0)
+#define SLJIT_COPYSIGN_F32 (SLJIT_COPYSIGN_F64 | SLJIT_32)
+
+/* Similar to sljit_emit_fop2, except the destination is always a register. */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w);
+
+/* Sets a floating point register to an immediate value. */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f32 value);
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value);
+
+/* The following opcodes are used by sljit_emit_fcopy(). */
+
+/* 64 bit: copy a 64 bit value from an integer register into a
+ 64 bit floating point register without any modifications.
+ 32 bit: copy a 32 bit register or register pair into a 64 bit
+ floating point register without any modifications. The
+ register, or the first register of the register pair
+ replaces the high order 32 bit of the floating point
+ register. If a register pair is passed, the low
+ order 32 bit is replaced by the second register.
+ Otherwise, the low order 32 bit is unchanged. */
+#define SLJIT_COPY_TO_F64 1
+/* Copy a 32 bit value from an integer register into a 32 bit
+ floating point register without any modifications. */
+#define SLJIT_COPY32_TO_F32 (SLJIT_COPY_TO_F64 | SLJIT_32)
+/* 64 bit: copy the value of a 64 bit floating point register into
+ an integer register without any modifications.
+ 32 bit: copy a 64 bit floating point register into a 32 bit register
+ or a 32 bit register pair without any modifications. The
+ high order 32 bit of the floating point register is copied
+ into the register, or the first register of the register
+ pair. If a register pair is passed, the low order 32 bit
+ is copied into the second register. */
+#define SLJIT_COPY_FROM_F64 2
+/* Copy the value of a 32 bit floating point register into an integer
+ register without any modifications. The register should be processed
+ with 32 bit operations later. */
+#define SLJIT_COPY32_FROM_F32 (SLJIT_COPY_FROM_F64 | SLJIT_32)
+
+/* Special data copy which involves floating point registers.
+
+ op must be between SLJIT_COPY_TO_F64 and SLJIT_COPY32_FROM_F32
+ freg must be a floating point register
+ reg must be a register or register pair */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg);
+
+/* Label and jump instructions. */
+
+/* Emits a label which can be the target of jump / mov_addr instructions. */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler);
+
+/* Alignment values for sljit_emit_aligned_label. */
+
+#define SLJIT_LABEL_ALIGN_1 0
+#define SLJIT_LABEL_ALIGN_2 1
+#define SLJIT_LABEL_ALIGN_4 2
+#define SLJIT_LABEL_ALIGN_8 3
+#define SLJIT_LABEL_ALIGN_16 4
+#define SLJIT_LABEL_ALIGN_W SLJIT_WORD_SHIFT
+#define SLJIT_LABEL_ALIGN_P SLJIT_POINTER_SHIFT
+
+/* Emits a label which address is aligned to a power of 2 value. When some
+ extra space needs to be added to align the label, that space is filled
+ with SLJIT_NOP instructions. These labels usually represent the end of a
+ compilation block, and a new function or some read-only data (e.g. a
+ jump table) follows it. In these typical cases the SLJIT_NOPs are never
+ executed.
+
+ Optionally, buffers for storing read-only data or code can be allocated
+ by this operation. The buffers are passed as a chain list, and a separate
+ memory area is allocated for each item in the list. All buffers are aligned
+ to SLJIT_NOP instruction size, and their starting address is returned as
+ as a label. The sljit_get_label_abs_addr function or the SLJIT_MOV_ABS_ADDR
+ operation can be used to get the real address. The label of the first buffer
+ is always the same as the returned label. The buffers are initially
+ initialized with SLJIT_NOP instructions. The alignment of the buffers can
+ be controlled by their starting address and sizes. If the starting address
+ is aligned to N, and size is also divisible by N, the next buffer is aligned
+ to N. I.e. if a buffer is 16 byte aligned, and its size is divisible by 4,
+ the next buffer is 4 byte aligned. Note: if a buffer is N (>=2) byte aligned,
+ it is also N/2 byte aligned.
+
+ align represents the alignment, and its value can
+ be specified by SLJIT_LABEL_* constants
+
+ buffers is a list of read-only buffers stored in a chain list.
+ After calling sljit_generate_code, these buffers can be
+ modified by sljit_read_only_buffer_start_writing() /
+ sljit_read_only_buffer_end_writing() functions
+
+ Note: the constant pool (if present) may be stored before the label. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers);
+
+/* The SLJIT_FAST_CALL is a calling method for creating lightweight function
+ calls. This type of calls preserve the values of all registers and stack
+ frame. Unlike normal function calls, the enter and return operations must
+ be performed by the SLJIT_FAST_ENTER and SLJIT_FAST_RETURN operations
+ respectively. The return address is stored in the dst argument of the
+ SLJIT_FAST_ENTER operation, and this return address should be passed as
+ the src argument for the SLJIT_FAST_RETURN operation to return from the
+ called function.
+
+ Fast calls are cheap operations (usually only a single call instruction is
+ emitted) but they do not preserve any registers. However the callee function
+ can freely use / update any registers and the locals area which can be
+ efficiently exploited by various optimizations. Registers can be saved
+ and restored manually if needed.
+
+ Although returning to different address by SLJIT_FAST_RETURN is possible,
+ this address usually cannot be predicted by the return address predictor of
+ modern CPUs which may reduce performance. Furthermore certain security
+ enhancement technologies such as Intel Control-flow Enforcement Technology
+ (CET) may disallow returning to a different address (indirect jumps
+ can be used instead, see SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN). */
+
+/* Invert (negate) conditional type: xor (^) with 0x1 */
+
+/* Integer comparison types. */
+#define SLJIT_EQUAL 0
+#define SLJIT_ZERO SLJIT_EQUAL
+#define SLJIT_NOT_EQUAL 1
+#define SLJIT_NOT_ZERO SLJIT_NOT_EQUAL
+
+#define SLJIT_LESS 2
+#define SLJIT_SET_LESS SLJIT_SET(SLJIT_LESS)
+#define SLJIT_GREATER_EQUAL 3
+#define SLJIT_SET_GREATER_EQUAL SLJIT_SET(SLJIT_LESS)
+#define SLJIT_GREATER 4
+#define SLJIT_SET_GREATER SLJIT_SET(SLJIT_GREATER)
+#define SLJIT_LESS_EQUAL 5
+#define SLJIT_SET_LESS_EQUAL SLJIT_SET(SLJIT_GREATER)
+#define SLJIT_SIG_LESS 6
+#define SLJIT_SET_SIG_LESS SLJIT_SET(SLJIT_SIG_LESS)
+#define SLJIT_SIG_GREATER_EQUAL 7
+#define SLJIT_SET_SIG_GREATER_EQUAL SLJIT_SET(SLJIT_SIG_LESS)
+#define SLJIT_SIG_GREATER 8
+#define SLJIT_SET_SIG_GREATER SLJIT_SET(SLJIT_SIG_GREATER)
+#define SLJIT_SIG_LESS_EQUAL 9
+#define SLJIT_SET_SIG_LESS_EQUAL SLJIT_SET(SLJIT_SIG_GREATER)
+
+#define SLJIT_OVERFLOW 10
+#define SLJIT_SET_OVERFLOW SLJIT_SET(SLJIT_OVERFLOW)
+#define SLJIT_NOT_OVERFLOW 11
+
+/* Unlike other comparison types, sljit_emit_jump may destroy zero flag
+ when carry flag is specified (powerpc limitation). Furthermore,
+ SLJIT_CARRY represents that the first operand is unsigned less than
+ the second operand after an SLJIT_SUB / SLJIT_SUBC operation. */
+#define SLJIT_CARRY 12
+#define SLJIT_SET_CARRY SLJIT_SET(SLJIT_CARRY)
+#define SLJIT_NOT_CARRY 13
+
+#define SLJIT_ATOMIC_STORED 14
+#define SLJIT_SET_ATOMIC_STORED SLJIT_SET(SLJIT_ATOMIC_STORED)
+#define SLJIT_ATOMIC_NOT_STORED 15
+
+/* Basic floating point comparison types.
+
+ Note: when the comparison result is unordered, their behaviour is unspecified. */
+
+#define SLJIT_F_EQUAL 16
+#define SLJIT_SET_F_EQUAL SLJIT_SET(SLJIT_F_EQUAL)
+#define SLJIT_F_NOT_EQUAL 17
+#define SLJIT_SET_F_NOT_EQUAL SLJIT_SET(SLJIT_F_EQUAL)
+#define SLJIT_F_LESS 18
+#define SLJIT_SET_F_LESS SLJIT_SET(SLJIT_F_LESS)
+#define SLJIT_F_GREATER_EQUAL 19
+#define SLJIT_SET_F_GREATER_EQUAL SLJIT_SET(SLJIT_F_LESS)
+#define SLJIT_F_GREATER 20
+#define SLJIT_SET_F_GREATER SLJIT_SET(SLJIT_F_GREATER)
+#define SLJIT_F_LESS_EQUAL 21
+#define SLJIT_SET_F_LESS_EQUAL SLJIT_SET(SLJIT_F_GREATER)
+
+/* Jumps when either argument contains a NaN value. */
+#define SLJIT_UNORDERED 22
+#define SLJIT_SET_UNORDERED SLJIT_SET(SLJIT_UNORDERED)
+/* Jumps when neither argument contains a NaN value. */
+#define SLJIT_ORDERED 23
+#define SLJIT_SET_ORDERED SLJIT_SET(SLJIT_UNORDERED)
+
+/* Ordered / unordered floating point comparison types.
+
+ Note: each comparison type has an ordered and unordered form. Some
+ architectures supports only either of them (see: sljit_cmp_info). */
+
+#define SLJIT_ORDERED_EQUAL 24
+#define SLJIT_SET_ORDERED_EQUAL SLJIT_SET(SLJIT_ORDERED_EQUAL)
+#define SLJIT_UNORDERED_OR_NOT_EQUAL 25
+#define SLJIT_SET_UNORDERED_OR_NOT_EQUAL SLJIT_SET(SLJIT_ORDERED_EQUAL)
+#define SLJIT_ORDERED_LESS 26
+#define SLJIT_SET_ORDERED_LESS SLJIT_SET(SLJIT_ORDERED_LESS)
+#define SLJIT_UNORDERED_OR_GREATER_EQUAL 27
+#define SLJIT_SET_UNORDERED_OR_GREATER_EQUAL SLJIT_SET(SLJIT_ORDERED_LESS)
+#define SLJIT_ORDERED_GREATER 28
+#define SLJIT_SET_ORDERED_GREATER SLJIT_SET(SLJIT_ORDERED_GREATER)
+#define SLJIT_UNORDERED_OR_LESS_EQUAL 29
+#define SLJIT_SET_UNORDERED_OR_LESS_EQUAL SLJIT_SET(SLJIT_ORDERED_GREATER)
+
+#define SLJIT_UNORDERED_OR_EQUAL 30
+#define SLJIT_SET_UNORDERED_OR_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_EQUAL)
+#define SLJIT_ORDERED_NOT_EQUAL 31
+#define SLJIT_SET_ORDERED_NOT_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_EQUAL)
+#define SLJIT_UNORDERED_OR_LESS 32
+#define SLJIT_SET_UNORDERED_OR_LESS SLJIT_SET(SLJIT_UNORDERED_OR_LESS)
+#define SLJIT_ORDERED_GREATER_EQUAL 33
+#define SLJIT_SET_ORDERED_GREATER_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_LESS)
+#define SLJIT_UNORDERED_OR_GREATER 34
+#define SLJIT_SET_UNORDERED_OR_GREATER SLJIT_SET(SLJIT_UNORDERED_OR_GREATER)
+#define SLJIT_ORDERED_LESS_EQUAL 35
+#define SLJIT_SET_ORDERED_LESS_EQUAL SLJIT_SET(SLJIT_UNORDERED_OR_GREATER)
+
+/* Unconditional jump types. */
+#define SLJIT_JUMP 36
+/* Fast calling method. See the description above. */
+#define SLJIT_FAST_CALL 37
+/* Default C calling convention. */
+#define SLJIT_CALL 38
+/* Called function must be compiled by SLJIT.
+ See SLJIT_ENTER_REG_ARG option. */
+#define SLJIT_CALL_REG_ARG 39
+
+/* The target can be changed during runtime (see: sljit_set_jump_addr). */
+#define SLJIT_REWRITABLE_JUMP 0x10000
+/* When this flag is passed, the execution of the current function ends and
+ the called function returns to the caller of the current function. The
+ stack usage is reduced before the call, but it is not necessarily reduced
+ to zero. In the latter case the compiler needs to allocate space for some
+ arguments and the return address must be stored on the stack as well. */
+#define SLJIT_CALL_RETURN 0x20000
+
+/* Emit a jump instruction. The destination is not set, only the type of the jump.
+ type must be between SLJIT_JUMP and SLJIT_FAST_CALL
+ type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
+
+ Flags: does not modify flags. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type);
+
+/* Emit a C compiler (ABI) compatible function call.
+ type must be SLJIT_CALL or SLJIT_CALL_REG_ARG
+ type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP and/or SLJIT_CALL_RETURN
+ arg_types can be specified by SLJIT_ARGSx (SLJIT_ARG_RETURN / SLJIT_ARG_VALUE) macros
+
+ Flags: destroy all flags. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types);
+
+/* Integer comparison operation. In most architectures it is implemented
+ as a compare (sljit_emit_op2u with SLJIT_SUB) operation followed by
+ an sljit_emit_jump. However, some architectures (e.g: ARM64 or RISCV)
+ may optimize the generated code further. It is suggested to use this
+ comparison form when appropriate.
+ type must be between SLJIT_EQUAL and SLJIT_SIG_LESS_EQUAL
+ type can be combined (or'ed) with SLJIT_32 or SLJIT_REWRITABLE_JUMP
+
+ Flags: may destroy flags. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w);
+
+/* Floating point comparison operation. In most architectures it is
+ implemented as a SLJIT_CMP_F32/64 operation (setting appropriate
+ flags) followed by a sljit_emit_jump. However, some architectures
+ (e.g: MIPS) may optimize the generated code further. It is suggested
+ to use this comparison form when appropriate.
+ type must be between SLJIT_F_EQUAL and SLJIT_ORDERED_LESS_EQUAL
+ type can be combined (or'ed) with SLJIT_32 or SLJIT_REWRITABLE_JUMP
+
+ Flags: destroy flags.
+ Note: when any operand is NaN the behaviour depends on the comparison type. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w);
+
+/* The following flags are used by sljit_emit_op2cmpz(). */
+#define SLJIT_JUMP_IF_NON_ZERO 0
+#define SLJIT_JUMP_IF_ZERO SLJIT_SET_Z
+
+/* Perform an integer arithmetic operation, then its result is compared to
+ zero. In most architectures it is implemented as an sljit_emit_op2
+ followed by an sljit_emit_jump. However, some architectures (e.g: RISCV)
+ may optimize the generated code further. It is suggested to use this
+ operation form when appropriate (e.g. for loops with counters).
+
+ op must be an sljit_emit_op2 operation where zero flag can be set,
+ op can be combined with SLJIT_SET_* status flag setters except
+ SLJIT_SET_Z, SLJIT_REWRITABLE_JUMP or SLJIT_JUMP_IF_* option bits.
+
+ Note: SLJIT_JUMP_IF_NON_ZERO is the default operation if neither
+ SLJIT_JUMP_IF_ZERO or SLJIT_JUMP_IF_NON_ZERO is specified.
+ Flags: sets the variable flag depending on op argument, the
+ zero flag is undefined. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op2cmpz(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w);
+
+/* Set the destination of the jump to this label. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label);
+/* Set the destination address of the jump to this label. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target);
+
+/* Emit an indirect jump or fast call.
+ Direct form: set src to SLJIT_IMM() and srcw to the address
+ Indirect form: any other valid addressing mode
+ type must be between SLJIT_JUMP and SLJIT_FAST_CALL
+
+ Flags: does not modify flags. */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw);
+
+/* Emit a C compiler (ABI) compatible function call.
+ Direct form: set src to SLJIT_IMM() and srcw to the address
+ Indirect form: any other valid addressing mode
+ type must be SLJIT_CALL or SLJIT_CALL_REG_ARG
+ type can be combined (or'ed) with SLJIT_CALL_RETURN
+ arg_types can be specified by SLJIT_ARGSx (SLJIT_ARG_RETURN / SLJIT_ARG_VALUE) macros
+
+ Flags: destroy all flags. */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types, sljit_s32 src, sljit_sw srcw);
+
+/* Perform an operation using the conditional flags as the second argument.
+ Type must always be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL.
+ The value represented by the type is 1, if the condition represented
+ by type is fulfilled, and 0 otherwise.
+
+ When op is SLJIT_MOV or SLJIT_MOV32:
+ Set dst to the value represented by the type (0 or 1).
+ Flags: - (does not modify flags)
+ When op is SLJIT_AND, SLJIT_AND32, SLJIT_OR, SLJIT_OR32, SLJIT_XOR, or SLJIT_XOR32
+ Performs the binary operation using dst as the first, and the value
+ represented by type as the second argument. Result is written into dst.
+ Flags: Z (may destroy flags) */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 type);
+
+/* The following flags are used by sljit_emit_select(). */
+
+/* Compare src1 and src2_reg operands before executing select
+ (i.e. converts the select operation to a min/max operation). */
+#define SLJIT_COMPARE_SELECT SLJIT_SET_Z
+
+/* Emit a conditional select instruction which moves src1 to dst_reg,
+ if the conditional flag is set, or src2_reg to dst_reg otherwise.
+ The conditional flag should be set before executing the select
+ instruction unless SLJIT_COMPARE_SELECT is specified.
+
+ type must be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL
+ when SLJIT_COMPARE_SELECT option is NOT specified
+ type must be between SLJIT_LESS and SLJIT_SET_SIG_LESS_EQUAL
+ when SLJIT_COMPARE_SELECT option is specified
+ type can be combined (or'ed) with SLJIT_32 to move 32 bit
+ register values instead of word sized ones
+ type can be combined (or'ed) with SLJIT_COMPARE_SELECT
+ which compares src1 and src2_reg before executing the select
+ dst_reg and src2_reg must be valid registers
+ src1 must be valid operand
+
+ Note: if src1 is a memory operand, its value
+ might be loaded even if the condition is false
+
+ Note: when SLJIT_COMPARE_SELECT is specified, the status flag
+ bits might not represent the result of a normal compare
+ operation, hence flags are not specified after the operation
+
+ Note: if sljit_has_cpu_feature(SLJIT_HAS_CMOV) returns with a non-zero value:
+ (a) conditional register move (dst_reg==src2_reg, src1 is register)
+ can be performed using a single instruction, except on RISCV,
+ where three instructions are needed
+ (b) conditional clearing (dst_reg==src2_reg, src1==SLJIT_IMM,
+ src1w==0) can be performed using a single instruction,
+ except on x86, where two instructions are needed
+
+ Flags:
+ When SLJIT_COMPARE_SELECT is NOT specified: - (does not modify flags)
+ When SLJIT_COMPARE_SELECT is specified: - (may destroy flags) */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_reg);
+
+/* Emit a conditional floating point select instruction which moves
+ src1 to dst_reg, if the conditional flag is set, or src2_reg to
+ dst_reg otherwise. The conditional flag should be set before
+ executing the select instruction.
+
+ type must be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL
+ type can be combined (or'ed) with SLJIT_32 to move 32 bit
+ floating point values instead of 64 bit ones
+ dst_freg and src2_freg must be valid floating point registers
+ src1 must be valid operand
+
+ Note: if src1 is a memory operand, its value
+ might be loaded even if the condition is false.
+
+ Flags: - (does not modify flags) */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_freg);
+
+/* The following flags are used by sljit_emit_mem(), sljit_emit_mem_update(),
+ sljit_emit_fmem(), and sljit_emit_fmem_update(). */
+
+/* Memory load operation. This is the default. */
+#define SLJIT_MEM_LOAD 0x000000
+/* Memory store operation. */
+#define SLJIT_MEM_STORE 0x000200
+
+/* The following flags are used by sljit_emit_mem() and sljit_emit_fmem(). */
+
+/* Load or store data from an unaligned (byte aligned) address. */
+#define SLJIT_MEM_UNALIGNED 0x000400
+/* Load or store data from a 16 bit aligned address. */
+#define SLJIT_MEM_ALIGNED_16 0x000800
+/* Load or store data from a 32 bit aligned address. */
+#define SLJIT_MEM_ALIGNED_32 0x001000
+
+/* The following flags are used by sljit_emit_mem_update(),
+ and sljit_emit_fmem_update(). */
+
+/* Base register is updated before the memory access (default). */
+#define SLJIT_MEM_PRE 0x000000
+/* Base register is updated after the memory access. */
+#define SLJIT_MEM_POST 0x000400
+
+/* When SLJIT_MEM_SUPP is passed, no instructions are emitted.
+ Instead the function returns with SLJIT_SUCCESS if the instruction
+ form is supported and SLJIT_ERR_UNSUPPORTED otherwise. This flag
+ allows runtime checking of available instruction forms. */
+#define SLJIT_MEM_SUPP 0x000800
+
+/* The sljit_emit_mem emits instructions for various memory operations:
+
+ When SLJIT_MEM_UNALIGNED / SLJIT_MEM_ALIGNED_16 /
+ SLJIT_MEM_ALIGNED_32 is set in type argument:
+ Emit instructions for unaligned memory loads or stores. When
+ SLJIT_UNALIGNED is not defined, the only way to access unaligned
+ memory data is using sljit_emit_mem. Otherwise all operations (e.g.
+ sljit_emit_op1/2, or sljit_emit_fop1/2) supports unaligned access.
+ In general, the performance of unaligned memory accesses are often
+ lower than aligned and should be avoided.
+
+ When a pair of registers is passed in reg argument:
+ Emit instructions for moving data between a register pair and
+ memory. The register pair can be specified by the SLJIT_REG_PAIR
+ macro. The first register is loaded from or stored into the
+ location specified by the mem/memw arguments, and the end address
+ of this operation is the starting address of the data transfer
+ between the second register and memory. The type argument must
+ be SLJIT_MOV. The SLJIT_MEM_UNALIGNED / SLJIT_MEM_ALIGNED_*
+ options are allowed for this operation.
+
+ type must be between SLJIT_MOV and SLJIT_MOV_P and can be
+ combined (or'ed) with SLJIT_MEM_* flags
+ reg is a register or register pair, which is the source or
+ destination of the operation
+ mem must be a memory operand
+
+ Flags: - (does not modify flags) */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw);
+
+/* Emit a single memory load or store with update instruction.
+ When the requested instruction form is not supported by the CPU,
+ it returns with SLJIT_ERR_UNSUPPORTED instead of emulating the
+ instruction. This allows specializing tight loops based on
+ the supported instruction forms (see SLJIT_MEM_SUPP flag).
+ Absolute address (SLJIT_MEM0) forms are never supported
+ and the base (first) register specified by the mem argument
+ must not be SLJIT_SP and must also be different from the
+ register specified by the reg argument.
+
+ type must be between SLJIT_MOV and SLJIT_MOV_P and can be
+ combined (or'ed) with SLJIT_MEM_* flags
+ reg is the source or destination register of the operation
+ mem must be a memory operand
+
+ Flags: - (does not modify flags) */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw);
+
+/* Same as sljit_emit_mem except the followings:
+
+ Loading or storing a pair of registers is not supported.
+
+ type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be
+ combined (or'ed) with SLJIT_MEM_* flags.
+ freg is the source or destination floating point register
+ of the operation
+ mem must be a memory operand
+
+ Flags: - (does not modify flags) */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 freg,
+ sljit_s32 mem, sljit_sw memw);
+
+/* Same as sljit_emit_mem_update except the followings:
+
+ type must be SLJIT_MOV_F64 or SLJIT_MOV_F32 and can be
+ combined (or'ed) with SLJIT_MEM_* flags
+ freg is the source or destination floating point register
+ of the operation
+ mem must be a memory operand
+
+ Flags: - (does not modify flags) */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 freg,
+ sljit_s32 mem, sljit_sw memw);
+
+/* The following options are used by several simd operations. */
+
+/* Load data into a vector register, this is the default */
+#define SLJIT_SIMD_LOAD 0x000000
+/* Store data from a vector register */
+#define SLJIT_SIMD_STORE 0x000001
+/* The vector register contains floating point values */
+#define SLJIT_SIMD_FLOAT 0x000400
+/* Tests whether the operation is available */
+#define SLJIT_SIMD_TEST 0x000800
+/* Move data to/from a 64 bit (8 byte) long vector register */
+#define SLJIT_SIMD_REG_64 (3 << 12)
+/* Move data to/from a 128 bit (16 byte) long vector register */
+#define SLJIT_SIMD_REG_128 (4 << 12)
+/* Move data to/from a 256 bit (32 byte) long vector register */
+#define SLJIT_SIMD_REG_256 (5 << 12)
+/* Move data to/from a 512 bit (64 byte) long vector register */
+#define SLJIT_SIMD_REG_512 (6 << 12)
+/* Element size is 8 bit long (this is the default), usually cannot be combined with SLJIT_SIMD_FLOAT */
+#define SLJIT_SIMD_ELEM_8 (0 << 18)
+/* Element size is 16 bit long, usually cannot be combined with SLJIT_SIMD_FLOAT */
+#define SLJIT_SIMD_ELEM_16 (1 << 18)
+/* Element size is 32 bit long */
+#define SLJIT_SIMD_ELEM_32 (2 << 18)
+/* Element size is 64 bit long */
+#define SLJIT_SIMD_ELEM_64 (3 << 18)
+/* Element size is 128 bit long */
+#define SLJIT_SIMD_ELEM_128 (4 << 18)
+/* Element size is 256 bit long */
+#define SLJIT_SIMD_ELEM_256 (5 << 18)
+
+/* The following options are used by sljit_emit_simd_mov()
+ and sljit_emit_simd_op2(). */
+
+/* Memory address is unaligned (this is the default) */
+#define SLJIT_SIMD_MEM_UNALIGNED (0 << 24)
+/* Memory address is 16 bit aligned */
+#define SLJIT_SIMD_MEM_ALIGNED_16 (1 << 24)
+/* Memory address is 32 bit aligned */
+#define SLJIT_SIMD_MEM_ALIGNED_32 (2 << 24)
+/* Memory address is 64 bit aligned */
+#define SLJIT_SIMD_MEM_ALIGNED_64 (3 << 24)
+/* Memory address is 128 bit aligned */
+#define SLJIT_SIMD_MEM_ALIGNED_128 (4 << 24)
+/* Memory address is 256 bit aligned */
+#define SLJIT_SIMD_MEM_ALIGNED_256 (5 << 24)
+/* Memory address is 512 bit aligned */
+#define SLJIT_SIMD_MEM_ALIGNED_512 (6 << 24)
+
+/* Moves data between a vector register and memory.
+
+ If the operation is not supported, it returns with
+ SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed,
+ it does not emit any instructions.
+
+ type must be a combination of SLJIT_SIMD_* and
+ SLJIT_SIMD_MEM_* options
+ vreg is the source or destination vector register
+ of the operation
+ srcdst must be a memory operand or a vector register
+
+ Note:
+ The alignment and element size must be
+ less or equal than vector register size.
+
+ Flags: - (does not modify flags) */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 srcdst, sljit_sw srcdstw);
+
+/* Replicates a scalar value to all lanes of a vector
+ register.
+
+ If the operation is not supported, it returns with
+ SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed,
+ it does not emit any instructions.
+
+ type must be a combination of SLJIT_SIMD_* options
+ except SLJIT_SIMD_STORE.
+ vreg is the destination vector register of the operation
+ src is the value which is replicated
+
+ Note:
+ The src == SLJIT_IMM and srcw == 0 can be used to
+ clear a register even when SLJIT_SIMD_FLOAT is set.
+
+ Flags: - (does not modify flags) */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw);
+
+/* The following options are used by sljit_emit_simd_lane_mov(). */
+
+/* Clear all bits of the simd register before loading the lane. */
+#define SLJIT_SIMD_LANE_ZERO 0x000002
+/* Sign extend the integer value stored from the lane. */
+#define SLJIT_SIMD_LANE_SIGNED 0x000004
+
+/* Moves data between a vector register lane and a register or
+ memory. If the srcdst argument is a register, it must be
+ a floating point register when SLJIT_SIMD_FLOAT is specified,
+ or a general purpose register otherwise.
+
+ If the operation is not supported, it returns with
+ SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed,
+ it does not emit any instructions.
+
+ type must be a combination of SLJIT_SIMD_* options
+ Further options:
+ SLJIT_32 - when SLJIT_SIMD_FLOAT is not set
+ SLJIT_SIMD_LANE_SIGNED - when SLJIT_SIMD_STORE
+ is set and SLJIT_SIMD_FLOAT is not set
+ SLJIT_SIMD_LANE_ZERO - when SLJIT_SIMD_LOAD
+ is specified
+ vreg is the source or destination vector register
+ of the operation
+ lane_index is the index of the lane
+ srcdst is the destination operand for loads, and
+ source operand for stores
+
+ Note:
+ The elem size must be lower than register size.
+
+ Flags: - (does not modify flags) */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg, sljit_s32 lane_index,
+ sljit_s32 srcdst, sljit_sw srcdstw);
+
+/* Replicates a scalar value from a lane to all lanes
+ of a vector register.
+
+ If the operation is not supported, it returns with
+ SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed,
+ it does not emit any instructions.
+
+ type must be a combination of SLJIT_SIMD_* options
+ except SLJIT_SIMD_STORE.
+ vreg is the destination vector register of the operation
+ src is the vector register which lane is replicated
+ src_lane_index is the lane index of the src register
+
+ Flags: - (does not modify flags) */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_s32 src_lane_index);
+
+/* The following options are used by sljit_emit_simd_load_extend(). */
+
+/* Sign extend the integer elements */
+#define SLJIT_SIMD_EXTEND_SIGNED 0x000002
+/* Extend data to 16 bit */
+#define SLJIT_SIMD_EXTEND_16 (1 << 24)
+/* Extend data to 32 bit */
+#define SLJIT_SIMD_EXTEND_32 (2 << 24)
+/* Extend data to 64 bit */
+#define SLJIT_SIMD_EXTEND_64 (3 << 24)
+
+/* Extend elements and stores them in a vector register.
+ The extension operation increases the size of the
+ elements (e.g. from 16 bit to 64 bit). For integer
+ values, the extension can be signed or unsigned.
+
+ If the operation is not supported, it returns with
+ SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed,
+ it does not emit any instructions.
+
+ type must be a combination of SLJIT_SIMD_*, and
+ SLJIT_SIMD_EXTEND_* options except SLJIT_SIMD_STORE
+ vreg is the destination vector register of the operation
+ src must be a memory operand or a vector register.
+ In the latter case, the source elements are stored
+ in the lower half of the register.
+
+ Flags: - (does not modify flags) */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw);
+
+/* Extract the highest bit (usually the sign bit) from
+ each elements of a vector.
+
+ If the operation is not supported, it returns with
+ SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed,
+ it does not emit any instructions.
+
+ type must be a combination of SLJIT_SIMD_* and SLJIT_32
+ options except SLJIT_SIMD_LOAD
+ vreg is the source vector register of the operation
+ dst is the destination operand
+
+ Flags: - (does not modify flags) */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 dst, sljit_sw dstw);
+
+/* The following operations are used by sljit_emit_simd_op2(). */
+
+/* Binary 'and' operation */
+#define SLJIT_SIMD_OP2_AND 0x000001
+/* Binary 'or' operation */
+#define SLJIT_SIMD_OP2_OR 0x000002
+/* Binary 'xor' operation */
+#define SLJIT_SIMD_OP2_XOR 0x000003
+/* Shuffle bytes of src1 using the indicies in src2 */
+#define SLJIT_SIMD_OP2_SHUFFLE 0x000004
+
+/* Perform simd operations using vector registers.
+
+ If the operation is not supported, it returns with
+ SLJIT_ERR_UNSUPPORTED. If SLJIT_SIMD_TEST is passed,
+ it does not emit any instructions.
+
+ type must be a combination of SLJIT_SIMD_*, SLJIT_SIMD_MEM_*
+ and SLJIT_SIMD_OP2_* options except SLJIT_SIMD_LOAD
+ and SLJIT_SIMD_STORE
+ dst_vreg is the destination register of the operation
+ src1_vreg is the first source register of the operation
+ src2 is the second source operand of the operation
+
+ Flags: - (does not modify flags) */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w);
+
+/* The following operations are used by sljit_emit_atomic_load() and
+ sljit_emit_atomic_store() operations. */
+
+/* Tests whether the atomic operation is available (does not generate
+ any instructions). When a load from is allowed, its corresponding
+ store form is allowed and vice versa. */
+#define SLJIT_ATOMIC_TEST 0x10000
+/* The compiler must generate compare and swap instruction.
+ When this bit is set, calling sljit_emit_atomic_load() is optional. */
+#define SLJIT_ATOMIC_USE_CAS 0x20000
+/* The compiler must generate load-acquire and store-release instructions.
+ When this bit is set, the temp_reg for sljit_emit_atomic_store is not used. */
+#define SLJIT_ATOMIC_USE_LS 0x40000
+
+/* The sljit_emit_atomic_load and sljit_emit_atomic_store operation pair
+ can perform an atomic read-modify-write operation. First, an unsigned
+ value must be loaded from memory using sljit_emit_atomic_load. Then,
+ the updated value must be written back to the same memory location by
+ sljit_emit_atomic_store. A thread can only perform a single atomic
+ operation at a time.
+
+ The following conditions must be satisfied, or the operation
+ is undefined:
+ - the address provided in mem_reg must be divisible by the size of
+ the value (only naturally aligned updates are supported)
+ - no memory operations are allowed between the load and store operations
+ - the memory operation (op) and the base address (stored in mem_reg)
+ passed to the load/store operations must be the same (the mem_reg
+ can be a different register, only its value must be the same)
+ - a store must always follow a load for the same transaction.
+
+ op must be between SLJIT_MOV and SLJIT_MOV_P
+ dst_reg is the register where the data will be loaded into
+ mem_reg is the base address of the memory load (it cannot be
+ SLJIT_SP or a virtual register on x86-32)
+
+ Flags: - (does not modify flags) */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 mem_reg);
+
+/* The sljit_emit_atomic_load and sljit_emit_atomic_store operations
+ allows performing an atomic read-modify-write operation. See the
+ description of sljit_emit_atomic_load.
+
+ op must be between SLJIT_MOV and SLJIT_MOV_P
+ src_reg is the register which value is stored into the memory
+ mem_reg is the base address of the memory store (it cannot be
+ SLJIT_SP or a virtual register on x86-32)
+ temp_reg is a scratch register, which must be initialized with
+ the value loaded into the dst_reg during the corresponding
+ sljit_emit_atomic_load operation, or the operation is undefined.
+ The temp_reg register preserves its value, if the memory store
+ is successful. Otherwise, its value is undefined.
+
+ Flags: ATOMIC_STORED
+ if ATOMIC_STORED flag is set, it represents that the memory
+ is updated with a new value. Otherwise the memory is unchanged. */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src_reg,
+ sljit_s32 mem_reg,
+ sljit_s32 temp_reg);
+
+/* Copies the base address of SLJIT_SP + offset to dst. The offset can
+ represent the starting address of a value in the local data (stack).
+ The offset is not limited by the local data limits, it can be any value.
+ For example if an array of bytes are stored on the stack from
+ offset 0x40, and R0 contains the offset of an array item plus 0x120,
+ this item can be changed by two SLJIT instructions:
+
+ sljit_get_local_base(compiler, SLJIT_R1, 0, 0x40 - 0x120);
+ sljit_emit_op1(compiler, SLJIT_MOV_U8, SLJIT_MEM2(SLJIT_R1, SLJIT_R0), 0, SLJIT_IMM, 0x5);
+
+ Flags: - (may destroy flags) */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset);
+
+/* Store a value that can be changed at runtime. The constant
+ can be managed by sljit_get_const_addr and sljit_set_const.
+
+ op must be SLJIT_MOV, SLJIT_MOV32, SLJIT_MOV_S32,
+ SLJIT_MOV_U8, SLJIT_MOV32_U8
+
+ Note: when SLJIT_MOV_U8 is used, and dst is a register,
+ init_value supports a 9 bit signed value between [-256..255]
+
+ Flags: - (does not modify flags) */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value);
+
+/* Opcodes for sljit_emit_mov_addr. */
+
+/* The address is suitable for jump/call target. */
+#define SLJIT_MOV_ADDR 0
+/* The address is suitable for reading memory. */
+#define SLJIT_MOV_ABS_ADDR 1
+/* Add absolute address. */
+#define SLJIT_ADD_ABS_ADDR 2
+
+/* Store the value of a label (see: sljit_set_label / sljit_set_target)
+ Flags: - (does not modify flags) */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw);
+
+/* Returns the address of a label after sljit_generate_code is called, and
+ before the compiler is freed by sljit_free_compiler. It is recommended
+ to save these addresses elsewhere before sljit_free_compiler is called.
+
+ The address returned by sljit_get_label_addr is suitable for a jump/call
+ target, and the address returned by sljit_get_label_abs_addr is suitable
+ for reading memory. */
+
+static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { return label->u.addr; }
+#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
+static SLJIT_INLINE sljit_uw sljit_get_label_abs_addr(struct sljit_label *label) { return label->u.addr & ~(sljit_uw)1; }
+#else /* !SLJIT_CONFIG_ARM_THUMB2 */
+static SLJIT_INLINE sljit_uw sljit_get_label_abs_addr(struct sljit_label *label) { return label->u.addr; }
+#endif /* SLJIT_CONFIG_ARM_THUMB2 */
+
+/* Returns the address of jump and const instructions after sljit_generate_code
+ is called, and before the compiler is freed by sljit_free_compiler. It is
+ recommended to save these addresses elsewhere before sljit_free_compiler is called. */
+
+static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; }
+static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) { return const_->addr; }
+
+/* Only the address and executable offset are required to perform dynamic
+ code modifications. See sljit_get_executable_offset function. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset);
+/* The op opcode must be set to the same value that was passed to sljit_emit_const. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset);
+
+/* Only a single buffer is writable at a time, so sljit_read_only_buffer_end_writing()
+ must be called before sljit_read_only_buffer_start_writing() is called again. */
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_read_only_buffer_start_writing(sljit_uw addr, sljit_uw size, sljit_sw executable_offset);
+SLJIT_API_FUNC_ATTRIBUTE void sljit_read_only_buffer_end_writing(sljit_uw addr, sljit_uw size, sljit_sw executable_offset);
+
+/* --------------------------------------------------------------------- */
+/* CPU specific functions */
+/* --------------------------------------------------------------------- */
+
+/* Types for sljit_get_register_index */
+
+/* General purpose (integer) registers. */
+#define SLJIT_GP_REGISTER 0
+/* Floating point registers. */
+#define SLJIT_FLOAT_REGISTER 1
+
+/* The following function is a helper function for sljit_emit_op_custom.
+ It returns with the real machine register index ( >=0 ) of any registers.
+
+ When type is SLJIT_GP_REGISTER:
+ reg must be an SLJIT_R(i), SLJIT_S(i), or SLJIT_SP register
+
+ When type is SLJIT_FLOAT_REGISTER:
+ reg must be an SLJIT_FR(i) or SLJIT_FS(i) register
+
+ When type is SLJIT_SIMD_REG_64 / 128 / 256 / 512 :
+ reg must be an SLJIT_FR(i) or SLJIT_FS(i) register
+
+ Note: it returns with -1 for unknown registers, such as virtual
+ registers on x86-32 or unsupported simd registers. */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg);
+
+/* Any instruction can be inserted into the instruction stream by
+ sljit_emit_op_custom. It has a similar purpose as inline assembly.
+ The size parameter must match to the instruction size of the target
+ architecture:
+
+ x86: 0 < size <= 15, the instruction argument can be byte aligned.
+ Thumb2: if size == 2, the instruction argument must be 2 byte aligned.
+ if size == 4, the instruction argument must be 4 byte aligned.
+ s390x: size can be 2, 4, or 6, the instruction argument can be byte aligned.
+ Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_u32 size);
+
+/* Flags were set by a 32 bit operation. */
+#define SLJIT_CURRENT_FLAGS_32 SLJIT_32
+
+/* Flags were set by an ADD or ADDC operations. */
+#define SLJIT_CURRENT_FLAGS_ADD 0x01
+/* Flags were set by a SUB or SUBC operation. */
+#define SLJIT_CURRENT_FLAGS_SUB 0x02
+
+/* Flags were set by sljit_emit_op2u with SLJIT_SUB opcode.
+ Must be combined with SLJIT_CURRENT_FLAGS_SUB. */
+#define SLJIT_CURRENT_FLAGS_COMPARE 0x04
+
+/* Flags were set by sljit_emit_op2cmpz operation. */
+#define SLJIT_CURRENT_FLAGS_OP2CMPZ 0x08
+
+/* Define the currently available CPU status flags. It is usually used after
+ an sljit_emit_label or sljit_emit_op_custom operations to define which CPU
+ status flags are available.
+
+ The current_flags must be a valid combination of SLJIT_SET_* and
+ SLJIT_CURRENT_FLAGS_* constants. */
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler,
+ sljit_s32 current_flags);
+
+/* --------------------------------------------------------------------- */
+/* Serialization functions */
+/* --------------------------------------------------------------------- */
+
+/* Label/jump/const enumeration functions. The items in each group
+ are enumerated in creation order. Serialization / deserialization
+ preserves this order for each group. For example the fifth label
+ after deserialization refers to the same machine code location as
+ the fifth label before the serialization. */
+static SLJIT_INLINE struct sljit_label *sljit_get_first_label(struct sljit_compiler *compiler) { return compiler->labels; }
+static SLJIT_INLINE struct sljit_jump *sljit_get_first_jump(struct sljit_compiler *compiler) { return compiler->jumps; }
+static SLJIT_INLINE struct sljit_const *sljit_get_first_const(struct sljit_compiler *compiler) { return compiler->consts; }
+
+static SLJIT_INLINE struct sljit_label *sljit_get_next_label(struct sljit_label *label) { return label->next; }
+static SLJIT_INLINE struct sljit_jump *sljit_get_next_jump(struct sljit_jump *jump) { return jump->next; }
+static SLJIT_INLINE struct sljit_const *sljit_get_next_const(struct sljit_const *const_) { return const_->next; }
+
+/* A number starting from 0 is assigned to each label, which
+represents its creation index. The first label created by the
+compiler has index 0, the second one has index 1, the third one
+has index 2, and so on. The returned value is unspecified after
+sljit_generate_code() is called.
+
+It is recommended to use this function to get the creation index
+of a label, since sljit_emit_label() may return with the last label,
+if no code is generated since the last sljit_emit_label() call. */
+SLJIT_API_FUNC_ATTRIBUTE sljit_uw sljit_get_label_index(struct sljit_label *label);
+
+/* The sljit_jump_has_label() and sljit_jump_has_target() functions
+returns non-zero value if a label or target is set for the jump
+respectively. Both may return with a zero value. The other two
+functions return the value assigned to the jump. */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_label(struct sljit_jump *jump);
+static SLJIT_INLINE struct sljit_label *sljit_jump_get_label(struct sljit_jump *jump) { return jump->u.label; }
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_target(struct sljit_jump *jump);
+static SLJIT_INLINE sljit_uw sljit_jump_get_target(struct sljit_jump *jump) { return jump->u.target; }
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_is_mov_addr(struct sljit_jump *jump);
+
+/* Option bits for sljit_serialize_compiler. */
+
+/* When debugging is enabled, the serialized buffer contains
+debugging information unless this option is specified. */
+#define SLJIT_SERIALIZE_IGNORE_DEBUG 0x1
+
+/* Serialize the internal structure of the compiler into a buffer.
+If the serialization is successful, the returned value is a newly
+allocated buffer which is allocated by the memory allocator assigned
+to the compiler. Otherwise the returned value is NULL. Unlike
+sljit_generate_code(), serialization does not modify the internal
+state of the compiler, so the code generation can be continued.
+
+ options must be the combination of SLJIT_SERIALIZE_* option bits
+ size is an output argument, which is set to the byte size of
+ the result buffer if the operation is successful
+
+Notes:
+ - This function is useful for ahead-of-time compilation (AOT).
+ - The returned buffer must be freed later by the caller.
+ The SLJIT_FREE() macro is suitable for this purpose:
+ SLJIT_FREE(returned_buffer, sljit_get_allocator_data(compiler))
+ - Memory allocated by sljit_alloc_memory() is not serialized.
+ - The type of the returned buffer is sljit_uw* to emphasize that
+ the buffer is word aligned. However, the 'size' output argument
+ contains the byte size, so this value is always divisible by
+ sizeof(sljit_uw).
+*/
+SLJIT_API_FUNC_ATTRIBUTE sljit_uw* sljit_serialize_compiler(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_uw *size);
+
+/* Construct a new compiler instance from a buffer produced by
+sljit_serialize_compiler(). If the operation is successful, the new
+compiler instance is returned. Otherwise the returned value is NULL.
+
+ buffer points to a word aligned memory data which was
+ created by sljit_serialize_compiler()
+ size is the byte size of the buffer
+ options must be 0
+ allocator_data specify an allocator specific data, see
+ sljit_create_compiler() for further details
+
+Notes:
+ - Labels assigned to jumps are restored with their
+ corresponding label in the label set created by
+ the deserializer. Target addresses assigned to
+ jumps are also restored. Uninitialized jumps
+ remain uninitialized.
+ - After the deserialization, sljit_generate_code() does
+ not need to be the next operation on the returned
+ compiler, the code generation can be continued.
+ Even sljit_serialize_compiler() can be called again.
+ - When debugging is enabled, a buffers without debug
+ information cannot be deserialized.
+*/
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler *sljit_deserialize_compiler(sljit_uw* buffer, sljit_uw size,
+ sljit_s32 options, void *allocator_data);
+
+/* --------------------------------------------------------------------- */
+/* Miscellaneous utility functions */
+/* --------------------------------------------------------------------- */
+
+/* Get the human readable name of the platform. Can be useful on platforms
+ like ARM, where ARM and Thumb2 functions can be mixed, and it is useful
+ to know the type of the code generator. */
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void);
+
+/* Portable helper function to get an offset of a member.
+ Same as offsetof() macro defined in stddef.h */
+#define SLJIT_OFFSETOF(base, member) ((sljit_sw)(&((base*)0x10)->member) - 0x10)
+
+#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
+
+/* The sljit_stack structure and its manipulation functions provides
+ an implementation for a top-down stack. The stack top is stored
+ in the end field of the sljit_stack structure and the stack goes
+ down to the min_start field, so the memory region reserved for
+ this stack is between min_start (inclusive) and end (exclusive)
+ fields. However the application can only use the region between
+ start (inclusive) and end (exclusive) fields. The sljit_stack_resize
+ function can be used to extend this region up to min_start.
+
+ This feature uses the "address space reserve" feature of modern
+ operating systems. Instead of allocating a large memory block
+ applications can allocate a small memory region and extend it
+ later without moving the content of the memory area. Therefore
+ after a successful resize by sljit_stack_resize all pointers into
+ this region are still valid.
+
+ Note:
+ this structure may not be supported by all operating systems.
+ end and max_limit fields are aligned to PAGE_SIZE bytes (usually
+ 4 Kbyte or more).
+ stack should grow in larger steps, e.g. 4Kbyte, 16Kbyte or more. */
+
+struct sljit_stack {
+ /* User data, anything can be stored here.
+ Initialized to the same value as the end field. */
+ sljit_u8 *top;
+/* These members are read only. */
+ /* End address of the stack */
+ sljit_u8 *end;
+ /* Current start address of the stack. */
+ sljit_u8 *start;
+ /* Lowest start address of the stack. */
+ sljit_u8 *min_start;
+};
+
+/* Allocates a new stack. Returns NULL if unsuccessful.
+ Note: see sljit_create_compiler for the explanation of allocator_data. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data);
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data);
+
+/* Can be used to increase (extend) or decrease (shrink) the stack
+ memory area. Returns with new_start if successful and NULL otherwise.
+ It always fails if new_start is less than min_start or greater or equal
+ than end fields. The fields of the stack are not changed if the returned
+ value is NULL (the current memory content is never lost). */
+SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start);
+
+#endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */
+
+#if !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+
+/* Get the entry address of a given function (signed, unsigned result). */
+#define SLJIT_FUNC_ADDR(func_name) ((sljit_sw)func_name)
+#define SLJIT_FUNC_UADDR(func_name) ((sljit_uw)func_name)
+
+#else /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */
+
+/* All JIT related code should be placed in the same context (library, binary, etc.). */
+
+/* Get the entry address of a given function (signed, unsigned result). */
+#define SLJIT_FUNC_ADDR(func_name) (*(sljit_sw*)(sljit_uw)func_name)
+#define SLJIT_FUNC_UADDR(func_name) (*(sljit_uw*)(sljit_uw)func_name)
+
+/* For powerpc64, the function pointers point to a context descriptor. */
+struct sljit_function_context {
+ sljit_uw addr;
+ sljit_uw r2;
+ sljit_uw r11;
+};
+
+/* Fill the context arguments using the addr and the function.
+ If func_ptr is NULL, it will not be set to the address of context
+ If addr is NULL, the function address also comes from the func pointer. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_uw addr, void (*func)(void));
+
+#endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */
+
+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
+/* Free unused executable memory. The allocator keeps some free memory
+ around to reduce the number of OS executable memory allocations.
+ This improves performance since these calls are costly. However
+ it is sometimes desired to free all unused memory regions, e.g.
+ before the application terminates. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
+#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* SLJIT_LIR_H_ */
diff --git a/deps/sljit/sljit_src/sljitNativeARM_32.c b/deps/sljit/sljit_src/sljitNativeARM_32.c
new file mode 100644
index 0000000..ef2762f
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativeARM_32.c
@@ -0,0 +1,4950 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef __SOFTFP__
+#define ARM_ABI_INFO " ABI:softfp"
+#else
+#define ARM_ABI_INFO " ABI:hardfp"
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
+{
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+ return "ARMv7" SLJIT_CPUINFO ARM_ABI_INFO;
+#elif (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ return "ARMv6" SLJIT_CPUINFO ARM_ABI_INFO;
+#else
+#error "Internal error: Unknown ARM architecture"
+#endif
+}
+
+/* Length of an instruction word. */
+typedef sljit_u32 sljit_ins;
+
+/* Last register + 1. */
+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
+#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 4)
+
+#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
+
+/* In ARM instruction words.
+ Cache lines are usually 32 byte aligned. */
+#define CONST_POOL_ALIGNMENT 8
+#define CONST_POOL_EMPTY 0xffffffff
+
+#define ALIGN_INSTRUCTION(ptr) \
+ (sljit_ins*)(((sljit_ins)(ptr) + (CONST_POOL_ALIGNMENT * sizeof(sljit_ins)) - 1) & ~((CONST_POOL_ALIGNMENT * sizeof(sljit_ins)) - 1))
+#define MAX_DIFFERENCE(max_diff) \
+ (((max_diff) / (sljit_s32)sizeof(sljit_ins)) - (CONST_POOL_ALIGNMENT - 1))
+
+/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
+ 0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15
+};
+
+static const sljit_u8 freg_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) + 1] = {
+ 0,
+ 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6,
+ 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6
+};
+
+static const sljit_u8 freg_ebit_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) + 1] = {
+ 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1
+};
+
+#define RM(rm) ((sljit_ins)reg_map[rm])
+#define RM8(rm) ((sljit_ins)reg_map[rm] << 8)
+#define RD(rd) ((sljit_ins)reg_map[rd] << 12)
+#define RN(rn) ((sljit_ins)reg_map[rn] << 16)
+
+#define VM(vm) (((sljit_ins)freg_map[vm]) | ((sljit_ins)freg_ebit_map[vm] << 5))
+#define VD(vd) (((sljit_ins)freg_map[vd] << 12) | ((sljit_ins)freg_ebit_map[vd] << 22))
+#define VN(vn) (((sljit_ins)freg_map[vn] << 16) | ((sljit_ins)freg_ebit_map[vn] << 7))
+
+/* --------------------------------------------------------------------- */
+/* Instruction forms */
+/* --------------------------------------------------------------------- */
+
+/* The instruction includes the AL condition.
+ INST_NAME - CONDITIONAL remove this flag. */
+#define COND_MASK 0xf0000000
+#define CONDITIONAL 0xe0000000
+#define PUSH_POOL 0xff000000
+
+#define ADC 0xe0a00000
+#define ADD 0xe0800000
+#define AND 0xe0000000
+#define B 0xea000000
+#define BIC 0xe1c00000
+#define BKPT 0xe1200070
+#define BL 0xeb000000
+#define BLX 0xe12fff30
+#define BX 0xe12fff10
+#define CLZ 0xe16f0f10
+#define CMN 0xe1600000
+#define CMP 0xe1400000
+#define DMB_SY 0xf57ff05f
+#define EOR 0xe0200000
+#define LDR 0xe5100000
+#define LDR_POST 0xe4100000
+#define LDREX 0xe1900f9f
+#define LDREXB 0xe1d00f9f
+#define LDREXH 0xe1f00f9f
+#define MLA 0xe0200090
+#define MOV 0xe1a00000
+#define MUL 0xe0000090
+#define MVN 0xe1e00000
+#define NOP 0xe1a00000
+#define ORR 0xe1800000
+#define PUSH 0xe92d0000
+#define POP 0xe8bd0000
+#define REV 0xe6bf0f30
+#define REV16 0xe6bf0fb0
+#define RSB 0xe0600000
+#define RSC 0xe0e00000
+#define SBC 0xe0c00000
+#define SMULL 0xe0c00090
+#define STR 0xe5000000
+#define STREX 0xe1800f90
+#define STREXB 0xe1c00f90
+#define STREXH 0xe1e00f90
+#define SUB 0xe0400000
+#define SXTB 0xe6af0070
+#define SXTH 0xe6bf0070
+#define TST 0xe1000000
+#define UMULL 0xe0800090
+#define UXTB 0xe6ef0070
+#define UXTH 0xe6ff0070
+#define VABS_F32 0xeeb00ac0
+#define VADD_F32 0xee300a00
+#define VAND 0xf2000110
+#define VCMP_F32 0xeeb40a40
+#define VCVT_F32_S32 0xeeb80ac0
+#define VCVT_F32_U32 0xeeb80a40
+#define VCVT_F64_F32 0xeeb70ac0
+#define VCVT_S32_F32 0xeebd0ac0
+#define VDIV_F32 0xee800a00
+#define VDUP 0xee800b10
+#define VDUP_s 0xf3b00c00
+#define VEOR 0xf3000110
+#define VLD1 0xf4200000
+#define VLD1_r 0xf4a00c00
+#define VLD1_s 0xf4a00000
+#define VLDR_F32 0xed100a00
+#define VMOV_F32 0xeeb00a40
+#define VMOV 0xee000a10
+#define VMOV2 0xec400a10
+#define VMOV_i 0xf2800010
+#define VMOV_s 0xee000b10
+#define VMOVN 0xf3b20200
+#define VMRS 0xeef1fa10
+#define VMUL_F32 0xee200a00
+#define VNEG_F32 0xeeb10a40
+#define VORR 0xf2200110
+#define VPOP 0xecbd0b00
+#define VPUSH 0xed2d0b00
+#define VSHLL 0xf2800a10
+#define VSHR 0xf2800010
+#define VSRA 0xf2800110
+#define VST1 0xf4000000
+#define VST1_s 0xf4800000
+#define VSTR_F32 0xed000a00
+#define VSUB_F32 0xee300a40
+#define VTBL 0xf3b00800
+
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+/* Arm v7 specific instructions. */
+#define MOVT 0xe3400000
+#define MOVW 0xe3000000
+#define RBIT 0xe6ff0f30
+#endif
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+
+static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32)
+{
+ if (compiler->scratches == -1)
+ return 0;
+
+ if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0))
+ fr -= SLJIT_F64_SECOND(0);
+
+ return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->real_fscratches))
+ || (fr > (SLJIT_FS0 - compiler->real_fsaveds) && fr <= SLJIT_FS0)
+ || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));
+}
+
+static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type)
+{
+ sljit_s32 vr_low = vr;
+
+ if (compiler->scratches == -1)
+ return 0;
+
+ if (SLJIT_SIMD_GET_REG_SIZE(type) == 4) {
+ vr += (vr & 0x1);
+ vr_low = vr - 1;
+ }
+
+ return (vr >= SLJIT_VR0 && vr < (SLJIT_VR0 + compiler->vscratches))
+ || (vr_low > (SLJIT_VS0 - compiler->vsaveds) && vr_low <= SLJIT_VS0)
+ || (vr >= SLJIT_TMP_VREGISTER_BASE && vr < (SLJIT_TMP_VREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS));
+}
+
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+
+static sljit_s32 push_cpool(struct sljit_compiler *compiler)
+{
+ /* Pushing the constant pool into the instruction stream. */
+ sljit_ins* inst;
+ sljit_uw* cpool_ptr;
+ sljit_uw* cpool_end;
+ sljit_s32 i;
+
+ /* The label could point the address after the constant pool. */
+ if (compiler->last_label && compiler->last_label->size == compiler->size)
+ compiler->last_label->size += compiler->cpool_fill + (CONST_POOL_ALIGNMENT - 1) + 1;
+
+ SLJIT_ASSERT(compiler->cpool_fill > 0 && compiler->cpool_fill <= CPOOL_SIZE);
+ inst = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!inst);
+ compiler->size++;
+ *inst = 0xff000000 | compiler->cpool_fill;
+
+ for (i = 0; i < CONST_POOL_ALIGNMENT - 1; i++) {
+ inst = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!inst);
+ compiler->size++;
+ *inst = 0;
+ }
+
+ cpool_ptr = compiler->cpool;
+ cpool_end = cpool_ptr + compiler->cpool_fill;
+ while (cpool_ptr < cpool_end) {
+ inst = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!inst);
+ compiler->size++;
+ *inst = *cpool_ptr++;
+ }
+ compiler->cpool_diff = CONST_POOL_EMPTY;
+ compiler->cpool_fill = 0;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins inst)
+{
+ sljit_ins* ptr;
+
+ if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))
+ FAIL_IF(push_cpool(compiler));
+
+ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ compiler->size++;
+ *ptr = inst;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 push_inst_with_literal(struct sljit_compiler *compiler, sljit_ins inst, sljit_uw literal)
+{
+ sljit_ins* ptr;
+ sljit_uw cpool_index = CPOOL_SIZE;
+ sljit_uw* cpool_ptr;
+ sljit_uw* cpool_end;
+ sljit_u8* cpool_unique_ptr;
+
+ if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)))
+ FAIL_IF(push_cpool(compiler));
+ else if (compiler->cpool_fill > 0) {
+ cpool_ptr = compiler->cpool;
+ cpool_end = cpool_ptr + compiler->cpool_fill;
+ cpool_unique_ptr = compiler->cpool_unique;
+ do {
+ if ((*cpool_ptr == literal) && !(*cpool_unique_ptr)) {
+ cpool_index = (sljit_uw)(cpool_ptr - compiler->cpool);
+ break;
+ }
+ cpool_ptr++;
+ cpool_unique_ptr++;
+ } while (cpool_ptr < cpool_end);
+ }
+
+ if (cpool_index == CPOOL_SIZE) {
+ /* Must allocate a new entry in the literal pool. */
+ if (compiler->cpool_fill < CPOOL_SIZE) {
+ cpool_index = compiler->cpool_fill;
+ compiler->cpool_fill++;
+ }
+ else {
+ FAIL_IF(push_cpool(compiler));
+ cpool_index = 0;
+ compiler->cpool_fill = 1;
+ }
+ }
+
+ SLJIT_ASSERT((inst & 0xfff) == 0);
+ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ compiler->size++;
+ *ptr = inst | cpool_index;
+
+ compiler->cpool[cpool_index] = literal;
+ compiler->cpool_unique[cpool_index] = 0;
+ if (compiler->cpool_diff == CONST_POOL_EMPTY)
+ compiler->cpool_diff = compiler->size;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 push_inst_with_unique_literal(struct sljit_compiler *compiler, sljit_ins inst, sljit_uw literal)
+{
+ sljit_ins* ptr;
+
+ if (SLJIT_UNLIKELY((compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4092)) || compiler->cpool_fill >= CPOOL_SIZE))
+ FAIL_IF(push_cpool(compiler));
+
+ SLJIT_ASSERT(compiler->cpool_fill < CPOOL_SIZE && (inst & 0xfff) == 0);
+ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ compiler->size++;
+ *ptr = inst | compiler->cpool_fill;
+
+ compiler->cpool[compiler->cpool_fill] = literal;
+ compiler->cpool_unique[compiler->cpool_fill] = 1;
+ compiler->cpool_fill++;
+ if (compiler->cpool_diff == CONST_POOL_EMPTY)
+ compiler->cpool_diff = compiler->size;
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 prepare_blx(struct sljit_compiler *compiler)
+{
+ /* Place for at least two instruction (doesn't matter whether the first has a literal). */
+ if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY && compiler->size - compiler->cpool_diff >= MAX_DIFFERENCE(4088)))
+ return push_cpool(compiler);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 emit_blx(struct sljit_compiler *compiler)
+{
+ /* Must follow tightly the previous instruction (to be able to convert it to bl instruction). */
+ SLJIT_ASSERT(compiler->cpool_diff == CONST_POOL_EMPTY || compiler->size - compiler->cpool_diff < MAX_DIFFERENCE(4092));
+ SLJIT_ASSERT(reg_map[TMP_REG1] != 14);
+
+ return push_inst(compiler, BLX | RM(TMP_REG1));
+}
+
+static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_ptr, sljit_uw* const_pool, sljit_uw cpool_size)
+{
+ sljit_uw diff;
+ sljit_uw ind;
+ sljit_uw counter = 0;
+ sljit_uw* clear_const_pool = const_pool;
+ sljit_uw* clear_const_pool_end = const_pool + cpool_size;
+
+ SLJIT_ASSERT(const_pool - code_ptr <= CONST_POOL_ALIGNMENT);
+ /* Set unused flag for all literals in the constant pool.
+ I.e.: unused literals can belong to branches, which can be encoded as B or BL.
+ We can "compress" the constant pool by discarding these literals. */
+ while (clear_const_pool < clear_const_pool_end)
+ *clear_const_pool++ = (sljit_uw)(-1);
+
+ while (last_pc_patch < code_ptr) {
+ /* Data transfer instruction with Rn == r15. */
+ if ((*last_pc_patch & 0x0e4f0000) == 0x040f0000) {
+ diff = (sljit_uw)(const_pool - last_pc_patch);
+ ind = (*last_pc_patch) & 0xfff;
+
+ /* Must be a load instruction with immediate offset. */
+ SLJIT_ASSERT(ind < cpool_size && !(*last_pc_patch & (1 << 25)) && (*last_pc_patch & (1 << 20)));
+ if ((sljit_s32)const_pool[ind] < 0) {
+ const_pool[ind] = counter;
+ ind = counter;
+ counter++;
+ }
+ else
+ ind = const_pool[ind];
+
+ SLJIT_ASSERT(diff >= 1);
+ if (diff >= 2 || ind > 0) {
+ diff = (diff + (sljit_uw)ind - 2) << 2;
+ SLJIT_ASSERT(diff <= 0xfff);
+ *last_pc_patch = (*last_pc_patch & ~(sljit_uw)0xfff) | diff;
+ }
+ else
+ *last_pc_patch = (*last_pc_patch & ~(sljit_uw)(0xfff | (1 << 23))) | 0x004;
+ }
+ last_pc_patch++;
+ }
+ return counter;
+}
+
+/* In some rare ocasions we may need future patches. The probability is close to 0 in practice. */
+struct future_patch {
+ struct future_patch* next;
+ sljit_s32 index;
+ sljit_s32 value;
+};
+
+static sljit_s32 resolve_const_pool_index(struct sljit_compiler *compiler, struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr)
+{
+ sljit_u32 value;
+ struct future_patch *curr_patch, *prev_patch;
+
+ SLJIT_UNUSED_ARG(compiler);
+
+ /* Using the values generated by patch_pc_relative_loads. */
+ if (!*first_patch)
+ value = cpool_start_address[cpool_current_index];
+ else {
+ curr_patch = *first_patch;
+ prev_patch = NULL;
+ while (1) {
+ if (!curr_patch) {
+ value = cpool_start_address[cpool_current_index];
+ break;
+ }
+ if ((sljit_uw)curr_patch->index == cpool_current_index) {
+ value = (sljit_uw)curr_patch->value;
+ if (prev_patch)
+ prev_patch->next = curr_patch->next;
+ else
+ *first_patch = curr_patch->next;
+ SLJIT_FREE(curr_patch, compiler->allocator_data);
+ break;
+ }
+ prev_patch = curr_patch;
+ curr_patch = curr_patch->next;
+ }
+ }
+
+ if ((sljit_sw)value >= 0) {
+ if (value > cpool_current_index) {
+ curr_patch = (struct future_patch*)SLJIT_MALLOC(sizeof(struct future_patch), compiler->allocator_data);
+ if (!curr_patch) {
+ while (*first_patch) {
+ curr_patch = *first_patch;
+ *first_patch = (*first_patch)->next;
+ SLJIT_FREE(curr_patch, compiler->allocator_data);
+ }
+ return SLJIT_ERR_ALLOC_FAILED;
+ }
+ curr_patch->next = *first_patch;
+ curr_patch->index = (sljit_sw)value;
+ curr_patch->value = (sljit_sw)cpool_start_address[value];
+ *first_patch = curr_patch;
+ }
+ cpool_start_address[value] = *buf_ptr;
+ }
+ return SLJIT_SUCCESS;
+}
+
+#else
+
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins inst)
+{
+ sljit_ins* ptr;
+
+ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ compiler->size++;
+ *ptr = inst;
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 emit_imm(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
+{
+ FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | ((sljit_u32)imm & 0xfff)));
+ return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | (((sljit_u32)imm >> 16) & 0xfff));
+}
+
+#endif
+
+static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_uw *code_ptr, sljit_uw *code, sljit_sw executable_offset)
+{
+ sljit_sw diff;
+ sljit_uw target_addr;
+ sljit_uw jump_addr = (sljit_uw)code_ptr;
+ sljit_uw orig_addr = jump->addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+ jump->addr = jump_addr;
+#endif
+
+ if (jump->flags & SLJIT_REWRITABLE_JUMP)
+ return 0;
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ if (jump->flags & IS_BL)
+ code_ptr--;
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+ if (jump->flags & JUMP_ADDR)
+ target_addr = jump->u.target;
+ else {
+ SLJIT_ASSERT(jump->u.label != NULL);
+ target_addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
+
+ if (jump->u.label->size > orig_addr)
+ jump_addr = (sljit_uw)(code + orig_addr);
+ }
+
+ diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr + 8, executable_offset);
+
+ /* Branch to Thumb code has not been optimized yet. */
+ if (diff & 0x3)
+ return 0;
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ if (jump->flags & IS_BL) {
+ if (diff <= 0x01ffffff && diff >= -0x02000000) {
+ *code_ptr = (BL - CONDITIONAL) | (*(code_ptr + 1) & COND_MASK);
+ jump->flags |= PATCH_B;
+ return 1;
+ }
+ } else if (diff <= 0x01ffffff && diff >= -0x02000000) {
+ *code_ptr = (B - CONDITIONAL) | (*code_ptr & COND_MASK);
+ jump->flags |= PATCH_B;
+ }
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ if (diff <= 0x01ffffff && diff >= -0x02000000) {
+ *code_ptr = ((jump->flags & IS_BL) ? (BL - CONDITIONAL) : (B - CONDITIONAL)) | (*code_ptr & COND_MASK);
+ jump->flags |= PATCH_B;
+ return 1;
+ }
+#endif /* SLJIT_CONFIG_ARM_V6 */
+ return 0;
+}
+
+static void set_jump_addr(sljit_uw jump_ptr, sljit_sw executable_offset, sljit_uw new_addr, sljit_s32 flush_cache)
+{
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ sljit_ins *ptr = (sljit_ins*)jump_ptr;
+ sljit_ins *inst = (sljit_ins*)ptr[0];
+ sljit_ins mov_pc = ptr[1];
+ sljit_s32 bl = (mov_pc & 0x0000f000) != RD(TMP_PC);
+ sljit_sw diff = (sljit_sw)(((sljit_sw)new_addr - (sljit_sw)(inst + 2) - executable_offset) >> 2);
+
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ if (diff <= 0x7fffff && diff >= -0x800000) {
+ /* Turn to branch. */
+ if (!bl) {
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
+ }
+ inst[0] = (mov_pc & COND_MASK) | (B - CONDITIONAL) | (diff & 0xffffff);
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
+ }
+ } else {
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ }
+ inst[0] = (mov_pc & COND_MASK) | (BL - CONDITIONAL) | (diff & 0xffffff);
+ inst[1] = NOP;
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ }
+ }
+ } else {
+ /* Get the position of the constant. */
+ if (mov_pc & (1 << 23))
+ ptr = inst + ((mov_pc & 0xfff) >> 2) + 2;
+ else
+ ptr = inst + 1;
+
+ if (*inst != mov_pc) {
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + (!bl ? 1 : 2), 0);
+ }
+ inst[0] = mov_pc;
+ if (!bl) {
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
+ }
+ } else {
+ inst[1] = BLX | RM(TMP_REG1);
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ }
+ }
+ }
+
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);
+ }
+
+ *ptr = new_addr;
+
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);
+ }
+ }
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ sljit_ins *inst = (sljit_ins*)jump_ptr;
+
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);
+
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ }
+
+ inst[0] = MOVW | (inst[0] & 0xf000) | ((new_addr << 4) & 0xf0000) | (new_addr & 0xfff);
+ inst[1] = MOVT | (inst[1] & 0xf000) | ((new_addr >> 12) & 0xf0000) | ((new_addr >> 16) & 0xfff);
+
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ }
+#endif /* SLJIT_CONFIG_ARM_V6 */
+}
+
+static sljit_uw get_imm(sljit_uw imm);
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm);
+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg);
+
+static void set_const_value(sljit_uw addr, sljit_sw executable_offset, sljit_uw new_constant, sljit_s32 flush_cache)
+{
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ sljit_ins *ptr = (sljit_ins*)addr;
+ sljit_ins *inst = (sljit_ins*)ptr[0];
+ sljit_uw ldr_literal = ptr[1];
+ sljit_uw src2;
+
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ src2 = get_imm(new_constant);
+ if (src2) {
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
+ }
+
+ *inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2;
+
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
+ }
+ return;
+ }
+
+ src2 = get_imm(~new_constant);
+ if (src2) {
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
+ }
+
+ *inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2;
+
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
+ }
+ return;
+ }
+
+ if (ldr_literal & (1 << 23))
+ ptr = inst + ((ldr_literal & 0xfff) >> 2) + 2;
+ else
+ ptr = inst + 1;
+
+ if (*inst != ldr_literal) {
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
+ }
+
+ *inst = ldr_literal;
+
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
+ }
+ }
+
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);
+ }
+
+ *ptr = new_constant;
+
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);
+ }
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ sljit_ins *inst = (sljit_ins*)addr;
+
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT);
+
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ }
+
+ inst[0] = MOVW | (inst[0] & 0xf000) | ((new_constant << 4) & 0xf0000) | (new_constant & 0xfff);
+ inst[1] = MOVT | (inst[1] & 0xf000) | ((new_constant >> 12) & 0xf0000) | ((new_constant >> 16) & 0xfff);
+
+ if (flush_cache) {
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ }
+#endif /* SLJIT_CONFIG_ARM_V6 */
+}
+
+static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
+{
+ sljit_uw addr;
+ sljit_uw jump_addr = (sljit_uw)code_ptr;
+ sljit_sw diff;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ if (jump->flags & JUMP_ADDR)
+ addr = jump->u.target;
+ else {
+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
+
+ if (jump->u.label->size > jump->addr)
+ jump_addr = (sljit_uw)(code + jump->addr);
+ }
+
+ /* The pc+8 offset is represented by the 2 * SSIZE_OF(ins) below. */
+ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);
+
+ if ((diff & 0x3) == 0 && diff <= (0x3fc + 2 * SSIZE_OF(ins)) && diff >= (-0x3fc + 2 * SSIZE_OF(ins))) {
+ jump->flags |= PATCH_B;
+ return 0;
+ }
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ return 0;
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ return 1;
+#endif /* SLJIT_CONFIG_ARM_V6 */
+}
+
+static SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+
+static void reduce_code_size(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+ SLJIT_NEXT_DEFINE_TYPES;
+ sljit_uw total_size;
+ sljit_uw size_reduce = 0;
+ sljit_sw diff;
+
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ SLJIT_NEXT_INIT_TYPES();
+
+ while (1) {
+ SLJIT_GET_NEXT_MIN();
+
+ if (next_min_addr == SLJIT_MAX_ADDRESS)
+ break;
+
+ if (next_min_addr == next_label_size) {
+ label->size -= size_reduce;
+
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ if (next_min_addr == next_const_addr) {
+ const_->addr -= size_reduce;
+ const_ = const_->next;
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+ continue;
+ }
+
+ if (next_min_addr != next_jump_addr)
+ continue;
+
+ jump->addr -= size_reduce;
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+ total_size = JUMP_MAX_SIZE - 1;
+
+ if (!(jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR))) {
+ /* Unit size: instruction. */
+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr - 2;
+ if (jump->u.label->size > jump->addr) {
+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);
+ diff -= (sljit_sw)size_reduce;
+ }
+
+ if (diff <= (0x01ffffff / SSIZE_OF(ins)) && diff >= (-0x02000000 / SSIZE_OF(ins)))
+ total_size = 1 - 1;
+ }
+
+ size_reduce += JUMP_MAX_SIZE - 1 - total_size;
+ } else {
+ /* Real size minus 1. Unit size: instruction. */
+ total_size = 1;
+
+ if (!(jump->flags & JUMP_ADDR)) {
+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
+ if (jump->u.label->size > jump->addr) {
+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);
+ diff -= (sljit_sw)size_reduce;
+ }
+
+ if (diff <= 0xff + 2 && diff >= -0xff + 2)
+ total_size = 0;
+ }
+
+ size_reduce += 1 - total_size;
+ }
+
+ jump->flags |= total_size << JUMP_SIZE_SHIFT;
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ }
+
+ compiler->size -= size_reduce;
+}
+
+#endif /* SLJIT_CONFIG_ARM_V7 */
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
+{
+ struct sljit_memory_fragment *buf;
+ sljit_ins *code;
+ sljit_ins *code_ptr;
+ sljit_ins *buf_ptr;
+ sljit_ins *buf_end;
+ sljit_uw word_count;
+ SLJIT_NEXT_DEFINE_TYPES;
+ sljit_sw executable_offset;
+ sljit_uw addr;
+ sljit_sw diff;
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ sljit_uw cpool_size;
+ sljit_uw cpool_skip_alignment;
+ sljit_uw cpool_current_index;
+ sljit_ins *cpool_start_address;
+ sljit_ins *last_pc_patch;
+ struct future_patch *first_patch;
+#endif
+
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
+
+ /* Second code generation pass. */
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ compiler->size += (compiler->patches << 1);
+ if (compiler->cpool_fill > 0)
+ compiler->size += compiler->cpool_fill + CONST_POOL_ALIGNMENT - 1;
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ reduce_code_size(compiler);
+#endif /* SLJIT_CONFIG_ARM_V6 */
+ code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
+ PTR_FAIL_WITH_EXEC_IF(code);
+
+ reverse_buf(compiler);
+ buf = compiler->buf;
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ cpool_size = 0;
+ cpool_skip_alignment = 0;
+ cpool_current_index = 0;
+ cpool_start_address = NULL;
+ first_patch = NULL;
+ last_pc_patch = code;
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+ code_ptr = code;
+ word_count = 0;
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ SLJIT_NEXT_INIT_TYPES();
+ SLJIT_GET_NEXT_MIN();
+
+ do {
+ buf_ptr = (sljit_ins*)buf->memory;
+ buf_end = buf_ptr + (buf->used_size >> 2);
+ do {
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ if (cpool_size > 0) {
+ if (cpool_skip_alignment > 0) {
+ buf_ptr++;
+ cpool_skip_alignment--;
+ } else {
+ if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {
+ SLJIT_FREE_EXEC(code, exec_allocator_data);
+ compiler->error = SLJIT_ERR_ALLOC_FAILED;
+ return NULL;
+ }
+ buf_ptr++;
+ if (++cpool_current_index >= cpool_size) {
+ SLJIT_ASSERT(!first_patch);
+ cpool_size = 0;
+ }
+ }
+ } else if ((*buf_ptr & 0xff000000) != PUSH_POOL) {
+#endif /* SLJIT_CONFIG_ARM_V6 */
+ *code_ptr = *buf_ptr++;
+ if (next_min_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+
+ if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+ *code_ptr = buf_ptr[-1];
+ }
+
+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ /* These structures are ordered by their address. */
+ if (next_min_addr == next_jump_addr) {
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ if (detect_jump_type(jump, code_ptr, code, executable_offset))
+ code_ptr--;
+ jump->addr = (sljit_uw)code_ptr;
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ word_count += jump->flags >> JUMP_SIZE_SHIFT;
+ if (!detect_jump_type(jump, code_ptr, code, executable_offset)) {
+ code_ptr[2] = code_ptr[0];
+ addr = ((code_ptr[0] & 0xf) << 12);
+ code_ptr[0] = MOVW | addr;
+ code_ptr[1] = MOVT | addr;
+ code_ptr += 2;
+ }
+ SLJIT_ASSERT((sljit_uw)code_ptr - jump->addr <= (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins));
+#endif /* SLJIT_CONFIG_ARM_V6 */
+ } else {
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+ word_count += jump->flags >> JUMP_SIZE_SHIFT;
+#endif /* SLJIT_CONFIG_ARM_V7 */
+ addr = (sljit_uw)code_ptr;
+ code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);
+ jump->addr = addr;
+ }
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ } else if (next_min_addr == next_const_addr) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+ }
+
+ SLJIT_GET_NEXT_MIN();
+ }
+ code_ptr++;
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ } else {
+ /* Fortunately, no need to shift. */
+ cpool_size = *buf_ptr++ & ~PUSH_POOL;
+ SLJIT_ASSERT(cpool_size > 0);
+ cpool_start_address = ALIGN_INSTRUCTION(code_ptr + 1);
+ cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, cpool_size);
+ if (cpool_current_index > 0) {
+ /* Unconditional branch. */
+ *code_ptr = B | (((sljit_ins)(cpool_start_address - code_ptr) + cpool_current_index - 2) & ~PUSH_POOL);
+ code_ptr = (sljit_ins*)(cpool_start_address + cpool_current_index);
+ }
+ cpool_skip_alignment = CONST_POOL_ALIGNMENT - 1;
+ cpool_current_index = 0;
+ last_pc_patch = code_ptr;
+ }
+#endif /* SLJIT_CONFIG_ARM_V6 */
+ word_count++;
+ } while (buf_ptr < buf_end);
+ buf = buf->next;
+ } while (buf);
+
+ if (label && label->size == word_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ }
+
+ SLJIT_ASSERT(!label);
+ SLJIT_ASSERT(!jump);
+ SLJIT_ASSERT(!const_);
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ SLJIT_ASSERT(cpool_size == 0);
+ if (compiler->cpool_fill > 0) {
+ cpool_start_address = ALIGN_INSTRUCTION(code_ptr);
+ cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, compiler->cpool_fill);
+ if (cpool_current_index > 0)
+ code_ptr = (sljit_ins*)(cpool_start_address + cpool_current_index);
+
+ buf_ptr = compiler->cpool;
+ buf_end = buf_ptr + compiler->cpool_fill;
+ cpool_current_index = 0;
+ while (buf_ptr < buf_end) {
+ if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) {
+ SLJIT_FREE_EXEC(code, exec_allocator_data);
+ compiler->error = SLJIT_ERR_ALLOC_FAILED;
+ return NULL;
+ }
+ buf_ptr++;
+ cpool_current_index++;
+ }
+ SLJIT_ASSERT(!first_patch);
+ }
+#endif
+
+ jump = compiler->jumps;
+ while (jump) {
+ addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
+ buf_ptr = (sljit_ins*)jump->addr;
+
+ if (jump->flags & JUMP_MOV_ADDR) {
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ SLJIT_ASSERT((buf_ptr[0] & (sljit_ins)0xffff0000) == 0xe59f0000);
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ SLJIT_ASSERT((buf_ptr[0] & ~(sljit_ins)0xf000) == 0);
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+ if (jump->flags & PATCH_B) {
+ SLJIT_ASSERT((((sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset)) & 0x3) == 0);
+ diff = ((sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset)) >> 2;
+
+ SLJIT_ASSERT(diff <= 0xff && diff >= -0xff);
+
+ addr = ADD;
+ if (diff < 0) {
+ diff = -diff;
+ addr = SUB;
+ }
+
+ buf_ptr[0] = addr | (buf_ptr[0] & 0xf000) | RN(TMP_PC) | (1 << 25) | (0xf << 8) | (sljit_ins)(diff & 0xff);
+ } else {
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ buf_ptr[((buf_ptr[0] & 0xfff) >> 2) + 2] = addr;
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ buf_ptr[1] = MOVT | buf_ptr[0] | ((addr >> 12) & 0xf0000) | ((addr >> 16) & 0xfff);
+ buf_ptr[0] = MOVW | buf_ptr[0] | ((addr << 4) & 0xf0000) | (addr & 0xfff);
+#endif /* SLJIT_CONFIG_ARM_V6 */
+ }
+ } else if (jump->flags & PATCH_B) {
+ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);
+ SLJIT_ASSERT(diff <= 0x01ffffff && diff >= -0x02000000);
+ *buf_ptr |= (diff >> 2) & 0x00ffffff;
+ } else {
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ if (jump->flags & IS_BL)
+ buf_ptr--;
+
+ if (jump->flags & SLJIT_REWRITABLE_JUMP) {
+ jump->addr = (sljit_uw)code_ptr;
+ code_ptr[0] = (sljit_ins)buf_ptr;
+ code_ptr[1] = *buf_ptr;
+ set_jump_addr((sljit_uw)code_ptr, executable_offset, addr, 0);
+ code_ptr += 2;
+ } else {
+ if (*buf_ptr & (1 << 23))
+ buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;
+ else
+ buf_ptr += 1;
+ *buf_ptr = addr;
+ }
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ set_jump_addr((sljit_uw)buf_ptr, executable_offset, addr, 0);
+#endif /* SLJIT_CONFIG_ARM_V6 */
+ }
+
+ jump = jump->next;
+ }
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ const_ = compiler->consts;
+ while (const_) {
+ buf_ptr = (sljit_ins*)const_->addr;
+
+ /* Note: MVN = (MOV ^ 0x400000) */
+ SLJIT_ASSERT((*buf_ptr & 0xfdb00000) == MOV || (*buf_ptr & 0xfd100000) == LDR);
+
+ if ((*buf_ptr & 0x4000000) != 0) {
+ const_->addr = (sljit_uw)code_ptr;
+
+ code_ptr[0] = (sljit_ins)buf_ptr;
+ code_ptr[1] = *buf_ptr;
+ if (*buf_ptr & (1 << 23))
+ buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;
+ else
+ buf_ptr += 1;
+ /* Set the value again (can be a simple constant). */
+ set_const_value((sljit_uw)code_ptr, executable_offset, *buf_ptr, 0);
+ code_ptr += 2;
+ }
+
+ const_ = const_->next;
+ }
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+ SLJIT_ASSERT(code_ptr - code <= (sljit_s32)compiler->size);
+
+ compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_uw);
+
+ code = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+ code_ptr = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
+ SLJIT_CACHE_FLUSH(code, code_ptr);
+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
+ return code;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type) {
+ case SLJIT_HAS_FPU:
+ case SLJIT_HAS_F64_AS_F32_PAIR:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return (SLJIT_IS_FPU_AVAILABLE) != 0;
+#else
+ /* Available by default. */
+ return 1;
+#endif /* SLJIT_IS_FPU_AVAILABLE */
+ case SLJIT_HAS_SIMD:
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ return 0;
+#else
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return (SLJIT_IS_FPU_AVAILABLE) != 0;
+#else
+ /* Available by default. */
+ return 1;
+#endif /* SLJIT_IS_FPU_AVAILABLE */
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+ case SLJIT_SIMD_REGS_ARE_PAIRS:
+ case SLJIT_HAS_CLZ:
+ case SLJIT_HAS_ROT:
+ case SLJIT_HAS_CMOV:
+ case SLJIT_HAS_REV:
+ case SLJIT_HAS_PREFETCH:
+ case SLJIT_HAS_COPY_F32:
+ case SLJIT_HAS_COPY_F64:
+ case SLJIT_HAS_ATOMIC:
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+ case SLJIT_HAS_MEMORY_BARRIER:
+#endif /* SLJIT_CONFIG_ARM_V7 */
+ return 1;
+
+ case SLJIT_HAS_CTZ:
+#if defined(SLJIT_CONFIG_ARM_V6) && SLJIT_CONFIG_ARM_V6
+ return 2;
+#else
+ return 1;
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+ default:
+ return 0;
+ }
+}
+
+/* --------------------------------------------------------------------- */
+/* Entry, exit */
+/* --------------------------------------------------------------------- */
+
+/* Creates an index in data_transfer_insts array. */
+#define WORD_SIZE 0x00
+#define BYTE_SIZE 0x01
+#define HALF_SIZE 0x02
+#define PRELOAD 0x03
+#define SIGNED 0x04
+#define LOAD_DATA 0x08
+
+/* Flag bits for emit_op. */
+#define ALLOW_IMM 0x10
+#define ALLOW_INV_IMM 0x20
+#define ALLOW_ANY_IMM (ALLOW_IMM | ALLOW_INV_IMM)
+#define ALLOW_NEG_IMM 0x40
+#define ALLOW_DOUBLE_IMM 0x80
+
+/* s/l - store/load (1 bit)
+ u/s - signed/unsigned (1 bit)
+ w/b/h/N - word/byte/half/NOT allowed (2 bit)
+ Storing signed and unsigned values are the same operations. */
+
+static const sljit_ins data_transfer_insts[16] = {
+/* s u w */ 0xe5000000 /* str */,
+/* s u b */ 0xe5400000 /* strb */,
+/* s u h */ 0xe10000b0 /* strh */,
+/* s u N */ 0x00000000 /* not allowed */,
+/* s s w */ 0xe5000000 /* str */,
+/* s s b */ 0xe5400000 /* strb */,
+/* s s h */ 0xe10000b0 /* strh */,
+/* s s N */ 0x00000000 /* not allowed */,
+
+/* l u w */ 0xe5100000 /* ldr */,
+/* l u b */ 0xe5500000 /* ldrb */,
+/* l u h */ 0xe11000b0 /* ldrh */,
+/* l u p */ 0xf5500000 /* preload */,
+/* l s w */ 0xe5100000 /* ldr */,
+/* l s b */ 0xe11000d0 /* ldrsb */,
+/* l s h */ 0xe11000f0 /* ldrsh */,
+/* l s N */ 0x00000000 /* not allowed */,
+};
+
+#define EMIT_DATA_TRANSFER(type, add, target_reg, base_reg, arg) \
+ (data_transfer_insts[(type) & 0xf] | ((add) << 23) | RD(target_reg) | RN(base_reg) | (sljit_ins)(arg))
+
+/* Normal ldr/str instruction.
+ Type2: ldrsb, ldrh, ldrsh */
+#define IS_TYPE1_TRANSFER(type) \
+ (data_transfer_insts[(type) & 0xf] & 0x04000000)
+#define TYPE2_TRANSFER_IMM(imm) \
+ (((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22))
+
+#define EMIT_FPU_OPERATION(opcode, mode, dst, src1, src2) \
+ ((sljit_ins)(opcode) | (sljit_ins)(mode) | VD(dst) | VM(src1) | VN(src2))
+
+/* Flags for emit_op: */
+ /* Arguments are swapped. */
+#define ARGS_SWAPPED 0x01
+ /* Inverted immediate. */
+#define INV_IMM 0x02
+ /* Source and destination is register. */
+#define REGISTER_OP 0x04
+ /* Unused return value. */
+#define UNUSED_RETURN 0x08
+/* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */
+#define SET_FLAGS (1 << 20)
+/* dst: reg
+ src1: reg
+ src2: reg or imm (if allowed)
+ SRC2_IMM must be (1 << 25) as it is also the value of I bit (can be used for optimization). */
+#define SRC2_IMM (1 << 25)
+
+static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w);
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches;
+ sljit_s32 fsaveds;
+ sljit_uw imm, offset;
+ sljit_s32 i, tmp, size, word_arg_count;
+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
+#ifdef __SOFTFP__
+ sljit_u32 float_arg_count;
+#else
+ sljit_u32 old_offset, f32_offset;
+ sljit_u32 remap[3];
+ sljit_u32 *remap_ptr = remap;
+#endif
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+
+ imm = 0;
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--)
+ imm |= (sljit_uw)1 << reg_map[i];
+
+ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
+ imm |= (sljit_uw)1 << reg_map[i];
+
+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
+
+ /* Push saved and temporary registers
+ multiple registers: stmdb sp!, {..., lr}
+ single register: str reg, [sp, #-4]! */
+ if (imm != 0)
+ FAIL_IF(push_inst(compiler, PUSH | (1 << 14) | imm));
+ else
+ FAIL_IF(push_inst(compiler, 0xe52d0004 | RD(TMP_REG2)));
+
+ /* Stack must be aligned to 8 bytes: */
+ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);
+
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if ((size & SSIZE_OF(sw)) != 0) {
+ FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | sizeof(sljit_sw)));
+ size += SSIZE_OF(sw);
+ }
+
+ if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {
+ FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_ins)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));
+ } else {
+ if (fsaveds > 0)
+ FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_ins)fsaveds << 1)));
+ if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)
+ FAIL_IF(push_inst(compiler, VPUSH | VD(fscratches) | ((sljit_ins)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));
+ }
+ }
+
+ local_size = ((size + local_size + 0x7) & ~0x7) - size;
+ compiler->local_size = local_size;
+
+ if (options & SLJIT_ENTER_REG_ARG)
+ arg_types = 0;
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ word_arg_count = 0;
+ saved_arg_count = 0;
+#ifdef __SOFTFP__
+ SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
+
+ offset = 0;
+ float_arg_count = 0;
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset & 0x7)
+ offset += sizeof(sljit_sw);
+
+ if (offset < 4 * sizeof(sljit_sw))
+ FAIL_IF(push_inst(compiler, VMOV2 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));
+ else
+ FAIL_IF(push_inst(compiler, VLDR_F32 | 0x800100 | RN(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset + (sljit_ins)size - 4 * sizeof(sljit_sw)) >> 2)));
+ float_arg_count++;
+ offset += sizeof(sljit_f64) - sizeof(sljit_sw);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (offset < 4 * sizeof(sljit_sw))
+ FAIL_IF(push_inst(compiler, VMOV | (float_arg_count << 16) | (offset << 10)));
+ else
+ FAIL_IF(push_inst(compiler, VLDR_F32 | 0x800000 | RN(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset + (sljit_ins)size - 4 * sizeof(sljit_sw)) >> 2)));
+ float_arg_count++;
+ break;
+ default:
+ word_arg_count++;
+
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ tmp = SLJIT_S0 - saved_arg_count;
+ saved_arg_count++;
+ } else if (word_arg_count - 1 != (sljit_s32)(offset >> 2))
+ tmp = word_arg_count;
+ else
+ break;
+
+ if (offset < 4 * sizeof(sljit_sw))
+ FAIL_IF(push_inst(compiler, MOV | RD(tmp) | (offset >> 2)));
+ else
+ FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_ins)size - 4 * sizeof(sljit_sw))));
+ break;
+ }
+
+ offset += sizeof(sljit_sw);
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ compiler->args_size = offset;
+#else
+ offset = SLJIT_FR0;
+ old_offset = SLJIT_FR0;
+ f32_offset = 0;
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset != old_offset)
+ *remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, SLJIT_32, offset, old_offset, 0);
+ old_offset++;
+ offset++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (f32_offset != 0) {
+ *remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, 0x20, offset, f32_offset, 0);
+ f32_offset = 0;
+ } else {
+ if (offset != old_offset)
+ *remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, 0, offset, old_offset, 0);
+ f32_offset = old_offset;
+ old_offset++;
+ }
+ offset++;
+ break;
+ default:
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S0 - saved_arg_count) | RM(SLJIT_R0 + word_arg_count)));
+ saved_arg_count++;
+ }
+
+ word_arg_count++;
+ break;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ SLJIT_ASSERT((sljit_uw)(remap_ptr - remap) <= sizeof(remap));
+
+ while (remap_ptr > remap)
+ FAIL_IF(push_inst(compiler, *(--remap_ptr)));
+#endif
+
+ if (local_size > 0)
+ FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM | ALLOW_DOUBLE_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size));
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches;
+ sljit_s32 fsaveds;
+ sljit_s32 size;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);
+
+ /* Doubles are saved, so alignment is unaffected. */
+ if ((size & SSIZE_OF(sw)) != 0 && (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG))
+ size += SSIZE_OF(sw);
+
+ compiler->local_size = ((size + local_size + 0x7) & ~0x7) - size;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm)
+{
+ sljit_uw imm2 = get_imm(imm);
+
+ if (imm2 == 0)
+ return emit_op(compiler, SLJIT_ADD, ALLOW_IMM | ALLOW_DOUBLE_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, (sljit_sw)imm);
+
+ return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | imm2);
+}
+
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size)
+{
+ sljit_s32 local_size, fscratches, fsaveds, i, tmp;
+ sljit_s32 restored_reg = 0;
+ sljit_s32 lr_dst = TMP_PC;
+ sljit_uw reg_list = 0;
+
+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14 && frame_size <= 128);
+
+ local_size = compiler->local_size;
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if (local_size > 0)
+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));
+
+ if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {
+ FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_ins)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));
+ } else {
+ if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)
+ FAIL_IF(push_inst(compiler, VPOP | VD(fscratches) | ((sljit_ins)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));
+ if (fsaveds > 0)
+ FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_ins)fsaveds << 1)));
+ }
+
+ local_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1) & 0x7;
+ }
+
+ if (frame_size < 0) {
+ lr_dst = TMP_REG2;
+ frame_size = 0;
+ } else if (frame_size > 0) {
+ SLJIT_ASSERT(frame_size == 1 || (frame_size & 0x7) == 0);
+ lr_dst = 0;
+ frame_size &= ~0x7;
+ }
+
+ if (lr_dst != 0)
+ reg_list |= (sljit_uw)1 << reg_map[lr_dst];
+
+ tmp = SLJIT_S0 - compiler->saveds;
+ i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options);
+ if (tmp < i) {
+ restored_reg = i;
+ do {
+ reg_list |= (sljit_uw)1 << reg_map[i];
+ } while (--i > tmp);
+ }
+
+ i = compiler->scratches;
+ if (i >= SLJIT_FIRST_SAVED_REG) {
+ restored_reg = i;
+ do {
+ reg_list |= (sljit_uw)1 << reg_map[i];
+ } while (--i >= SLJIT_FIRST_SAVED_REG);
+ }
+
+ if (lr_dst == TMP_REG2 && reg_list == 0) {
+ restored_reg = TMP_REG2;
+ lr_dst = 0;
+ }
+
+ if (lr_dst == 0 && (reg_list & (reg_list - 1)) == 0) {
+ /* The local_size does not include the saved registers. */
+ tmp = 0;
+ if (reg_list != 0) {
+ tmp = 2;
+ if (local_size <= 0xfff) {
+ if (local_size == 0) {
+ SLJIT_ASSERT(restored_reg != TMP_REG2);
+ if (frame_size == 0)
+ return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | 0x800008);
+ if (frame_size > 2 * SSIZE_OF(sw))
+ return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)(frame_size - (2 * SSIZE_OF(sw))));
+ }
+
+ FAIL_IF(push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)local_size));
+ tmp = 1;
+ } else if (frame_size == 0) {
+ frame_size = (restored_reg == TMP_REG2) ? SSIZE_OF(sw) : 2 * SSIZE_OF(sw);
+ tmp = 3;
+ }
+
+ /* Place for the saved register. */
+ if (restored_reg != TMP_REG2)
+ local_size += SSIZE_OF(sw);
+ }
+
+ /* Place for the lr register. */
+ local_size += SSIZE_OF(sw);
+
+ if (frame_size > local_size)
+ FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | (sljit_ins)(frame_size - local_size)));
+ else if (frame_size < local_size)
+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size)));
+
+ if (tmp <= 1)
+ return SLJIT_SUCCESS;
+
+ if (tmp == 2) {
+ frame_size -= SSIZE_OF(sw);
+ if (restored_reg != TMP_REG2)
+ frame_size -= SSIZE_OF(sw);
+
+ return push_inst(compiler, LDR | 0x800000 | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)frame_size);
+ }
+
+ tmp = (restored_reg == TMP_REG2) ? 0x800004 : 0x800008;
+ return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(restored_reg) | (sljit_ins)tmp);
+ }
+
+ if (local_size > 0)
+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));
+
+ /* Pop saved and temporary registers
+ multiple registers: ldmia sp!, {...}
+ single register: ldr reg, [sp], #4 */
+ if ((reg_list & (reg_list - 1)) == 0) {
+ SLJIT_ASSERT(lr_dst != 0);
+ SLJIT_ASSERT(reg_list == (sljit_uw)1 << reg_map[lr_dst]);
+
+ return push_inst(compiler, LDR_POST | RN(SLJIT_SP) | RD(lr_dst) | 0x800004);
+ }
+
+ FAIL_IF(push_inst(compiler, POP | reg_list));
+
+ if (frame_size > 0)
+ return push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | ((sljit_ins)frame_size - sizeof(sljit_sw)));
+
+ if (lr_dst != 0)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | sizeof(sljit_sw));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ return emit_stack_frame_release(compiler, 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
+ src = TMP_REG1;
+ srcw = 0;
+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src)));
+ src = TMP_REG1;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 1));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
+}
+
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
+static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+ sljit_uw dst, sljit_uw src1, sljit_uw src2)
+{
+ sljit_s32 reg, is_masked;
+ sljit_uw shift_type;
+
+ switch (op) {
+ case SLJIT_MOV:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
+ if (dst != src2) {
+ if (src2 & SRC2_IMM) {
+ return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);
+ }
+ return push_inst(compiler, MOV | RD(dst) | RM(src2));
+ }
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_U8:
+ case SLJIT_MOV_S8:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
+ if (flags & REGISTER_OP)
+ return push_inst(compiler, (op == SLJIT_MOV_U8 ? UXTB : SXTB) | RD(dst) | RM(src2));
+
+ if (dst != src2) {
+ SLJIT_ASSERT(src2 & SRC2_IMM);
+ return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);
+ }
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_U16:
+ case SLJIT_MOV_S16:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
+ if (flags & REGISTER_OP)
+ return push_inst(compiler, (op == SLJIT_MOV_U16 ? UXTH : SXTH) | RD(dst) | RM(src2));
+
+ if (dst != src2) {
+ SLJIT_ASSERT(src2 & SRC2_IMM);
+ return push_inst(compiler, ((flags & INV_IMM) ? MVN : MOV) | RD(dst) | src2);
+ }
+ return SLJIT_SUCCESS;
+
+ case SLJIT_CLZ:
+ SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM));
+ FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(src2)));
+ return SLJIT_SUCCESS;
+
+ case SLJIT_CTZ:
+ SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM));
+ SLJIT_ASSERT(src1 == TMP_REG1 && src2 != TMP_REG2 && !(flags & ARGS_SWAPPED));
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ FAIL_IF(push_inst(compiler, RSB | SRC2_IMM | RD(TMP_REG2) | RN(src2) | 0));
+ FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RN(src2) | RM(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, CLZ | RD(dst) | RM(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, CMP | SET_FLAGS | SRC2_IMM | RN(dst) | 32));
+ return push_inst(compiler, (EOR ^ 0xf0000000) | SRC2_IMM | RD(dst) | RN(dst) | 0x1f);
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ FAIL_IF(push_inst(compiler, RBIT | RD(dst) | RM(src2)));
+ return push_inst(compiler, CLZ | RD(dst) | RM(dst));
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+ case SLJIT_REV:
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
+ return push_inst(compiler, REV | RD(dst) | RM(src2));
+
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & ARGS_SWAPPED));
+ FAIL_IF(push_inst(compiler, REV16 | RD(dst) | RM(src2)));
+ if (!(flags & REGISTER_OP))
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, (op == SLJIT_REV_U16 ? UXTH : SXTH) | RD(dst) | RM(dst));
+ case SLJIT_ADD:
+ SLJIT_ASSERT(!(flags & INV_IMM));
+
+ if ((flags & (UNUSED_RETURN | ARGS_SWAPPED)) == UNUSED_RETURN)
+ return push_inst(compiler, CMN | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
+ return push_inst(compiler, ADD | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
+
+ case SLJIT_ADDC:
+ SLJIT_ASSERT(!(flags & INV_IMM));
+ return push_inst(compiler, ADC | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
+
+ case SLJIT_SUB:
+ SLJIT_ASSERT(!(flags & INV_IMM));
+
+ if ((flags & (UNUSED_RETURN | ARGS_SWAPPED)) == UNUSED_RETURN)
+ return push_inst(compiler, CMP | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
+
+ return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SUB : RSB) | (flags & SET_FLAGS)
+ | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
+
+ case SLJIT_SUBC:
+ SLJIT_ASSERT(!(flags & INV_IMM));
+ return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SBC : RSC) | (flags & SET_FLAGS)
+ | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
+
+ case SLJIT_MUL:
+ SLJIT_ASSERT(!(flags & INV_IMM));
+ SLJIT_ASSERT(!(src2 & SRC2_IMM));
+ compiler->status_flags_state = 0;
+
+ if (!(flags & SET_FLAGS))
+ return push_inst(compiler, MUL | RN(dst) | RM8(src2) | RM(src1));
+
+ reg = dst == TMP_REG1 ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(push_inst(compiler, SMULL | RN(reg) | RD(dst) | RM8(src2) | RM(src1)));
+
+ /* cmp TMP_REG1, dst asr #31. */
+ return push_inst(compiler, CMP | SET_FLAGS | RN(reg) | RM(dst) | 0xfc0);
+
+ case SLJIT_AND:
+ if ((flags & (UNUSED_RETURN | INV_IMM)) == UNUSED_RETURN)
+ return push_inst(compiler, TST | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
+ return push_inst(compiler, (!(flags & INV_IMM) ? AND : BIC) | (flags & SET_FLAGS)
+ | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
+
+ case SLJIT_OR:
+ SLJIT_ASSERT(!(flags & INV_IMM));
+ return push_inst(compiler, ORR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
+
+ case SLJIT_XOR:
+ if (flags & INV_IMM) {
+ SLJIT_ASSERT(src2 == SRC2_IMM);
+ return push_inst(compiler, MVN | (flags & SET_FLAGS) | RD(dst) | RM(src1));
+ }
+ return push_inst(compiler, EOR | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
+
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ shift_type = 0;
+ is_masked = op == SLJIT_MSHL;
+ break;
+
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ shift_type = 1;
+ is_masked = op == SLJIT_MLSHR;
+ break;
+
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ shift_type = 2;
+ is_masked = op == SLJIT_MASHR;
+ break;
+
+ case SLJIT_ROTL:
+ if (compiler->shift_imm == 0x20) {
+ FAIL_IF(push_inst(compiler, RSB | SRC2_IMM | RD(TMP_REG2) | RN(src2) | 0));
+ src2 = TMP_REG2;
+ } else
+ compiler->shift_imm = (sljit_uw)(-(sljit_sw)compiler->shift_imm) & 0x1f;
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_ROTR:
+ shift_type = 3;
+ is_masked = 0;
+ break;
+
+ case SLJIT_MULADD:
+ return push_inst(compiler, MLA | RN(dst) | RD(dst) | RM8(src2) | RM(src1));
+
+ default:
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
+ }
+
+ SLJIT_ASSERT(!(flags & ARGS_SWAPPED) && !(flags & INV_IMM) && !(src2 & SRC2_IMM));
+
+ if (compiler->shift_imm != 0x20) {
+ SLJIT_ASSERT(src1 == TMP_REG1);
+
+ if (compiler->shift_imm != 0)
+ return push_inst(compiler, MOV | (flags & SET_FLAGS) |
+ RD(dst) | (compiler->shift_imm << 7) | (shift_type << 5) | RM(src2));
+ return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | RM(src2));
+ }
+
+ SLJIT_ASSERT(src1 != TMP_REG2);
+
+ if (is_masked) {
+ FAIL_IF(push_inst(compiler, AND | RD(TMP_REG2) | RN(src2) | SRC2_IMM | 0x1f));
+ src2 = TMP_REG2;
+ }
+
+ return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst)
+ | RM8(src2) | (sljit_ins)(shift_type << 5) | 0x10 | RM(src1));
+}
+
+#undef EMIT_SHIFT_INS_AND_RETURN
+
+/* Tests whether the immediate can be stored in the 12 bit imm field.
+ Returns with 0 if not possible. */
+static sljit_uw get_imm(sljit_uw imm)
+{
+ sljit_u32 rol;
+
+ if (imm <= 0xff)
+ return SRC2_IMM | imm;
+
+ if (!(imm & 0xff000000)) {
+ imm <<= 8;
+ rol = 8;
+ } else {
+ imm = (imm << 24) | (imm >> 8);
+ rol = 0;
+ }
+
+ if (!(imm & 0xff000000)) {
+ imm <<= 8;
+ rol += 4;
+ }
+
+ if (!(imm & 0xf0000000)) {
+ imm <<= 4;
+ rol += 2;
+ }
+
+ if (!(imm & 0xc0000000)) {
+ imm <<= 2;
+ rol += 1;
+ }
+
+ if (!(imm & 0x00ffffff))
+ return SRC2_IMM | (imm >> 24) | (rol << 8);
+ return 0;
+}
+
+static sljit_uw compute_imm(sljit_uw imm, sljit_uw* imm2)
+{
+ sljit_uw mask;
+ sljit_uw imm1;
+ sljit_uw rol;
+
+ /* Step1: Search a zero byte (8 continous zero bit). */
+ mask = 0xff000000;
+ rol = 8;
+ while (1) {
+ if (!(imm & mask)) {
+ /* Rol imm by rol. */
+ imm = (imm << rol) | (imm >> (32 - rol));
+ /* Calculate arm rol. */
+ rol = 4 + (rol >> 1);
+ break;
+ }
+
+ rol += 2;
+ mask >>= 2;
+ if (mask & 0x3) {
+ /* rol by 8. */
+ imm = (imm << 8) | (imm >> 24);
+ mask = 0xff00;
+ rol = 24;
+ while (1) {
+ if (!(imm & mask)) {
+ /* Rol imm by rol. */
+ imm = (imm << rol) | (imm >> (32 - rol));
+ /* Calculate arm rol. */
+ rol = (rol >> 1) - 8;
+ break;
+ }
+ rol += 2;
+ mask >>= 2;
+ if (mask & 0x3)
+ return 0;
+ }
+ break;
+ }
+ }
+
+ /* The low 8 bit must be zero. */
+ SLJIT_ASSERT(!(imm & 0xff));
+
+ if (!(imm & 0xff000000)) {
+ imm1 = SRC2_IMM | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8);
+ *imm2 = SRC2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8);
+ } else if (imm & 0xc0000000) {
+ imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);
+ imm <<= 8;
+ rol += 4;
+
+ if (!(imm & 0xff000000)) {
+ imm <<= 8;
+ rol += 4;
+ }
+
+ if (!(imm & 0xf0000000)) {
+ imm <<= 4;
+ rol += 2;
+ }
+
+ if (!(imm & 0xc0000000)) {
+ imm <<= 2;
+ rol += 1;
+ }
+
+ if (!(imm & 0x00ffffff))
+ *imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);
+ else
+ return 0;
+ } else {
+ if (!(imm & 0xf0000000)) {
+ imm <<= 4;
+ rol += 2;
+ }
+
+ if (!(imm & 0xc0000000)) {
+ imm <<= 2;
+ rol += 1;
+ }
+
+ imm1 = SRC2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);
+ imm <<= 8;
+ rol += 4;
+
+ if (!(imm & 0xf0000000)) {
+ imm <<= 4;
+ rol += 2;
+ }
+
+ if (!(imm & 0xc0000000)) {
+ imm <<= 2;
+ rol += 1;
+ }
+
+ if (!(imm & 0x00ffffff))
+ *imm2 = SRC2_IMM | (imm >> 24) | ((rol & 0xf) << 8);
+ else
+ return 0;
+ }
+
+ return imm1;
+}
+
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm)
+{
+ sljit_uw tmp;
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ sljit_uw imm1, imm2;
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ if (!(imm & ~(sljit_uw)0xffff))
+ return push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff));
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+ /* Create imm by 1 inst. */
+ tmp = get_imm(imm);
+ if (tmp)
+ return push_inst(compiler, MOV | RD(reg) | tmp);
+
+ tmp = get_imm(~imm);
+ if (tmp)
+ return push_inst(compiler, MVN | RD(reg) | tmp);
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ /* Create imm by 2 inst. */
+ imm1 = compute_imm(imm, &imm2);
+ if (imm1 != 0) {
+ FAIL_IF(push_inst(compiler, MOV | RD(reg) | imm1));
+ return push_inst(compiler, ORR | RD(reg) | RN(reg) | imm2);
+ }
+
+ imm1 = compute_imm(~imm, &imm2);
+ if (imm1 != 0) {
+ FAIL_IF(push_inst(compiler, MVN | RD(reg) | imm1));
+ return push_inst(compiler, BIC | RD(reg) | RN(reg) | imm2);
+ }
+
+ /* Load integer. */
+ return push_inst_with_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, reg, TMP_PC, 0), imm);
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)));
+ if (imm <= 0xffff)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff));
+#endif /* SLJIT_CONFIG_ARM_V6 */
+}
+
+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,
+ sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
+{
+ sljit_uw imm, offset_reg, tmp;
+ sljit_sw mask = IS_TYPE1_TRANSFER(flags) ? 0xfff : 0xff;
+ sljit_sw sign = IS_TYPE1_TRANSFER(flags) ? 0x1000 : 0x100;
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+ SLJIT_ASSERT((arg & REG_MASK) != tmp_reg || (arg == SLJIT_MEM1(tmp_reg) && argw >= -mask && argw <= mask));
+
+ if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
+ tmp = (sljit_uw)(argw & (sign | mask));
+ tmp = (sljit_uw)((argw + (tmp <= (sljit_uw)sign ? 0 : sign)) & ~mask);
+
+ FAIL_IF(load_immediate(compiler, tmp_reg, tmp));
+
+ argw -= (sljit_sw)tmp;
+ tmp = 1;
+
+ if (argw < 0) {
+ argw = -argw;
+ tmp = 0;
+ }
+
+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, tmp, reg, tmp_reg,
+ (mask == 0xff) ? TYPE2_TRANSFER_IMM(argw) : argw));
+ }
+
+ if (arg & OFFS_REG_MASK) {
+ offset_reg = OFFS_REG(arg);
+ arg &= REG_MASK;
+ argw &= 0x3;
+
+ if (argw != 0 && (mask == 0xff)) {
+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | ((sljit_ins)argw << 7)));
+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0)));
+ }
+
+ /* Bit 25: RM is offset. */
+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
+ RM(offset_reg) | (mask == 0xff ? 0 : (1 << 25)) | ((sljit_ins)argw << 7)));
+ }
+
+ arg &= REG_MASK;
+
+ if (argw > mask) {
+ tmp = (sljit_uw)(argw & (sign | mask));
+ tmp = (sljit_uw)((argw + (tmp <= (sljit_uw)sign ? 0 : sign)) & ~mask);
+ imm = get_imm(tmp);
+
+ if (imm) {
+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
+ argw -= (sljit_sw)tmp;
+ arg = tmp_reg;
+
+ SLJIT_ASSERT(argw >= -mask && argw <= mask);
+ }
+ } else if (argw < -mask) {
+ tmp = (sljit_uw)(-argw & (sign | mask));
+ tmp = (sljit_uw)((-argw + (tmp <= (sljit_uw)sign ? 0 : sign)) & ~mask);
+ imm = get_imm(tmp);
+
+ if (imm) {
+ FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
+ argw += (sljit_sw)tmp;
+ arg = tmp_reg;
+
+ SLJIT_ASSERT(argw >= -mask && argw <= mask);
+ }
+ }
+
+ if (argw <= mask && argw >= -mask) {
+ if (argw >= 0) {
+ if (mask == 0xff)
+ argw = TYPE2_TRANSFER_IMM(argw);
+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg, argw));
+ }
+
+ argw = -argw;
+
+ if (mask == 0xff)
+ argw = TYPE2_TRANSFER_IMM(argw);
+
+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 0, reg, arg, argw));
+ }
+
+ FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw));
+ return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
+ RM(tmp_reg) | (mask == 0xff ? 0 : (1 << 25))));
+}
+
+static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ /* src1 is reg or TMP_REG1
+ src2 is reg, TMP_REG2, or imm
+ result goes to TMP_REG2, so put result can use TMP_REG1. */
+
+ /* We prefers register and simple consts. */
+ sljit_s32 dst_reg;
+ sljit_s32 src1_reg = 0;
+ sljit_s32 src2_reg = 0;
+ sljit_s32 src2_tmp_reg = 0;
+ sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
+ sljit_s32 neg_op = 0;
+ sljit_u32 imm2;
+
+ op = GET_OPCODE(op);
+
+ if (flags & SET_FLAGS)
+ inp_flags &= ~ALLOW_DOUBLE_IMM;
+
+ if (dst == TMP_REG1)
+ flags |= UNUSED_RETURN;
+
+ SLJIT_ASSERT(!(inp_flags & ALLOW_INV_IMM) || (inp_flags & ALLOW_IMM));
+
+ if (inp_flags & ALLOW_NEG_IMM) {
+ switch (op) {
+ case SLJIT_ADD:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ neg_op = SLJIT_SUB;
+ break;
+ case SLJIT_ADDC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ neg_op = SLJIT_SUBC;
+ break;
+ case SLJIT_SUB:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ neg_op = SLJIT_ADD;
+ break;
+ case SLJIT_SUBC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ neg_op = SLJIT_ADDC;
+ break;
+ }
+ }
+
+ do {
+ if (!(inp_flags & ALLOW_IMM))
+ break;
+
+ if (src2 == SLJIT_IMM) {
+ src2_reg = (sljit_s32)get_imm((sljit_uw)src2w);
+ if (src2_reg)
+ break;
+
+ if (inp_flags & ALLOW_INV_IMM) {
+ src2_reg = (sljit_s32)get_imm(~(sljit_uw)src2w);
+ if (src2_reg) {
+ flags |= INV_IMM;
+ break;
+ }
+ }
+
+ if (neg_op != 0) {
+ src2_reg = (sljit_s32)get_imm((neg_op == SLJIT_ADD || neg_op == SLJIT_SUB) ? (sljit_uw)-src2w : ~(sljit_uw)src2w);
+ if (src2_reg) {
+ op = neg_op | GET_ALL_FLAGS(op);
+ break;
+ }
+ }
+ }
+
+ if (src1 == SLJIT_IMM) {
+ src2_reg = (sljit_s32)get_imm((sljit_uw)src1w);
+ if (src2_reg) {
+ flags |= ARGS_SWAPPED;
+ src1 = src2;
+ src1w = src2w;
+ break;
+ }
+
+ if (inp_flags & ALLOW_INV_IMM) {
+ src2_reg = (sljit_s32)get_imm(~(sljit_uw)src1w);
+ if (src2_reg) {
+ flags |= ARGS_SWAPPED | INV_IMM;
+ src1 = src2;
+ src1w = src2w;
+ break;
+ }
+ }
+
+ if (neg_op >= SLJIT_SUB) {
+ /* Note: additive operation (commutative). */
+ SLJIT_ASSERT(op == SLJIT_ADD || op == SLJIT_ADDC);
+
+ src2_reg = (sljit_s32)get_imm((sljit_uw)-src1w);
+ if (src2_reg) {
+ src1 = src2;
+ src1w = src2w;
+ op = neg_op | GET_ALL_FLAGS(op);
+ break;
+ }
+ }
+ }
+ } while(0);
+
+ /* Destination. */
+ dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (op <= SLJIT_MOV_P) {
+ if (dst & SLJIT_MEM) {
+ if (inp_flags & BYTE_SIZE)
+ inp_flags &= ~SIGNED;
+
+ if (FAST_IS_REG(src2))
+ return emit_op_mem(compiler, inp_flags, src2, dst, dstw, TMP_REG1);
+ }
+
+ if (FAST_IS_REG(src2) && dst_reg != TMP_REG2)
+ flags |= REGISTER_OP;
+
+ src2_tmp_reg = dst_reg;
+ } else {
+ if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {
+ if (!(dst & SLJIT_MEM) && (!(src2 & SLJIT_MEM) || op == SLJIT_REV_S16))
+ flags |= REGISTER_OP;
+ }
+
+ src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;
+ }
+
+ if (src2_reg == 0 && (src2 & SLJIT_MEM)) {
+ src2_reg = src2_tmp_reg;
+ FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, src2_reg, src2, src2w, TMP_REG1));
+ }
+
+ /* Source 1. */
+ if (FAST_IS_REG(src1))
+ src1_reg = src1;
+ else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
+ src1_reg = TMP_REG1;
+ } else if (!(inp_flags & ALLOW_DOUBLE_IMM) || src2_reg != 0 || op == SLJIT_SUB || op == SLJIT_SUBC) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
+ src1_reg = TMP_REG1;
+ }
+
+ /* Source 2. */
+ if (src2_reg == 0) {
+ src2_reg = src2_tmp_reg;
+
+ if (FAST_IS_REG(src2))
+ src2_reg = src2;
+ else if (!(inp_flags & ALLOW_DOUBLE_IMM))
+ FAIL_IF(load_immediate(compiler, src2_reg, (sljit_uw)src2w));
+ else {
+ SLJIT_ASSERT(!(flags & SET_FLAGS));
+
+ if (src1_reg == 0) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
+ src1_reg = TMP_REG1;
+ }
+
+ src2_reg = (sljit_s32)compute_imm((sljit_uw)src2w, &imm2);
+
+ if (src2_reg == 0 && neg_op != 0) {
+ src2_reg = (sljit_s32)compute_imm((sljit_uw)-src2w, &imm2);
+ if (src2_reg != 0)
+ op = neg_op;
+ }
+
+ if (src2_reg == 0) {
+ FAIL_IF(load_immediate(compiler, src2_tmp_reg, (sljit_uw)src2w));
+ src2_reg = src2_tmp_reg;
+ } else {
+ FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src1_reg, (sljit_uw)src2_reg));
+ src1_reg = dst_reg;
+ src2_reg = (sljit_s32)imm2;
+
+ if (op == SLJIT_ADDC)
+ op = SLJIT_ADD;
+ else if (op == SLJIT_SUBC)
+ op = SLJIT_SUB;
+ }
+ }
+ }
+
+ if (src1_reg == 0) {
+ SLJIT_ASSERT((inp_flags & ALLOW_DOUBLE_IMM) && !(flags & SET_FLAGS));
+
+ src1_reg = (sljit_s32)compute_imm((sljit_uw)src1w, &imm2);
+
+ if (src1_reg == 0 && neg_op != 0) {
+ src1_reg = (sljit_s32)compute_imm((sljit_uw)-src1w, &imm2);
+ if (src1_reg != 0)
+ op = neg_op;
+ }
+
+ if (src1_reg == 0) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
+ src1_reg = TMP_REG1;
+ } else {
+ FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src2_reg, (sljit_uw)src1_reg));
+ src1_reg = dst_reg;
+ src2_reg = (sljit_s32)imm2;
+
+ if (op == SLJIT_ADDC)
+ op = SLJIT_ADD;
+ }
+ }
+
+ FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src1_reg, (sljit_uw)src2_reg));
+
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+
+ return emit_op_mem(compiler, inp_flags, dst_reg, dst, dstw, TMP_REG1);
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__GNUC__)
+extern unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator);
+extern int __aeabi_idivmod(int numerator, int denominator);
+#else
+#error "Software divmod functions are needed"
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
+{
+ sljit_uw saved_reg_list[3];
+ sljit_sw saved_reg_count;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op0(compiler, op));
+
+ op = GET_OPCODE(op);
+ switch (op) {
+ case SLJIT_BREAKPOINT:
+ FAIL_IF(push_inst(compiler, BKPT));
+ break;
+ case SLJIT_NOP:
+ FAIL_IF(push_inst(compiler, NOP));
+ break;
+ case SLJIT_LMUL_UW:
+ case SLJIT_LMUL_SW:
+ return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)
+ | RN(SLJIT_R1) | RD(SLJIT_R0) | RM8(SLJIT_R0) | RM(SLJIT_R1));
+ case SLJIT_DIVMOD_UW:
+ case SLJIT_DIVMOD_SW:
+ case SLJIT_DIV_UW:
+ case SLJIT_DIV_SW:
+ SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
+ SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 3);
+
+ saved_reg_count = 0;
+ if (compiler->scratches >= 4)
+ saved_reg_list[saved_reg_count++] = 3;
+ if (compiler->scratches >= 3)
+ saved_reg_list[saved_reg_count++] = 2;
+ if (op >= SLJIT_DIV_UW)
+ saved_reg_list[saved_reg_count++] = 1;
+
+ if (saved_reg_count > 0) {
+ FAIL_IF(push_inst(compiler, STR | 0x2d0000 | (saved_reg_count >= 3 ? 16 : 8)
+ | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));
+ if (saved_reg_count >= 2) {
+ SLJIT_ASSERT(saved_reg_list[1] < 8);
+ FAIL_IF(push_inst(compiler, STR | 0x8d0004 | (saved_reg_list[1] << 12) /* str rX, [sp, #4] */));
+ }
+ if (saved_reg_count >= 3) {
+ SLJIT_ASSERT(saved_reg_list[2] < 8);
+ FAIL_IF(push_inst(compiler, STR | 0x8d0008 | (saved_reg_list[2] << 12) /* str rX, [sp, #8] */));
+ }
+ }
+
+#if defined(__GNUC__)
+ FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
+ ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_ADDR(__aeabi_uidivmod) : SLJIT_FUNC_ADDR(__aeabi_idivmod))));
+#else
+#error "Software divmod functions are needed"
+#endif
+
+ if (saved_reg_count > 0) {
+ if (saved_reg_count >= 3) {
+ SLJIT_ASSERT(saved_reg_list[2] < 8);
+ FAIL_IF(push_inst(compiler, LDR | 0x8d0008 | (saved_reg_list[2] << 12) /* ldr rX, [sp, #8] */));
+ }
+ if (saved_reg_count >= 2) {
+ SLJIT_ASSERT(saved_reg_list[1] < 8);
+ FAIL_IF(push_inst(compiler, LDR | 0x8d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */));
+ }
+ return push_inst(compiler, (LDR ^ (1 << 24)) | 0x8d0000 | (sljit_ins)(saved_reg_count >= 3 ? 16 : 8)
+ | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
+ }
+ return SLJIT_SUCCESS;
+ case SLJIT_MEMORY_BARRIER:
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+ return push_inst(compiler, DMB_SY);
+#else /* !SLJIT_CONFIG_ARM_V7 */
+ return SLJIT_ERR_UNSUPPORTED;
+#endif /* SLJIT_CONFIG_ARM_V7 */
+ case SLJIT_ENDBR:
+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
+ return SLJIT_SUCCESS;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ case SLJIT_MOV_P:
+ return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_MOV_U8:
+ return emit_op(compiler, SLJIT_MOV_U8, ALLOW_ANY_IMM | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);
+
+ case SLJIT_MOV_S8:
+ return emit_op(compiler, SLJIT_MOV_S8, ALLOW_ANY_IMM | SIGNED | BYTE_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);
+
+ case SLJIT_MOV_U16:
+ return emit_op(compiler, SLJIT_MOV_U16, ALLOW_ANY_IMM | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);
+
+ case SLJIT_MOV_S16:
+ return emit_op(compiler, SLJIT_MOV_S16, ALLOW_ANY_IMM | SIGNED | HALF_SIZE, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);
+
+ case SLJIT_CLZ:
+ case SLJIT_CTZ:
+ case SLJIT_REV:
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+ return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+ return emit_op(compiler, op, HALF_SIZE, dst, dstw, TMP_REG1, 0, src, srcw);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 inp_flags;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD:
+ case SLJIT_ADDC:
+ case SLJIT_SUB:
+ case SLJIT_SUBC:
+ return emit_op(compiler, op, ALLOW_IMM | ALLOW_NEG_IMM | ALLOW_DOUBLE_IMM, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_OR:
+ return emit_op(compiler, op, ALLOW_IMM | ALLOW_DOUBLE_IMM, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_XOR:
+ inp_flags = ALLOW_IMM | ALLOW_DOUBLE_IMM;
+ if ((src1 == SLJIT_IMM && src1w == -1) || (src2 == SLJIT_IMM && src2w == -1)) {
+ inp_flags |= ALLOW_INV_IMM;
+ }
+ return emit_op(compiler, op, inp_flags, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_MUL:
+ return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_AND:
+ return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ case SLJIT_ROTL:
+ case SLJIT_ROTR:
+ if (src2 == SLJIT_IMM) {
+ compiler->shift_imm = src2w & 0x1f;
+ return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src1, src1w);
+ } else {
+ compiler->shift_imm = 0x20;
+ return emit_op(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w);
+ }
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MULADD:
+ return emit_op(compiler, op, 0, dst_reg, 0, src1, src1w, src2, src2w);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1_reg,
+ sljit_s32 src2_reg,
+ sljit_s32 src3, sljit_sw src3w)
+{
+ sljit_s32 is_left;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
+
+ op = GET_OPCODE(op);
+ is_left = (op == SLJIT_SHL || op == SLJIT_MSHL);
+
+ if (src1_reg == src2_reg) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, is_left ? SLJIT_ROTL : SLJIT_ROTR, dst_reg, 0, src1_reg, 0, src3, src3w);
+ }
+
+ ADJUST_LOCAL_OFFSET(src3, src3w);
+
+ /* Shift type of ROR is 3. */
+ if (src3 == SLJIT_IMM) {
+ src3w &= 0x1f;
+
+ if (src3w == 0)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM(src1_reg) | ((sljit_ins)(is_left ? 0 : 1) << 5) | ((sljit_ins)src3w << 7)));
+ src3w = (src3w ^ 0x1f) + 1;
+ return push_inst(compiler, ORR | RD(dst_reg) | RN(dst_reg) | RM(src2_reg) | ((sljit_ins)(is_left ? 1 : 0) << 5) | ((sljit_ins)src3w << 7));
+ }
+
+ if (src3 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src3, src3w, TMP_REG2));
+ src3 = TMP_REG2;
+ }
+
+ if (op == SLJIT_MSHL || op == SLJIT_MLSHR || dst_reg == src3) {
+ FAIL_IF(push_inst(compiler, AND | SRC2_IMM | RD(TMP_REG2) | RN(src3) | 0x1f));
+ src3 = TMP_REG2;
+ }
+
+ FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM8(src3) | ((sljit_ins)(is_left ? 0 : 1) << 5) | 0x10 | RM(src1_reg)));
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src2_reg) | ((sljit_ins)(is_left ? 1 : 0) << 5) | (1 << 7)));
+ FAIL_IF(push_inst(compiler, EOR | SRC2_IMM | RD(TMP_REG2) | RN(src3) | 0x1f));
+ return push_inst(compiler, ORR | RD(dst_reg) | RN(dst_reg) | RM8(TMP_REG2) | ((sljit_ins)(is_left ? 1 : 0) << 5) | 0x10 | RM(TMP_REG1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r, tmp_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= 0x1f;
+
+ if (src2 == SLJIT_IMM) {
+ src2w = (sljit_sw)((sljit_uw)src2w << shift_arg);
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
+ src1 = TMP_REG1;
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
+ src1 = TMP_REG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, tmp_r, src2, src2w, tmp_r));
+ src2 = tmp_r;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RN(src1) | RM(src2) | ((sljit_ins)shift_arg << 7)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_SIZE, dst_r, dst, dstw, TMP_REG1);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ switch (op) {
+ case SLJIT_FAST_RETURN:
+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
+
+ if (FAST_IS_REG(src)) {
+ if (src != TMP_REG2)
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src)));
+ } else
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1));
+
+ return push_inst(compiler, BX | RM(TMP_REG2));
+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
+ return SLJIT_SUCCESS;
+ case SLJIT_PREFETCH_L1:
+ case SLJIT_PREFETCH_L2:
+ case SLJIT_PREFETCH_L3:
+ case SLJIT_PREFETCH_ONCE:
+ SLJIT_ASSERT(src & SLJIT_MEM);
+ return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 size, dst_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ switch (op) {
+ case SLJIT_FAST_ENTER:
+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
+
+ if (FAST_IS_REG(dst)) {
+ if (dst == TMP_REG2)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, MOV | RD(dst) | RM(TMP_REG2));
+ }
+ break;
+ case SLJIT_GET_RETURN_ADDRESS:
+ size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 0);
+
+ if (compiler->fsaveds > 0 || compiler->fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ /* The size of pc is not added above. */
+ if ((size & SSIZE_OF(sw)) == 0)
+ size += SSIZE_OF(sw);
+
+ size += GET_SAVED_FLOAT_REGISTERS_SIZE(compiler->fscratches, compiler->fsaveds, f64);
+ }
+
+ SLJIT_ASSERT(((compiler->local_size + size + SSIZE_OF(sw)) & 0x7) == 0);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + size, TMP_REG1));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
+{
+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
+
+ if (type == SLJIT_GP_REGISTER)
+ return reg_map[reg];
+
+ if (type == SLJIT_FLOAT_REGISTER || type == SLJIT_SIMD_REG_64)
+ return freg_map[reg];
+
+ if (type == SLJIT_SIMD_REG_128)
+ return freg_map[reg] & ~0x1;
+
+ return -1;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_u32 size)
+{
+ SLJIT_UNUSED_ARG(size);
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
+
+ return push_inst(compiler, *(sljit_ins*)instruction);
+}
+
+/* --------------------------------------------------------------------- */
+/* Floating point operators */
+/* --------------------------------------------------------------------- */
+
+#define FPU_LOAD (1 << 20)
+#define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \
+ ((inst) | (sljit_ins)((add) << 23) | RN(base) | VD(freg) | (sljit_ins)(offs))
+
+static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
+{
+ sljit_uw imm;
+ sljit_ins inst = VSTR_F32 | (flags & (SLJIT_32 | FPU_LOAD));
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+ arg &= ~SLJIT_MEM;
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (((sljit_ins)argw & 0x3) << 7)));
+ arg = TMP_REG1;
+ argw = 0;
+ }
+
+ /* Fast loads and stores. */
+ if (arg) {
+ if (!(argw & ~0x3fc))
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, arg & REG_MASK, reg, argw >> 2));
+ if (!(-argw & ~0x3fc))
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & REG_MASK, reg, (-argw) >> 2));
+
+ imm = get_imm((sljit_uw)argw & ~(sljit_uw)0x3fc);
+ if (imm) {
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | imm));
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, (argw & 0x3fc) >> 2));
+ }
+ imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0x3fc);
+ if (imm) {
+ argw = -argw;
+ FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG1) | RN(arg & REG_MASK) | imm));
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, TMP_REG1, reg, (argw & 0x3fc) >> 2));
+ }
+ }
+
+ if (arg) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)argw));
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(TMP_REG1)));
+ }
+ else
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)argw));
+
+ return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG1, reg, 0));
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ op ^= SLJIT_32;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src, srcw));
+ src = TMP_FREG1;
+ }
+
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_S32_F32, op & SLJIT_32, TMP_FREG1, src, 0)));
+
+ if (FAST_IS_REG(dst))
+ return push_inst(compiler, VMOV | (1 << 20) | RD(dst) | VN(TMP_FREG1));
+
+ /* Store the integer value from a VFP register. */
+ return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);
+}
+
+static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (FAST_IS_REG(src))
+ FAIL_IF(push_inst(compiler, VMOV | RD(src) | VN(TMP_FREG1)));
+ else if (src & SLJIT_MEM) {
+ /* Load the integer value into a VFP register. */
+ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));
+ }
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));
+ FAIL_IF(push_inst(compiler, VMOV | RD(TMP_REG1) | VN(TMP_FREG1)));
+ }
+
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(ins, ins & SLJIT_32, dst_r, TMP_FREG1, 0)));
+
+ if (dst & SLJIT_MEM)
+ return emit_fop_mem(compiler, (ins & SLJIT_32), TMP_FREG1, dst, dstw);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ return sljit_emit_fop1_conv_f64_from_w(compiler, VCVT_F32_S32 | (~op & SLJIT_32), dst, dstw, src, srcw);
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ return sljit_emit_fop1_conv_f64_from_w(compiler, VCVT_F32_U32 | (~op & SLJIT_32), dst, dstw, src, srcw);
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ op ^= SLJIT_32;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));
+ src1 = TMP_FREG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));
+ src2 = TMP_FREG2;
+ }
+
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_32, src1, src2, 0)));
+ FAIL_IF(push_inst(compiler, VMRS));
+
+ if (GET_FLAG_TYPE(op) != SLJIT_UNORDERED_OR_EQUAL)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, (CMP - CONDITIONAL) | (0x60000000 /* VS */) | SET_FLAGS | RN(TMP_REG1) | RM(TMP_REG1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+
+ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100), float_transfer_bit_error);
+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32)
+ op ^= SLJIT_32;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, dst_r, src, srcw));
+ src = dst_r;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_F64:
+ if (src != dst_r) {
+ if (!(dst & SLJIT_MEM))
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, op & SLJIT_32, dst_r, src, 0)));
+ else
+ dst_r = src;
+ }
+ break;
+ case SLJIT_NEG_F64:
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_32, dst_r, src, 0)));
+ break;
+ case SLJIT_ABS_F64:
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_32, dst_r, src, 0)));
+ break;
+ case SLJIT_CONV_F64_FROM_F32:
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F64_F32, op & SLJIT_32, dst_r, src, 0)));
+ op ^= SLJIT_32;
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_fop_mem(compiler, (op & SLJIT_32), dst_r, dst, dstw);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ op ^= SLJIT_32;
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));
+ src2 = TMP_FREG2;
+ }
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));
+ src1 = TMP_FREG1;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD_F64:
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_32, dst_r, src2, src1)));
+ break;
+ case SLJIT_SUB_F64:
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_32, dst_r, src2, src1)));
+ break;
+ case SLJIT_MUL_F64:
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_32, dst_r, src2, src1)));
+ break;
+ case SLJIT_DIV_F64:
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_32, dst_r, src2, src1)));
+ break;
+ case SLJIT_COPYSIGN_F64:
+ FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(src2) | RD(TMP_REG1) | ((op & SLJIT_32) ? (1 << 7) : 0)));
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_32, dst_r, src1, 0)));
+ FAIL_IF(push_inst(compiler, CMP | SET_FLAGS | RN(TMP_REG1) | SRC2_IMM | 0));
+ return push_inst(compiler, EMIT_FPU_OPERATION((VNEG_F32 & ~COND_MASK) | 0xb0000000, op & SLJIT_32, dst_r, dst_r, 0));
+ }
+
+ if (dst_r != dst)
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw));
+
+ return SLJIT_SUCCESS;
+}
+
+#undef EMIT_FPU_DATA_TRANSFER
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f32 value)
+{
+#if defined(__ARM_NEON) && __ARM_NEON
+ sljit_u32 exp;
+ sljit_ins ins;
+#endif /* NEON */
+ union {
+ sljit_u32 imm;
+ sljit_f32 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset32(compiler, freg, value));
+
+ u.value = value;
+
+#if defined(__ARM_NEON) && __ARM_NEON
+ if ((u.imm << (32 - 19)) == 0) {
+ exp = (u.imm >> (23 + 2)) & 0x3f;
+
+ if (exp == 0x20 || exp == 0x1f) {
+ ins = ((u.imm >> 24) & 0x80) | ((u.imm >> 19) & 0x7f);
+ return push_inst(compiler, (VMOV_F32 ^ (1 << 6)) | ((ins & 0xf0) << 12) | VD(freg) | (ins & 0xf));
+ }
+ }
+#endif /* NEON */
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));
+ return push_inst(compiler, VMOV | VN(freg) | RD(TMP_REG1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value)
+{
+#if defined(__ARM_NEON) && __ARM_NEON
+ sljit_u32 exp;
+ sljit_ins ins;
+#endif /* NEON */
+ union {
+ sljit_u32 imm[2];
+ sljit_f64 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset64(compiler, freg, value));
+
+ u.value = value;
+
+#if defined(__ARM_NEON) && __ARM_NEON
+ if (u.imm[0] == 0 && (u.imm[1] << (64 - 48)) == 0) {
+ exp = (u.imm[1] >> ((52 - 32) + 2)) & 0x1ff;
+
+ if (exp == 0x100 || exp == 0xff) {
+ ins = ((u.imm[1] >> (56 - 32)) & 0x80) | ((u.imm[1] >> (48 - 32)) & 0x7f);
+ return push_inst(compiler, (VMOV_F32 ^ (1 << 6)) | (1 << 8) | ((ins & 0xf0) << 12) | VD(freg) | (ins & 0xf));
+ }
+ }
+#endif /* NEON */
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0]));
+ if (u.imm[0] == u.imm[1])
+ return push_inst(compiler, VMOV2 | RN(TMP_REG1) | RD(TMP_REG1) | VM(freg));
+
+ FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1]));
+ return push_inst(compiler, VMOV2 | RN(TMP_REG2) | RD(TMP_REG1) | VM(freg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg)
+{
+ sljit_s32 reg2;
+ sljit_ins inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
+
+ if (reg & REG_PAIR_MASK) {
+ reg2 = REG_PAIR_SECOND(reg);
+ reg = REG_PAIR_FIRST(reg);
+
+ inst = VMOV2 | RN(reg) | RD(reg2) | VM(freg);
+ } else {
+ inst = VMOV | VN(freg) | RD(reg);
+
+ if (!(op & SLJIT_32))
+ inst |= 1 << 7;
+ }
+
+ if (GET_OPCODE(op) == SLJIT_COPY_FROM_F64)
+ inst |= 1 << 20;
+
+ return push_inst(compiler, inst);
+}
+
+/* --------------------------------------------------------------------- */
+/* Conditional instructions */
+/* --------------------------------------------------------------------- */
+
+static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
+{
+ switch (type) {
+ case SLJIT_EQUAL:
+ case SLJIT_ATOMIC_STORED:
+ case SLJIT_F_EQUAL:
+ case SLJIT_ORDERED_EQUAL:
+ case SLJIT_UNORDERED_OR_EQUAL:
+ return 0x00000000;
+
+ case SLJIT_NOT_EQUAL:
+ case SLJIT_ATOMIC_NOT_STORED:
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_NOT_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ return 0x10000000;
+
+ case SLJIT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
+ return 0x20000000;
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_LESS:
+ return 0x30000000;
+
+ case SLJIT_NOT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
+ return 0x30000000;
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_GREATER_EQUAL:
+ return 0x20000000;
+
+ case SLJIT_GREATER:
+ case SLJIT_UNORDERED_OR_GREATER:
+ return 0x80000000;
+
+ case SLJIT_LESS_EQUAL:
+ case SLJIT_F_LESS_EQUAL:
+ case SLJIT_ORDERED_LESS_EQUAL:
+ return 0x90000000;
+
+ case SLJIT_SIG_LESS:
+ case SLJIT_UNORDERED_OR_LESS:
+ return 0xb0000000;
+
+ case SLJIT_SIG_GREATER_EQUAL:
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_ORDERED_GREATER_EQUAL:
+ return 0xa0000000;
+
+ case SLJIT_SIG_GREATER:
+ case SLJIT_F_GREATER:
+ case SLJIT_ORDERED_GREATER:
+ return 0xc0000000;
+
+ case SLJIT_SIG_LESS_EQUAL:
+ case SLJIT_UNORDERED_OR_LESS_EQUAL:
+ return 0xd0000000;
+
+ case SLJIT_OVERFLOW:
+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
+ return 0x10000000;
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_UNORDERED:
+ return 0x60000000;
+
+ case SLJIT_NOT_OVERFLOW:
+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
+ return 0x00000000;
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_ORDERED:
+ return 0x70000000;
+
+ case SLJIT_F_LESS:
+ case SLJIT_ORDERED_LESS:
+ return 0x40000000;
+
+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:
+ return 0x50000000;
+
+ default:
+ SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);
+ return 0xe0000000;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_label(compiler));
+
+ if (compiler->last_label && compiler->last_label->size == compiler->size)
+ return compiler->last_label;
+
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+ PTR_FAIL_IF(!label);
+ set_label(label, compiler);
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, i;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY))
+ PTR_FAIL_IF(push_cpool(compiler));
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+ if (alignment <= SLJIT_LABEL_ALIGN_4) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);
+
+ for (i = (mask >> 2); i != 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ for (i = (buffers->size + 3) >> 2; i > 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
+{
+ struct sljit_jump *jump;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_jump(compiler, type));
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ type &= 0xff;
+
+ SLJIT_ASSERT(reg_map[TMP_REG1] != 14);
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ if (type >= SLJIT_FAST_CALL)
+ PTR_FAIL_IF(prepare_blx(compiler));
+
+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler, ((EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
+ type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0)) & ~COND_MASK) | get_cc(compiler, type), 0));
+ jump->addr = compiler->size - 1;
+
+ if (jump->flags & SLJIT_REWRITABLE_JUMP)
+ compiler->patches++;
+
+ if (type >= SLJIT_FAST_CALL) {
+ jump->flags |= IS_BL;
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(emit_blx(compiler));
+ }
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ jump->addr = compiler->size;
+ if (type >= SLJIT_FAST_CALL)
+ jump->flags |= IS_BL;
+ PTR_FAIL_IF(push_inst(compiler, (((type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)) & ~COND_MASK) | get_cc(compiler, type)));
+ compiler->size += JUMP_MAX_SIZE - 1;
+#endif /* SLJIT_CONFIG_ARM_V6 */
+ return jump;
+}
+
+#ifdef __SOFTFP__
+
+static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src, sljit_u32 *extra_space)
+{
+ sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;
+ sljit_u32 offset = 0;
+ sljit_u32 word_arg_offset = 0;
+ sljit_u32 src_offset = 4 * sizeof(sljit_sw);
+ sljit_u32 float_arg_count = 0;
+ sljit_s32 types = 0;
+ sljit_u8 offsets[4];
+ sljit_u8 *offset_ptr = offsets;
+
+ if (src && FAST_IS_REG(*src))
+ src_offset = (sljit_u32)reg_map[*src] * sizeof(sljit_sw);
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ while (arg_types) {
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
+
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset & 0x7)
+ offset += sizeof(sljit_sw);
+ *offset_ptr++ = (sljit_u8)offset;
+ offset += sizeof(sljit_f64);
+ float_arg_count++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ *offset_ptr++ = (sljit_u8)offset;
+ offset += sizeof(sljit_f32);
+ float_arg_count++;
+ break;
+ default:
+ *offset_ptr++ = (sljit_u8)offset;
+ offset += sizeof(sljit_sw);
+ word_arg_offset += sizeof(sljit_sw);
+ break;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {
+ /* Keep lr register on the stack. */
+ if (is_tail_call)
+ offset += sizeof(sljit_sw);
+
+ offset = ((offset - 4 * sizeof(sljit_sw)) + 0x7) & ~(sljit_u32)0x7;
+
+ *extra_space = offset;
+
+ if (is_tail_call)
+ FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset));
+ else
+ FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | offset));
+ } else {
+ if (is_tail_call)
+ FAIL_IF(emit_stack_frame_release(compiler, -1));
+ *extra_space = 0;
+ }
+
+ /* Process arguments in reversed direction. */
+ while (types) {
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ float_arg_count--;
+ offset = *(--offset_ptr);
+
+ SLJIT_ASSERT((offset & 0x7) == 0);
+
+ if (offset < 4 * sizeof(sljit_sw)) {
+ if (src_offset == offset || src_offset == offset + sizeof(sljit_sw)) {
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));
+ *src = TMP_REG1;
+ }
+ FAIL_IF(push_inst(compiler, VMOV2 | 0x100000 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));
+ } else
+ FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800100 | RN(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ float_arg_count--;
+ offset = *(--offset_ptr);
+
+ if (offset < 4 * sizeof(sljit_sw)) {
+ if (src_offset == offset) {
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));
+ *src = TMP_REG1;
+ }
+ FAIL_IF(push_inst(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (offset << 10)));
+ } else
+ FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800000 | RN(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));
+ break;
+ default:
+ word_arg_offset -= sizeof(sljit_sw);
+ offset = *(--offset_ptr);
+
+ SLJIT_ASSERT(offset >= word_arg_offset);
+
+ if (offset != word_arg_offset) {
+ if (offset < 4 * sizeof(sljit_sw)) {
+ if (src_offset == offset) {
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));
+ *src = TMP_REG1;
+ }
+ else if (src_offset == word_arg_offset) {
+ *src = (sljit_s32)(SLJIT_R0 + (offset >> 2));
+ src_offset = offset;
+ }
+ FAIL_IF(push_inst(compiler, MOV | (offset << 10) | (word_arg_offset >> 2)));
+ } else
+ FAIL_IF(push_inst(compiler, STR | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (offset - 4 * sizeof(sljit_sw))));
+ }
+ break;
+ }
+
+ types >>= SLJIT_ARG_SHIFT;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
+{
+ if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64)
+ FAIL_IF(push_inst(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0));
+ if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32)
+ FAIL_IF(push_inst(compiler, VMOV | (0 << 16) | (0 << 12)));
+
+ return SLJIT_SUCCESS;
+}
+
+#else /* !__SOFTFP__ */
+
+static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
+{
+ sljit_u32 offset = SLJIT_FR0;
+ sljit_u32 new_offset = SLJIT_FR0;
+ sljit_u32 f32_offset = 0;
+
+ /* Remove return value. */
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset != new_offset)
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,
+ SLJIT_32, new_offset, offset, 0)));
+
+ new_offset++;
+ offset++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (f32_offset != 0) {
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,
+ 0x400000, f32_offset, offset, 0)));
+ f32_offset = 0;
+ } else {
+ if (offset != new_offset)
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,
+ 0, new_offset, offset, 0)));
+ f32_offset = new_offset;
+ new_offset++;
+ }
+ offset++;
+ break;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+#endif /* __SOFTFP__ */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types)
+{
+#ifdef __SOFTFP__
+ struct sljit_jump *jump;
+ sljit_u32 extra_space = (sljit_u32)type;
+#endif
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
+
+#ifdef __SOFTFP__
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
+ PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
+ SLJIT_ASSERT((extra_space & 0x7) == 0);
+
+ if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+
+ SLJIT_SKIP_CHECKS(compiler);
+ jump = sljit_emit_jump(compiler, type);
+ PTR_FAIL_IF(jump == NULL);
+
+ if (extra_space > 0) {
+ if (type & SLJIT_CALL_RETURN)
+ PTR_FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
+ TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
+
+ PTR_FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
+
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(push_inst(compiler, BX | RM(TMP_REG2)));
+ return jump;
+ }
+ }
+
+ SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
+ PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
+ return jump;
+ }
+#endif /* __SOFTFP__ */
+
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ }
+
+#ifndef __SOFTFP__
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)
+ PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
+#endif /* !__SOFTFP__ */
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_jump(compiler, type);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
+{
+ struct sljit_jump *jump;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ SLJIT_ASSERT(reg_map[TMP_REG1] != 14);
+
+ if (src != SLJIT_IMM) {
+ if (FAST_IS_REG(src)) {
+ SLJIT_ASSERT(reg_map[src] != 14);
+ return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(src));
+ }
+
+ SLJIT_ASSERT(src & SLJIT_MEM);
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
+ return push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1));
+ }
+
+ /* These jumps are converted to jump/call instructions when possible. */
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF(!jump);
+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
+ jump->u.target = (sljit_uw)srcw;
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ if (type >= SLJIT_FAST_CALL)
+ FAIL_IF(prepare_blx(compiler));
+ jump->addr = compiler->size;
+ FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, TMP_PC, 0), 0));
+ if (type >= SLJIT_FAST_CALL) {
+ jump->addr = compiler->size;
+ FAIL_IF(emit_blx(compiler));
+ }
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ jump->addr = compiler->size;
+ FAIL_IF(push_inst(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RM(TMP_REG1)));
+ compiler->size += JUMP_MAX_SIZE - 1;
+#endif /* SLJIT_CONFIG_ARM_V6 */
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types,
+ sljit_s32 src, sljit_sw srcw)
+{
+#ifdef __SOFTFP__
+ sljit_u32 extra_space = (sljit_u32)type;
+#endif
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
+ src = TMP_REG1;
+ }
+
+ if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) {
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src)));
+ src = TMP_REG1;
+ }
+
+#ifdef __SOFTFP__
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
+ FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
+ SLJIT_ASSERT((extra_space & 0x7) == 0);
+
+ if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
+ type = SLJIT_JUMP;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
+
+ if (extra_space > 0) {
+ if (type & SLJIT_CALL_RETURN)
+ FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
+ TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
+
+ FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
+
+ if (type & SLJIT_CALL_RETURN)
+ return push_inst(compiler, BX | RM(TMP_REG2));
+ }
+
+ SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
+ return softfloat_post_call_with_args(compiler, arg_types);
+ }
+#endif /* __SOFTFP__ */
+
+ if (type & SLJIT_CALL_RETURN) {
+ FAIL_IF(emit_stack_frame_release(compiler, -1));
+ type = SLJIT_JUMP;
+ }
+
+#ifndef __SOFTFP__
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)
+ FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
+#endif /* !__SOFTFP__ */
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, type, src, srcw);
+}
+
+#ifdef __SOFTFP__
+
+static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
+{
+ if (compiler->options & SLJIT_ENTER_REG_ARG) {
+ if (src == SLJIT_FR0)
+ return SLJIT_SUCCESS;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw);
+ }
+
+ if (FAST_IS_REG(src)) {
+ if (op & SLJIT_32)
+ return push_inst(compiler, VMOV | (1 << 20) | RD(SLJIT_R0) | VN(src));
+ return push_inst(compiler, VMOV2 | (1 << 20) | RD(SLJIT_R0) | RN(SLJIT_R1) | VM(src));
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+
+ if (op & SLJIT_32)
+ return sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, src, srcw);
+ return sljit_emit_mem(compiler, SLJIT_MOV, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), src, srcw);
+}
+
+#endif /* __SOFTFP__ */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 type)
+{
+ sljit_s32 dst_reg, flags = GET_ALL_FLAGS(op);
+ sljit_ins cc, ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ op = GET_OPCODE(op);
+ cc = get_cc(compiler, type);
+ dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (op < SLJIT_ADD) {
+ FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | SRC2_IMM | 0));
+ FAIL_IF(push_inst(compiler, ((MOV | RD(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc));
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2);
+ return SLJIT_SUCCESS;
+ }
+
+ ins = (op == SLJIT_AND ? AND : (op == SLJIT_OR ? ORR : EOR));
+
+ if (dst & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG2));
+
+ FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 1) & ~COND_MASK) | cc));
+
+ if (op == SLJIT_AND)
+ FAIL_IF(push_inst(compiler, ((ins | RD(dst_reg) | RN(dst_reg) | SRC2_IMM | 0) & ~COND_MASK) | (cc ^ 0x10000000)));
+
+ if (dst & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2));
+
+ if (flags & SLJIT_SET_Z)
+ return push_inst(compiler, MOV | SET_FLAGS | RD(TMP_REG2) | RM(dst_reg));
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_reg)
+{
+ sljit_ins cc, tmp, tmp2;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ if (src2_reg != dst_reg && src1 == dst_reg) {
+ src1 = src2_reg;
+ src1w = 0;
+ src2_reg = dst_reg;
+ if (!(type & SLJIT_COMPARE_SELECT))
+ type ^= 0x1;
+ }
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, (src2_reg != dst_reg) ? dst_reg : TMP_REG1, src1, src1w, TMP_REG1));
+
+ if (src2_reg != dst_reg) {
+ src1 = src2_reg;
+ src1w = 0;
+ if (!(type & SLJIT_COMPARE_SELECT))
+ type ^= 0x1;
+ } else {
+ src1 = TMP_REG1;
+ src1w = 0;
+ }
+ } else if (dst_reg != src2_reg)
+ FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM(src2_reg)));
+
+ if (type & SLJIT_COMPARE_SELECT)
+ type ^= 0x1;
+
+ cc = get_cc(compiler, type & ~(SLJIT_32 | SLJIT_COMPARE_SELECT));
+
+ if (SLJIT_UNLIKELY(src1 == SLJIT_IMM)) {
+ tmp = get_imm((sljit_uw)src1w);
+ if (tmp) {
+ if (type & SLJIT_COMPARE_SELECT)
+ FAIL_IF(push_inst(compiler, (CMP | SET_FLAGS | RN(dst_reg) | tmp)));
+ return push_inst(compiler, ((MOV | RD(dst_reg) | tmp) & ~COND_MASK) | cc);
+ }
+
+ tmp = get_imm(~(sljit_uw)src1w);
+ if (tmp && (type & SLJIT_COMPARE_SELECT)) {
+ tmp2 = get_imm((sljit_uw)-src1w);
+ if (tmp2)
+ FAIL_IF(push_inst(compiler, (CMN | SET_FLAGS | RN(dst_reg) | tmp2)));
+ else
+ tmp = 0;
+ }
+
+ if (tmp)
+ return push_inst(compiler, ((MVN | RD(dst_reg) | tmp) & ~COND_MASK) | cc);
+
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+ if (!(type & SLJIT_COMPARE_SELECT)) {
+ tmp = (sljit_ins)src1w;
+ FAIL_IF(push_inst(compiler, (MOVW & ~COND_MASK) | cc | RD(dst_reg) | ((tmp << 4) & 0xf0000) | (tmp & 0xfff)));
+ if (tmp <= 0xffff)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, (MOVT & ~COND_MASK) | cc | RD(dst_reg) | ((tmp >> 12) & 0xf0000) | ((tmp >> 16) & 0xfff));
+ }
+#endif /* SLJIT_CONFIG_ARM_V7 */
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
+ src1 = TMP_REG1;
+ }
+
+ if (type & SLJIT_COMPARE_SELECT)
+ FAIL_IF(push_inst(compiler, (CMP | SET_FLAGS | RN(dst_reg) | RM(src1))));
+
+ return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src1)) & ~COND_MASK) | cc);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_freg)
+{
+ sljit_ins cc;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ type ^= SLJIT_32;
+
+ if (dst_freg != src2_freg) {
+ if (dst_freg == src1) {
+ src1 = src2_freg;
+ src1w = 0;
+ type ^= 0x1;
+ } else
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, (type & SLJIT_32), dst_freg, src2_freg, 0)));
+ }
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (type & SLJIT_32) | FPU_LOAD, TMP_FREG2, src1, src1w));
+ src1 = TMP_FREG2;
+ }
+
+ cc = get_cc(compiler, type & ~SLJIT_32);
+ return push_inst(compiler, EMIT_FPU_OPERATION((VMOV_F32 & ~COND_MASK) | cc, (type & SLJIT_32), dst_freg, src1, 0));
+}
+
+#undef EMIT_FPU_OPERATION
+
+static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s32 max_offset)
+{
+ sljit_s32 arg = *mem;
+ sljit_sw argw = *memw;
+ sljit_uw imm, tmp;
+ sljit_sw mask = 0xfff;
+ sljit_sw sign = 0x1000;
+
+ SLJIT_ASSERT(max_offset >= 0xf00);
+
+ *mem = TMP_REG1;
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ *memw = 0;
+ return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_ins)(argw & 0x3) << 7));
+ }
+
+ arg &= REG_MASK;
+
+ if (arg) {
+ if (argw <= max_offset && argw >= -mask) {
+ *mem = arg;
+ return SLJIT_SUCCESS;
+ }
+
+ if (argw >= 0) {
+ tmp = (sljit_uw)(argw & (sign | mask));
+ tmp = (sljit_uw)((argw + ((tmp <= (sljit_uw)max_offset || tmp == (sljit_uw)sign) ? 0 : sign)) & ~mask);
+ imm = get_imm(tmp);
+
+ if (imm) {
+ *memw = argw - (sljit_sw)tmp;
+ SLJIT_ASSERT(*memw >= -mask && *memw <= max_offset);
+
+ return push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg) | imm);
+ }
+ } else {
+ tmp = (sljit_uw)(-argw & (sign | mask));
+ tmp = (sljit_uw)((-argw + ((tmp <= (sljit_uw)((sign << 1) - max_offset - 1)) ? 0 : sign)) & ~mask);
+ imm = get_imm(tmp);
+
+ if (imm) {
+ *memw = argw + (sljit_sw)tmp;
+ SLJIT_ASSERT(*memw >= -mask && *memw <= max_offset);
+
+ return push_inst(compiler, SUB | RD(TMP_REG1) | RN(arg) | imm);
+ }
+ }
+ }
+
+ tmp = (sljit_uw)(argw & (sign | mask));
+ tmp = (sljit_uw)((argw + ((tmp <= (sljit_uw)max_offset || tmp == (sljit_uw)sign) ? 0 : sign)) & ~mask);
+ *memw = argw - (sljit_sw)tmp;
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, tmp));
+
+ if (arg == 0)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, ADD | RD(TMP_REG1) | RN(TMP_REG1) | RM(arg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_s32 flags;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
+
+ if (!(reg & REG_PAIR_MASK))
+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
+
+ ADJUST_LOCAL_OFFSET(mem, memw);
+
+ FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
+
+ flags = WORD_SIZE;
+
+ if (!(type & SLJIT_MEM_STORE)) {
+ if (REG_PAIR_FIRST(reg) == (mem & REG_MASK)) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw), TMP_REG1));
+ return emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw, TMP_REG1);
+ }
+
+ flags = WORD_SIZE | LOAD_DATA;
+ }
+
+ FAIL_IF(emit_op_mem(compiler, flags, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw, TMP_REG1));
+ return emit_op_mem(compiler, flags, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), memw + SSIZE_OF(sw), TMP_REG1);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_s32 flags;
+ sljit_ins is_type1_transfer, inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));
+
+ is_type1_transfer = 1;
+
+ switch (type & 0xff) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ case SLJIT_MOV_P:
+ flags = WORD_SIZE;
+ break;
+ case SLJIT_MOV_U8:
+ flags = BYTE_SIZE;
+ break;
+ case SLJIT_MOV_S8:
+ if (!(type & SLJIT_MEM_STORE))
+ is_type1_transfer = 0;
+ flags = BYTE_SIZE | SIGNED;
+ break;
+ case SLJIT_MOV_U16:
+ is_type1_transfer = 0;
+ flags = HALF_SIZE;
+ break;
+ case SLJIT_MOV_S16:
+ is_type1_transfer = 0;
+ flags = HALF_SIZE | SIGNED;
+ break;
+ default:
+ SLJIT_UNREACHABLE();
+ flags = WORD_SIZE;
+ break;
+ }
+
+ if (!(type & SLJIT_MEM_STORE))
+ flags |= LOAD_DATA;
+
+ SLJIT_ASSERT(is_type1_transfer == !!IS_TYPE1_TRANSFER(flags));
+
+ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
+ if (!is_type1_transfer && memw != 0)
+ return SLJIT_ERR_UNSUPPORTED;
+ } else {
+ if (is_type1_transfer) {
+ if (memw > 4095 || memw < -4095)
+ return SLJIT_ERR_UNSUPPORTED;
+ } else if (memw > 255 || memw < -255)
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+
+ if (type & SLJIT_MEM_SUPP)
+ return SLJIT_SUCCESS;
+
+ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
+ memw &= 0x3;
+
+ inst = EMIT_DATA_TRANSFER(flags, 1, reg, mem & REG_MASK, RM(OFFS_REG(mem)) | ((sljit_ins)memw << 7));
+
+ if (is_type1_transfer)
+ inst |= (1 << 25);
+
+ if (type & SLJIT_MEM_POST)
+ inst ^= (1 << 24);
+ else
+ inst |= (1 << 21);
+
+ return push_inst(compiler, inst);
+ }
+
+ inst = EMIT_DATA_TRANSFER(flags, 0, reg, mem & REG_MASK, 0);
+
+ if (type & SLJIT_MEM_POST)
+ inst ^= (1 << 24);
+ else
+ inst |= (1 << 21);
+
+ if (is_type1_transfer) {
+ if (memw >= 0)
+ inst |= (1 << 23);
+ else
+ memw = -memw;
+
+ return push_inst(compiler, inst | (sljit_ins)memw);
+ }
+
+ if (memw >= 0)
+ inst |= (1 << 23);
+ else
+ memw = -memw;
+
+ return push_inst(compiler, inst | TYPE2_TRANSFER_IMM((sljit_ins)memw));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 freg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
+
+ if (type & SLJIT_MEM_ALIGNED_32)
+ return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw);
+
+ if (type & SLJIT_MEM_STORE) {
+ FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | RD(TMP_REG2)));
+
+ if (type & SLJIT_32)
+ return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1);
+
+ FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
+ mem |= SLJIT_MEM;
+
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1));
+ FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(freg) | 0x80 | RD(TMP_REG2)));
+ return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw + 4, TMP_REG1);
+ }
+
+ if (type & SLJIT_32) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, mem, memw, TMP_REG1));
+ return push_inst(compiler, VMOV | VN(freg) | RD(TMP_REG2));
+ }
+
+ FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
+ mem |= SLJIT_MEM;
+
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, mem, memw, TMP_REG1));
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, mem, memw + 4, TMP_REG1));
+ return push_inst(compiler, VMOV2 | VM(freg) | RD(TMP_REG2) | RN(TMP_REG1));
+}
+
+static sljit_s32 sljit_emit_simd_mem_offset(struct sljit_compiler *compiler, sljit_s32 *mem_ptr, sljit_sw memw)
+{
+ sljit_s32 mem = *mem_ptr;
+ sljit_uw imm;
+
+ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
+ *mem_ptr = TMP_REG1;
+ return push_inst(compiler, ADD | RD(TMP_REG1) | RN(mem & REG_MASK) | RM(OFFS_REG(mem)) | ((sljit_ins)(memw & 0x3) << 7));
+ }
+
+ if (SLJIT_UNLIKELY(!(mem & REG_MASK))) {
+ *mem_ptr = TMP_REG1;
+ return load_immediate(compiler, TMP_REG1, (sljit_uw)memw);
+ }
+
+ mem &= REG_MASK;
+
+ if (memw == 0) {
+ *mem_ptr = mem;
+ return SLJIT_SUCCESS;
+ }
+
+ *mem_ptr = TMP_REG1;
+ imm = get_imm((sljit_uw)(memw < 0 ? -memw : memw));
+
+ if (imm != 0)
+ return push_inst(compiler, ((memw < 0) ? SUB : ADD) | RD(TMP_REG1) | RN(mem) | imm);
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));
+ return push_inst(compiler, ADD | RD(TMP_REG1) | RN(TMP_REG1) | RM(mem));
+}
+
+static SLJIT_INLINE sljit_s32 simd_get_quad_reg_index(sljit_s32 freg)
+{
+ freg += freg & 0x1;
+
+ SLJIT_ASSERT((freg_map[freg] & 0x1) == (freg <= SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS));
+
+ if (freg <= SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS)
+ freg--;
+
+ return freg;
+}
+
+#define SLJIT_QUAD_OTHER_HALF(freg) ((((freg) & 0x1) << 1) - 1)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw));
+
+ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (reg_size == 4)
+ vreg = simd_get_quad_reg_index(vreg);
+
+ if (!(srcdst & SLJIT_MEM)) {
+ if (reg_size == 4)
+ srcdst = simd_get_quad_reg_index(srcdst);
+
+ if (type & SLJIT_SIMD_STORE)
+ ins = VD(srcdst) | VN(vreg) | VM(vreg);
+ else
+ ins = VD(vreg) | VN(srcdst) | VM(srcdst);
+
+ if (reg_size == 4)
+ ins |= (sljit_ins)1 << 6;
+
+ return push_inst(compiler, VORR | ins);
+ }
+
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));
+
+ if (elem_size > 3)
+ elem_size = 3;
+
+ ins = ((type & SLJIT_SIMD_STORE) ? VST1 : VLD1) | VD(vreg)
+ | (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8));
+
+ SLJIT_ASSERT(reg_size >= alignment);
+
+ if (alignment == 3)
+ ins |= 0x10;
+ else if (alignment >= 3)
+ ins |= 0x20;
+
+ return push_inst(compiler, ins | RN(srcdst) | ((sljit_ins)elem_size) << 6 | 0xf);
+}
+
+static sljit_ins simd_get_imm(sljit_s32 elem_size, sljit_uw value)
+{
+ sljit_ins result;
+
+ if (elem_size > 1 && (sljit_u16)value == (value >> 16)) {
+ elem_size = 1;
+ value = (sljit_u16)value;
+ }
+
+ if (elem_size == 1 && (sljit_u8)value == (value >> 8)) {
+ elem_size = 0;
+ value = (sljit_u8)value;
+ }
+
+ switch (elem_size) {
+ case 0:
+ SLJIT_ASSERT(value <= 0xff);
+ result = 0xe00;
+ break;
+ case 1:
+ SLJIT_ASSERT(value <= 0xffff);
+ result = 0;
+
+ while (1) {
+ if (value <= 0xff) {
+ result |= 0x800;
+ break;
+ }
+
+ if ((value & 0xff) == 0) {
+ value >>= 8;
+ result |= 0xa00;
+ break;
+ }
+
+ if (result != 0)
+ return ~(sljit_ins)0;
+
+ value ^= (sljit_uw)0xffff;
+ result = (1 << 5);
+ }
+ break;
+ default:
+ SLJIT_ASSERT(value <= 0xffffffff);
+ result = 0;
+
+ while (1) {
+ if (value <= 0xff) {
+ result |= 0x000;
+ break;
+ }
+
+ if ((value & ~(sljit_uw)0xff00) == 0) {
+ value >>= 8;
+ result |= 0x200;
+ break;
+ }
+
+ if ((value & ~(sljit_uw)0xff0000) == 0) {
+ value >>= 16;
+ result |= 0x400;
+ break;
+ }
+
+ if ((value & ~(sljit_uw)0xff000000) == 0) {
+ value >>= 24;
+ result |= 0x600;
+ break;
+ }
+
+ if ((value & (sljit_uw)0xff) == 0xff && (value >> 16) == 0) {
+ value >>= 8;
+ result |= 0xc00;
+ break;
+ }
+
+ if ((value & (sljit_uw)0xffff) == 0xffff && (value >> 24) == 0) {
+ value >>= 16;
+ result |= 0xd00;
+ break;
+ }
+
+ if (result != 0)
+ return ~(sljit_ins)0;
+
+ value = ~value;
+ result = (1 << 5);
+ }
+ break;
+ }
+
+ return ((sljit_ins)value & 0xf) | (((sljit_ins)value & 0x70) << 12) | (((sljit_ins)value & 0x80) << 17) | result;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins, imm;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw));
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (reg_size == 4)
+ vreg = simd_get_quad_reg_index(vreg);
+
+ if (src == SLJIT_IMM && srcw == 0)
+ return push_inst(compiler, VMOV_i | ((reg_size == 4) ? (1 << 6) : 0) | VD(vreg));
+
+ if (SLJIT_UNLIKELY(elem_size == 3)) {
+ SLJIT_ASSERT(type & SLJIT_SIMD_FLOAT);
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD | SLJIT_32, vreg, src, srcw));
+ src = vreg;
+ } else if (vreg != src)
+ FAIL_IF(push_inst(compiler, VORR | VD(vreg) | VN(src) | VM(src)));
+
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+
+ if (vreg != src)
+ return push_inst(compiler, VORR | VD(vreg) | VN(src) | VM(src));
+ return SLJIT_SUCCESS;
+ }
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));
+
+ ins = (sljit_ins)(elem_size << 6);
+
+ if (reg_size == 4)
+ ins |= (sljit_ins)1 << 5;
+
+ return push_inst(compiler, VLD1_r | ins | VD(vreg) | RN(src) | 0xf);
+ }
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ SLJIT_ASSERT(elem_size == 2);
+ ins = ((sljit_ins)freg_ebit_map[src] << (16 + 2 + 1)) | ((sljit_ins)1 << (16 + 2));
+
+ if (reg_size == 4)
+ ins |= (sljit_ins)1 << 6;
+
+ return push_inst(compiler, VDUP_s | ins | VD(vreg) | (sljit_ins)freg_map[src]);
+ }
+
+ if (src == SLJIT_IMM) {
+ if (elem_size < 2)
+ srcw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1;
+
+ imm = simd_get_imm(elem_size, (sljit_uw)srcw);
+
+ if (imm != ~(sljit_ins)0) {
+ if (reg_size == 4)
+ imm |= (sljit_ins)1 << 6;
+
+ return push_inst(compiler, VMOV_i | imm | VD(vreg));
+ }
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));
+ src = TMP_REG1;
+ }
+
+ switch (elem_size) {
+ case 0:
+ ins = 1 << 22;
+ break;
+ case 1:
+ ins = 1 << 5;
+ break;
+ default:
+ ins = 0;
+ break;
+ }
+
+ if (reg_size == 4)
+ ins |= (sljit_ins)1 << 21;
+
+ return push_inst(compiler, VDUP | ins | VN(vreg) | RD(src));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg, sljit_s32 lane_index,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw));
+
+ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (reg_size == 4)
+ vreg = simd_get_quad_reg_index(vreg);
+
+ if (type & SLJIT_SIMD_LANE_ZERO) {
+ ins = (reg_size == 3) ? 0 : ((sljit_ins)1 << 6);
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (elem_size == 3 && !(srcdst & SLJIT_MEM)) {
+ if (lane_index == 1)
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+
+ if (srcdst != vreg)
+ FAIL_IF(push_inst(compiler, VORR | VD(vreg) | VN(srcdst) | VM(srcdst)));
+
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+ return push_inst(compiler, VMOV_i | VD(vreg));
+ }
+
+ if (srcdst == vreg || (elem_size == 3 && srcdst == (vreg + SLJIT_QUAD_OTHER_HALF(vreg)))) {
+ FAIL_IF(push_inst(compiler, VORR | ins | VD(TMP_FREG2) | VN(vreg) | VM(vreg)));
+ srcdst = TMP_FREG2;
+ srcdstw = 0;
+ }
+ }
+
+ FAIL_IF(push_inst(compiler, VMOV_i | ins | VD(vreg)));
+ }
+
+ if (reg_size == 4 && lane_index >= (0x8 >> elem_size)) {
+ lane_index -= (0x8 >> elem_size);
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+ }
+
+ if (srcdst & SLJIT_MEM) {
+ if (elem_size == 3)
+ return emit_fop_mem(compiler, ((type & SLJIT_SIMD_STORE) ? 0 : FPU_LOAD) | SLJIT_32, vreg, srcdst, srcdstw);
+
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));
+
+ lane_index = lane_index << elem_size;
+ ins = (sljit_ins)((elem_size << 10) | (lane_index << 5));
+ return push_inst(compiler, ((type & SLJIT_SIMD_STORE) ? VST1_s : VLD1_s) | ins | VD(vreg) | RN(srcdst) | 0xf);
+ }
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (elem_size == 3) {
+ if (type & SLJIT_SIMD_STORE)
+ return push_inst(compiler, VORR | VD(srcdst) | VN(vreg) | VM(vreg));
+ return push_inst(compiler, VMOV_F32 | SLJIT_32 | VD(vreg) | VM(srcdst));
+ }
+
+ if (type & SLJIT_SIMD_STORE) {
+ if (freg_ebit_map[vreg] == 0) {
+ if (lane_index == 1)
+ vreg = SLJIT_F64_SECOND(vreg);
+
+ return push_inst(compiler, VMOV_F32 | VD(srcdst) | VM(vreg));
+ }
+
+ FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | ((sljit_ins)lane_index << 21) | VN(vreg) | RD(TMP_REG1)));
+ return push_inst(compiler, VMOV | VN(srcdst) | RD(TMP_REG1));
+ }
+
+ FAIL_IF(push_inst(compiler, VMOV | (1 << 20) | VN(srcdst) | RD(TMP_REG1)));
+ return push_inst(compiler, VMOV_s | ((sljit_ins)lane_index << 21) | VN(vreg) | RD(TMP_REG1));
+ }
+
+ if (srcdst == SLJIT_IMM) {
+ if (elem_size < 2)
+ srcdstw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1;
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcdstw));
+ srcdst = TMP_REG1;
+ }
+
+ if (elem_size == 0)
+ ins = 0x400000;
+ else if (elem_size == 1)
+ ins = 0x20;
+ else
+ ins = 0;
+
+ lane_index = lane_index << elem_size;
+ ins |= (sljit_ins)(((lane_index & 0x4) << 19) | ((lane_index & 0x3) << 5));
+
+ if (type & SLJIT_SIMD_STORE) {
+ ins |= (1 << 20);
+
+ if (elem_size < 2 && !(type & SLJIT_SIMD_LANE_SIGNED))
+ ins |= (1 << 23);
+ }
+
+ return push_inst(compiler, VMOV_s | ins | VN(vreg) | RD(srcdst));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_s32 src_lane_index)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index));
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (reg_size == 4) {
+ vreg = simd_get_quad_reg_index(vreg);
+ src = simd_get_quad_reg_index(src);
+
+ if (src_lane_index >= (0x8 >> elem_size)) {
+ src_lane_index -= (0x8 >> elem_size);
+ src += SLJIT_QUAD_OTHER_HALF(src);
+ }
+ }
+
+ if (elem_size == 3) {
+ if (vreg != src)
+ FAIL_IF(push_inst(compiler, VORR | VD(vreg) | VN(src) | VM(src)));
+
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+
+ if (vreg != src)
+ return push_inst(compiler, VORR | VD(vreg) | VN(src) | VM(src));
+ return SLJIT_SUCCESS;
+ }
+
+ ins = ((((sljit_ins)src_lane_index << 1) | 1) << (16 + elem_size));
+
+ if (reg_size == 4)
+ ins |= (sljit_ins)1 << 6;
+
+ return push_inst(compiler, VDUP_s | ins | VD(vreg) | VM(src));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);
+ sljit_s32 dst_reg;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw));
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size != 2 || elem2_size != 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (reg_size == 4)
+ vreg = simd_get_quad_reg_index(vreg);
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));
+ if (reg_size == 4 && elem2_size - elem_size == 1)
+ FAIL_IF(push_inst(compiler, VLD1 | (0x7 << 8) | VD(vreg) | RN(src) | 0xf));
+ else
+ FAIL_IF(push_inst(compiler, VLD1_s | (sljit_ins)((reg_size - elem2_size + elem_size) << 10) | VD(vreg) | RN(src) | 0xf));
+ src = vreg;
+ } else if (reg_size == 4)
+ src = simd_get_quad_reg_index(src);
+
+ if (!(type & SLJIT_SIMD_FLOAT)) {
+ dst_reg = (reg_size == 4) ? vreg : TMP_FREG2;
+
+ do {
+ FAIL_IF(push_inst(compiler, VSHLL | ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0 : (1 << 24))
+ | ((sljit_ins)1 << (19 + elem_size)) | VD(dst_reg) | VM(src)));
+ src = dst_reg;
+ } while (++elem_size < elem2_size);
+
+ if (dst_reg == TMP_FREG2)
+ return push_inst(compiler, VORR | VD(vreg) | VN(TMP_FREG2) | VM(TMP_FREG2));
+ return SLJIT_SUCCESS;
+ }
+
+ /* No SIMD variant, must use VFP instead. */
+ SLJIT_ASSERT(reg_size == 4);
+
+ if (vreg == src) {
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+ FAIL_IF(push_inst(compiler, VCVT_F64_F32 | VD(vreg) | VM(src) | 0x20));
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+ return push_inst(compiler, VCVT_F64_F32 | VD(vreg) | VM(src));
+ }
+
+ FAIL_IF(push_inst(compiler, VCVT_F64_F32 | VD(vreg) | VM(src)));
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+ return push_inst(compiler, VCVT_F64_F32 | VD(vreg) | VM(src) | 0x20);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins, imms;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw));
+
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ switch (elem_size) {
+ case 0:
+ imms = 0x243219;
+ ins = VSHR | (1 << 24) | (0x9 << 16);
+ break;
+ case 1:
+ imms = (reg_size == 4) ? 0x243219 : 0x2231;
+ ins = VSHR | (1 << 24) | (0x11 << 16);
+ break;
+ case 2:
+ imms = (reg_size == 4) ? 0x2231 : 0x21;
+ ins = VSHR | (1 << 24) | (0x21 << 16);
+ break;
+ default:
+ imms = 0x21;
+ ins = VSHR | (1 << 24) | (0x1 << 16) | (1 << 7);
+ break;
+ }
+
+ if (reg_size == 4) {
+ vreg = simd_get_quad_reg_index(vreg);
+ ins |= (sljit_ins)1 << 6;
+ }
+
+ SLJIT_ASSERT((freg_map[TMP_FREG2] & 0x1) == 0);
+ FAIL_IF(push_inst(compiler, ins | VD(TMP_FREG2) | VM(vreg)));
+
+ if (reg_size == 4 && elem_size > 0)
+ FAIL_IF(push_inst(compiler, VMOVN | ((sljit_ins)(elem_size - 1) << 18) | VD(TMP_FREG2) | VM(TMP_FREG2)));
+
+ ins = (reg_size == 4 && elem_size == 0) ? (1 << 6) : 0;
+
+ while (imms >= 0x100) {
+ FAIL_IF(push_inst(compiler, VSRA | (1 << 24) | ins | ((imms & 0xff) << 16) | VD(TMP_FREG2) | VM(TMP_FREG2)));
+ imms >>= 8;
+ }
+
+ FAIL_IF(push_inst(compiler, VSRA | (1 << 24) | ins | (1 << 7) | (imms << 16) | VD(TMP_FREG2) | VM(TMP_FREG2)));
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | (1 << 23) | (0x2 << 21) | RD(dst_r) | VN(TMP_FREG2)));
+
+ if (reg_size == 4 && elem_size == 0) {
+ SLJIT_ASSERT(freg_map[TMP_FREG2] + 1 == freg_map[TMP_FREG1]);
+ FAIL_IF(push_inst(compiler, VMOV_s | (1 << 20) | (1 << 23) | (0x2 << 21) | RD(TMP_REG2) | VN(TMP_FREG1)));
+ FAIL_IF(push_inst(compiler, ORR | RD(dst_r) | RN(dst_r) | RM(TMP_REG2) | (0x8 << 7)));
+ }
+
+ if (dst_r == TMP_REG1)
+ return emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 alignment;
+ sljit_ins ins = 0, load_ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ switch (SLJIT_SIMD_GET_OPCODE(type)) {
+ case SLJIT_SIMD_OP2_AND:
+ ins = VAND;
+ break;
+ case SLJIT_SIMD_OP2_OR:
+ ins = VORR;
+ break;
+ case SLJIT_SIMD_OP2_XOR:
+ ins = VEOR;
+ break;
+ case SLJIT_SIMD_OP2_SHUFFLE:
+ ins = VTBL;
+ break;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ if (elem_size > 3)
+ elem_size = 3;
+
+ load_ins = VLD1 | (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8));
+ alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);
+
+ SLJIT_ASSERT(reg_size >= alignment);
+
+ if (alignment == 3)
+ load_ins |= 0x10;
+ else if (alignment >= 4)
+ load_ins |= 0x20;
+
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src2, src2w));
+ FAIL_IF(push_inst(compiler, load_ins | VD(TMP_FREG2) | RN(src2) | ((sljit_ins)elem_size) << 6 | 0xf));
+ src2 = TMP_FREG2;
+ }
+
+ if (reg_size == 4) {
+ dst_vreg = simd_get_quad_reg_index(dst_vreg);
+ src1_vreg = simd_get_quad_reg_index(src1_vreg);
+ src2 = simd_get_quad_reg_index(src2);
+
+ if (SLJIT_SIMD_GET_OPCODE(type) == SLJIT_SIMD_OP2_SHUFFLE) {
+ ins |= (sljit_ins)1 << 8;
+
+ FAIL_IF(push_inst(compiler, ins | VD(dst_vreg != src1_vreg ? dst_vreg : TMP_FREG2) | VN(src1_vreg) | VM(src2)));
+ src2 += SLJIT_QUAD_OTHER_HALF(src2);
+ FAIL_IF(push_inst(compiler, ins | VD(dst_vreg + SLJIT_QUAD_OTHER_HALF(dst_vreg)) | VN(src1_vreg) | VM(src2)));
+
+ if (dst_vreg == src1_vreg)
+ return push_inst(compiler, VORR | VD(dst_vreg) | VN(TMP_FREG2) | VM(TMP_FREG2));
+ return SLJIT_SUCCESS;
+ }
+
+ ins |= (sljit_ins)1 << 6;
+ }
+
+ return push_inst(compiler, ins | VD(dst_vreg) | VN(src1_vreg) | VM(src2));
+}
+
+#undef FPU_LOAD
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 mem_reg)
+{
+ sljit_u32 ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));
+
+ if (op & SLJIT_ATOMIC_USE_CAS)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_S8:
+ case SLJIT_MOV_S16:
+ case SLJIT_MOV_S32:
+ return SLJIT_ERR_UNSUPPORTED;
+
+ case SLJIT_MOV_U8:
+ ins = LDREXB;
+ break;
+ case SLJIT_MOV_U16:
+ ins = LDREXH;
+ break;
+ default:
+ ins = LDREX;
+ break;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, ins | RN(mem_reg) | RD(dst_reg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src_reg,
+ sljit_s32 mem_reg,
+ sljit_s32 temp_reg)
+{
+ sljit_u32 ins;
+
+ /* temp_reg == mem_reg is undefined so use another temp register */
+ SLJIT_UNUSED_ARG(temp_reg);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));
+
+ if (op & SLJIT_ATOMIC_USE_CAS)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_S8:
+ case SLJIT_MOV_S16:
+ case SLJIT_MOV_S32:
+ return SLJIT_ERR_UNSUPPORTED;
+
+ case SLJIT_MOV_U8:
+ ins = STREXB;
+ break;
+ case SLJIT_MOV_U16:
+ ins = STREXH;
+ break;
+ default:
+ ins = STREX;
+ break;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst(compiler, ins | RN(mem_reg) | RD(TMP_REG1) | RM(src_reg)));
+ if (op & SLJIT_SET_ATOMIC_STORED)
+ return push_inst(compiler, CMP | SET_FLAGS | SRC2_IMM | RN(TMP_REG1));
+
+ return SLJIT_SUCCESS;
+}
+
+#define SLJIT_EMIT_CONST_U8(c) \
+ (((c) & 0x100) != 0 ? (MVN | SRC2_IMM | (~(c) & 0xff)) : (MOV | SRC2_IMM | ((c) & 0xff)))
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
+{
+ struct sljit_const *const_;
+ sljit_s32 dst_r;
+ sljit_s32 mem_flags = WORD_SIZE;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+ PTR_FAIL_IF(!const_);
+ set_const(const_, compiler);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (GET_OPCODE(op) == SLJIT_MOV_U8) {
+ PTR_FAIL_IF(push_inst(compiler, SLJIT_EMIT_CONST_U8(init_value) | RD(dst_r)));
+ mem_flags = BYTE_SIZE;
+ } else {
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler,
+ EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), (sljit_ins)init_value));
+ compiler->patches++;
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ PTR_FAIL_IF(emit_imm(compiler, dst_r, init_value));
+#endif /* SLJIT_CONFIG_ARM_V6 */
+ }
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, dst, dstw, TMP_REG1));
+
+ return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_jump *jump;
+ sljit_s32 dst_r, target_r;
+ SLJIT_UNUSED_ARG(op);
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = TMP_REG1;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, dst, dstw, TMP_REG1));
+ }
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, target_r, TMP_PC, 0), 0));
+ compiler->patches++;
+#else /* !SLJIT_CONFIG_ARM_V6 */
+ PTR_FAIL_IF(push_inst(compiler, RD(target_r)));
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_mov_addr(jump, compiler, 1);
+
+#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+ compiler->size += 1;
+#endif /* SLJIT_CONFIG_ARM_V7 */
+
+ if (op == SLJIT_ADD_ABS_ADDR)
+ PTR_FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RN(dst_r) | RM(TMP_REG1)));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
+{
+ set_jump_addr(addr, executable_offset, new_target, 1);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
+{
+ sljit_ins *inst;
+
+ if (GET_OPCODE(op) != SLJIT_MOV_U8) {
+ set_const_value(addr, executable_offset, (sljit_uw)new_constant, 1);
+ return;
+ }
+
+ inst = (sljit_ins*)addr;
+ SLJIT_ASSERT((inst[0] & 0xfff00000) == (MOV | SRC2_IMM) || (inst[0] & 0xfff00000) == (MVN | SRC2_IMM));
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
+ *inst = SLJIT_EMIT_CONST_U8(new_constant) | (*inst & 0xf000);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
+}
diff --git a/deps/sljit/sljit_src/sljitNativeARM_64.c b/deps/sljit/sljit_src/sljitNativeARM_64.c
new file mode 100644
index 0000000..06d94a9
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativeARM_64.c
@@ -0,0 +1,3805 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef __ARM_FEATURE_ATOMICS
+#define ARM_ATOMIC_INFO " (LSE)"
+#else
+#define ARM_ATOMIC_INFO ""
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
+{
+ return "ARM-64" ARM_ATOMIC_INFO SLJIT_CPUINFO;
+}
+
+/* Length of an instruction word */
+typedef sljit_u32 sljit_ins;
+
+#define TMP_ZERO (0)
+
+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
+#define TMP_LR (SLJIT_NUMBER_OF_REGISTERS + 4)
+#define TMP_FP (SLJIT_NUMBER_OF_REGISTERS + 5)
+
+#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
+
+/* r18 - platform register, currently not used */
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = {
+ 31, 0, 1, 2, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 17, 8, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 31, 9, 10, 30, 29
+};
+
+static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 15, 14, 13, 12, 11, 10, 9, 8, 30, 31
+};
+
+#define W_OP ((sljit_ins)1 << 31)
+#define RD(rd) ((sljit_ins)reg_map[rd])
+#define RT(rt) ((sljit_ins)reg_map[rt])
+#define RN(rn) ((sljit_ins)reg_map[rn] << 5)
+#define RT2(rt2) ((sljit_ins)reg_map[rt2] << 10)
+#define RM(rm) ((sljit_ins)reg_map[rm] << 16)
+#define VD(vd) ((sljit_ins)freg_map[vd])
+#define VT(vt) ((sljit_ins)freg_map[vt])
+#define VT2(vt) ((sljit_ins)freg_map[vt] << 10)
+#define VN(vn) ((sljit_ins)freg_map[vn] << 5)
+#define VM(vm) ((sljit_ins)freg_map[vm] << 16)
+
+/* --------------------------------------------------------------------- */
+/* Instruction forms */
+/* --------------------------------------------------------------------- */
+
+#define ADC 0x9a000000
+#define ADD 0x8b000000
+#define ADDE 0x8b200000
+#define ADDI 0x91000000
+#define ADR 0x10000000
+#define ADRP 0x90000000
+#define AND 0x8a000000
+#define ANDI 0x92000000
+#define AND_v 0x0e201c00
+#define ASRV 0x9ac02800
+#define B 0x14000000
+#define B_CC 0x54000000
+#define BL 0x94000000
+#define BLR 0xd63f0000
+#define BR 0xd61f0000
+#define BRK 0xd4200000
+#define CAS 0xc8a07c00
+#define CASB 0x08a07c00
+#define CASH 0x48a07c00
+#define CBZ 0xb4000000
+#define CCMPI 0xfa400800
+#define CLZ 0xdac01000
+#define CSEL 0x9a800000
+#define CSINC 0x9a800400
+#define CSINV 0xda800000
+#define DMB_SY 0xd5033fbf
+#define DUP_e 0x0e000400
+#define DUP_g 0x0e000c00
+#define EOR 0xca000000
+#define EOR_v 0x2e201c00
+#define EORI 0xd2000000
+#define EXTR 0x93c00000
+#define FABS 0x1e60c000
+#define FADD 0x1e602800
+#define FCMP 0x1e602000
+#define FCSEL 0x1e600c00
+#define FCVT 0x1e224000
+#define FCVTL 0x0e217800
+#define FCVTZS 0x9e780000
+#define FDIV 0x1e601800
+#define FMOV 0x1e604000
+#define FMOV_R 0x9e660000
+#define FMOV_I 0x1e601000
+#define FMUL 0x1e600800
+#define FNEG 0x1e614000
+#define FSUB 0x1e603800
+#define INS 0x4e001c00
+#define INS_e 0x6e000400
+#define LD1 0x0c407000
+#define LD1_s 0x0d400000
+#define LD1R 0x0d40c000
+#define LDRI 0xf9400000
+#define LDRI_F64 0xfd400000
+#define LDRI_POST 0xf8400400
+#define LDP 0xa9400000
+#define LDP_F64 0x6d400000
+#define LDP_POST 0xa8c00000
+#define LDR_PRE 0xf8400c00
+#define LDXR 0xc85f7c00
+#define LDXRB 0x085f7c00
+#define LDXRH 0x485f7c00
+#define LSLV 0x9ac02000
+#define LSRV 0x9ac02400
+#define MADD 0x9b000000
+#define MOVI 0x0f000400
+#define MOVK 0xf2800000
+#define MOVN 0x92800000
+#define MOVZ 0xd2800000
+#define NOP 0xd503201f
+#define ORN 0xaa200000
+#define ORR 0xaa000000
+#define ORR_v 0x0ea01c00
+#define ORRI 0xb2000000
+#define RBIT 0xdac00000
+#define RET 0xd65f0000
+#define REV 0xdac00c00
+#define REV16 0xdac00400
+#define RORV 0x9ac02c00
+#define SBC 0xda000000
+#define SBFM 0x93400000
+#define SCVTF 0x9e620000
+#define SDIV 0x9ac00c00
+#define SMADDL 0x9b200000
+#define SMOV 0x0e002c00
+#define SMULH 0x9b407c00
+#define SSHLL 0x0f00a400
+#define ST1 0x0c007000
+#define ST1_s 0x0d000000
+#define STP 0xa9000000
+#define STP_F64 0x6d000000
+#define STP_PRE 0xa9800000
+#define STRB 0x38206800
+#define STRBI 0x39000000
+#define STRI 0xf9000000
+#define STRI_F64 0xfd000000
+#define STR_FI 0x3d000000
+#define STR_FR 0x3c206800
+#define STUR_FI 0x3c000000
+#define STURBI 0x38000000
+#define STXR 0xc8007c00
+#define STXRB 0x08007c00
+#define STXRH 0x48007c00
+#define SUB 0xcb000000
+#define SUBI 0xd1000000
+#define SUBS 0xeb000000
+#define TBZ 0x36000000
+#define TBL_v 0x0e000000
+#define UBFM 0xd3400000
+#define UCVTF 0x9e630000
+#define UDIV 0x9ac00800
+#define UMOV 0x0e003c00
+#define UMULH 0x9bc07c00
+#define USHLL 0x2f00a400
+#define USHR 0x2f000400
+#define USRA 0x2f001400
+#define XTN 0x0e212800
+
+#define CSET (CSINC | RM(TMP_ZERO) | RN(TMP_ZERO))
+#define LDR (STRI | (1 << 22))
+#define LDRB (STRBI | (1 << 22))
+#define LDRH (LDRB | (1 << 30))
+#define MOV (ORR | RN(TMP_ZERO))
+
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
+{
+ sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ *ptr = ins;
+ compiler->size++;
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 emit_imm64_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm)
+{
+ FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((sljit_ins)(imm & 0xffff) << 5)));
+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)(imm >> 16) & 0xffff) << 5) | (1 << 21)));
+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)(imm >> 32) & 0xffff) << 5) | (2 << 21)));
+ return push_inst(compiler, MOVK | RD(dst) | ((sljit_ins)(imm >> 48) << 5) | (3 << 21));
+}
+
+static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
+{
+ sljit_sw diff;
+ sljit_uw target_addr;
+ sljit_uw jump_addr = (sljit_uw)code_ptr;
+ sljit_uw orig_addr = jump->addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ jump->addr = jump_addr;
+ if (jump->flags & SLJIT_REWRITABLE_JUMP)
+ goto exit;
+
+ if (jump->flags & JUMP_ADDR)
+ target_addr = jump->u.target;
+ else {
+ SLJIT_ASSERT(jump->u.label != NULL);
+ target_addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
+
+ if (jump->u.label->size > orig_addr)
+ jump_addr = (sljit_uw)(code + orig_addr);
+ }
+
+ diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);
+
+ if (jump->flags & IS_COND) {
+ diff += SSIZE_OF(ins);
+ if (diff <= 0xfffff && diff >= -0x100000) {
+ *(--code_ptr) ^= (jump->flags & IS_CBZ) ? (0x1 << 24) : 0x1;
+ jump->flags |= PATCH_COND;
+ jump->addr -= sizeof(sljit_ins);
+ return code_ptr;
+ }
+ diff -= SSIZE_OF(ins);
+ }
+
+ if (diff <= 0x7ffffff && diff >= -0x8000000) {
+ if (jump->flags & IS_COND)
+ code_ptr[-1] -= (4 << 5);
+ jump->flags |= PATCH_B;
+ return code_ptr;
+ }
+
+ if (target_addr < 0x100000000l) {
+ if (jump->flags & IS_COND)
+ code_ptr[-1] -= (2 << 5);
+ code_ptr[2] = code_ptr[0];
+ return code_ptr + 2;
+ }
+
+ if (diff <= 0xfffff000l && diff >= -0x100000000l) {
+ if (jump->flags & IS_COND)
+ code_ptr[-1] -= (2 << 5);
+ jump->flags |= PATCH_B32;
+ code_ptr[2] = code_ptr[0];
+ return code_ptr + 2;
+ }
+
+ if (target_addr < 0x1000000000000l) {
+ if (jump->flags & IS_COND)
+ code_ptr[-1] -= (1 << 5);
+ jump->flags |= PATCH_ABS48;
+ code_ptr[3] = code_ptr[0];
+ return code_ptr + 3;
+ }
+
+exit:
+ jump->flags |= PATCH_ABS64;
+ code_ptr[4] = code_ptr[0];
+ return code_ptr + 4;
+}
+
+static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
+{
+ sljit_uw addr;
+ sljit_uw jump_addr = (sljit_uw)code_ptr;
+ sljit_sw diff;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_ASSERT(jump->flags < ((sljit_uw)4 << JUMP_SIZE_SHIFT));
+ if (jump->flags & JUMP_ADDR)
+ addr = jump->u.target;
+ else {
+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
+
+ if (jump->u.label->size > jump->addr)
+ jump_addr = (sljit_uw)(code + jump->addr);
+ }
+
+ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);
+
+ if (diff <= 0xfffff && diff >= -0x100000) {
+ jump->flags |= PATCH_B;
+ return 0;
+ }
+
+ if (diff <= 0xfffff000l && diff >= -0x100000000l) {
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
+ jump->flags |= PATCH_B32;
+ return 1;
+ }
+
+ if (addr < 0x100000000l) {
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
+ return 1;
+ }
+
+ if (addr < 0x1000000000000l) {
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)2 << JUMP_SIZE_SHIFT));
+ jump->flags |= PATCH_ABS48;
+ return 2;
+ }
+
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));
+ jump->flags |= PATCH_ABS64;
+ return 3;
+}
+
+static SLJIT_INLINE void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset)
+{
+ sljit_sw addr = (sljit_sw)((jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr);
+ sljit_ins* buf_ptr = (sljit_ins*)jump->addr;
+ sljit_u32 dst;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+ if (jump->flags & PATCH_COND) {
+ addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
+ SLJIT_ASSERT(addr <= 0x3ffff && addr >= -0x40000);
+ buf_ptr[0] = (buf_ptr[0] & ~(sljit_ins)0xffffe0) | (sljit_ins)((addr & 0x7ffff) << 5);
+ return;
+ }
+
+ if (jump->flags & PATCH_B) {
+ addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
+ SLJIT_ASSERT(addr <= 0x1ffffff && addr >= -0x2000000);
+ buf_ptr[0] = ((jump->flags & IS_BL) ? BL : B) | (sljit_ins)(addr & 0x3ffffff);
+ return;
+ }
+
+ dst = (buf_ptr[0] >> 5) & 0x1f;
+
+ if (jump->flags & PATCH_B32) {
+ addr -= (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) & ~(sljit_sw)0xfff;
+ SLJIT_ASSERT(addr <= 0xfffff000l && addr >= -0x100000000l);
+ buf_ptr[0] = ADRP | (((sljit_ins)(addr >> 12) & 0x3) << 29) | (((sljit_ins)(addr >> 14) & 0x7ffff) << 5) | dst;
+ buf_ptr[1] = ADDI | dst | (dst << 5) | ((sljit_ins)(addr & 0xfff) << 10);
+ return;
+ }
+ } else {
+ dst = *buf_ptr;
+
+ if (jump->flags & PATCH_B) {
+ addr -= (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
+ SLJIT_ASSERT(addr <= 0xfffff && addr >= -0x100000);
+ buf_ptr[0] = ADR | (((sljit_ins)addr & 0x3) << 29) | (((sljit_ins)(addr >> 2) & 0x7ffff) << 5) | dst;
+ return;
+ }
+
+ if (jump->flags & PATCH_B32) {
+ addr -= ((sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) & ~(sljit_sw)0xfff;
+ SLJIT_ASSERT(addr <= 0xffffffffl && addr >= -0x100000000l);
+ buf_ptr[0] = ADRP | (((sljit_ins)(addr >> 12) & 0x3) << 29) | (((sljit_ins)(addr >> 14) & 0x7ffff) << 5) | dst;
+ buf_ptr[1] = ADDI | dst | (dst << 5) | ((sljit_ins)(addr & 0xfff) << 10);
+ return;
+ }
+ }
+
+ SLJIT_ASSERT((jump->flags & (PATCH_ABS48 | PATCH_ABS64)) || (sljit_uw)addr <= (sljit_uw)0xffffffff);
+ SLJIT_ASSERT((jump->flags & PATCH_ABS64) || (sljit_uw)addr <= (sljit_uw)0xffffffffffff);
+
+ buf_ptr[0] = MOVZ | (((sljit_ins)addr & 0xffff) << 5) | dst;
+ buf_ptr[1] = MOVK | (((sljit_ins)(addr >> 16) & 0xffff) << 5) | (1 << 21) | dst;
+ if (jump->flags & (PATCH_ABS48 | PATCH_ABS64))
+ buf_ptr[2] = MOVK | (((sljit_ins)(addr >> 32) & 0xffff) << 5) | (2 << 21) | dst;
+
+ if (jump->flags & PATCH_ABS64)
+ buf_ptr[3] = MOVK | ((sljit_ins)((sljit_uw)addr >> 48) << 5) | (3 << 21) | dst;
+}
+
+static SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
+static void reduce_code_size(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+ SLJIT_NEXT_DEFINE_TYPES;
+ sljit_uw total_size;
+ sljit_uw size_reduce = 0;
+ sljit_sw diff;
+
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ SLJIT_NEXT_INIT_TYPES();
+
+ while (1) {
+ SLJIT_GET_NEXT_MIN();
+
+ if (next_min_addr == SLJIT_MAX_ADDRESS)
+ break;
+
+ if (next_min_addr == next_label_size) {
+ label->size -= size_reduce;
+
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ if (next_min_addr == next_const_addr) {
+ const_->addr -= size_reduce;
+ const_ = const_->next;
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+ continue;
+ }
+
+ if (next_min_addr != next_jump_addr)
+ continue;
+
+ jump->addr -= size_reduce;
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+ total_size = JUMP_MAX_SIZE;
+
+ if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {
+ if (jump->flags & JUMP_ADDR) {
+ if (jump->u.target < 0x100000000l)
+ total_size = 3;
+ else if (jump->u.target < 0x1000000000000l)
+ total_size = 4;
+ } else {
+ /* Unit size: instruction. */
+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
+ if (jump->u.label->size > jump->addr) {
+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);
+ diff -= (sljit_sw)size_reduce;
+ }
+
+ if ((jump->flags & IS_COND) && (diff + 1) <= (0xfffff / SSIZE_OF(ins)) && (diff + 1) >= (-0x100000 / SSIZE_OF(ins)))
+ total_size = 0;
+ else if (diff <= (0x7ffffff / SSIZE_OF(ins)) && diff >= (-0x8000000 / SSIZE_OF(ins)))
+ total_size = 1;
+ else if (diff <= (0xfffff000l / SSIZE_OF(ins)) && diff >= (-0x100000000l / SSIZE_OF(ins)))
+ total_size = 3;
+ }
+ }
+
+ size_reduce += JUMP_MAX_SIZE - total_size;
+ } else {
+ /* Real size minus 1. Unit size: instruction. */
+ total_size = 3;
+
+ if (!(jump->flags & JUMP_ADDR)) {
+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
+ if (jump->u.label->size > jump->addr) {
+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);
+ diff -= (sljit_sw)size_reduce;
+ }
+
+ if (diff <= (0xfffff / SSIZE_OF(ins)) && diff >= (-0x100000 / SSIZE_OF(ins)))
+ total_size = 0;
+ else if (diff <= (0xfffff000l / SSIZE_OF(ins)) && diff >= (-0x100000000l / SSIZE_OF(ins)))
+ total_size = 1;
+ } else if (jump->u.target < 0x100000000l)
+ total_size = 1;
+ else if (jump->u.target < 0x1000000000000l)
+ total_size = 2;
+
+ size_reduce += 3 - total_size;
+ }
+
+ jump->flags |= total_size << JUMP_SIZE_SHIFT;
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ }
+
+ compiler->size -= size_reduce;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
+{
+ struct sljit_memory_fragment *buf;
+ sljit_ins *code;
+ sljit_ins *code_ptr;
+ sljit_ins *buf_ptr;
+ sljit_ins *buf_end;
+ sljit_uw word_count;
+ SLJIT_NEXT_DEFINE_TYPES;
+ sljit_sw executable_offset;
+ sljit_sw addr;
+
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
+
+ reduce_code_size(compiler);
+
+ code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
+ PTR_FAIL_WITH_EXEC_IF(code);
+
+ reverse_buf(compiler);
+ buf = compiler->buf;
+
+ code_ptr = code;
+ word_count = 0;
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ SLJIT_NEXT_INIT_TYPES();
+ SLJIT_GET_NEXT_MIN();
+
+ do {
+ buf_ptr = (sljit_ins*)buf->memory;
+ buf_end = buf_ptr + (buf->used_size >> 2);
+ do {
+ *code_ptr = *buf_ptr++;
+ if (next_min_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+
+ /* These structures are ordered by their address. */
+ if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+ *code_ptr = buf_ptr[-1];
+ }
+
+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ if (next_min_addr == next_jump_addr) {
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+ word_count = word_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT);
+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
+ SLJIT_ASSERT((jump->flags & PATCH_COND) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));
+ } else {
+ word_count += jump->flags >> JUMP_SIZE_SHIFT;
+ addr = (sljit_sw)code_ptr;
+ code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);
+ jump->addr = (sljit_uw)addr;
+ }
+
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ } else if (next_min_addr == next_const_addr) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+ }
+
+ SLJIT_GET_NEXT_MIN();
+ }
+ code_ptr++;
+ word_count++;
+ } while (buf_ptr < buf_end);
+
+ buf = buf->next;
+ } while (buf);
+
+ if (label && label->size == word_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ }
+
+ SLJIT_ASSERT(!label);
+ SLJIT_ASSERT(!jump);
+ SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
+
+ jump = compiler->jumps;
+ while (jump) {
+ generate_jump_or_mov_addr(jump, executable_offset);
+ jump = jump->next;
+ }
+
+ compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
+
+ code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+ code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
+ SLJIT_CACHE_FLUSH(code, code_ptr);
+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
+ return code;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type) {
+ case SLJIT_HAS_FPU:
+ case SLJIT_HAS_SIMD:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return (SLJIT_IS_FPU_AVAILABLE) != 0;
+#else
+ /* Available by default. */
+ return 1;
+#endif
+
+ case SLJIT_HAS_CLZ:
+ case SLJIT_HAS_CTZ:
+ case SLJIT_HAS_REV:
+ case SLJIT_HAS_ROT:
+ case SLJIT_HAS_CMOV:
+ case SLJIT_HAS_PREFETCH:
+ case SLJIT_HAS_COPY_F32:
+ case SLJIT_HAS_COPY_F64:
+ case SLJIT_HAS_ATOMIC:
+ case SLJIT_HAS_MEMORY_BARRIER:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
+{
+ switch (type) {
+ case SLJIT_UNORDERED_OR_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ return 2;
+ }
+
+ return 0;
+}
+
+/* --------------------------------------------------------------------- */
+/* Core code generator functions. */
+/* --------------------------------------------------------------------- */
+
+#define COUNT_TRAILING_ZERO(value, result) \
+ result = 0; \
+ if (!(value & 0xffffffff)) { \
+ result += 32; \
+ value >>= 32; \
+ } \
+ if (!(value & 0xffff)) { \
+ result += 16; \
+ value >>= 16; \
+ } \
+ if (!(value & 0xff)) { \
+ result += 8; \
+ value >>= 8; \
+ } \
+ if (!(value & 0xf)) { \
+ result += 4; \
+ value >>= 4; \
+ } \
+ if (!(value & 0x3)) { \
+ result += 2; \
+ value >>= 2; \
+ } \
+ if (!(value & 0x1)) { \
+ result += 1; \
+ value >>= 1; \
+ }
+
+#define LOGICAL_IMM_CHECK (sljit_ins)0x100
+
+static sljit_ins logical_imm(sljit_sw imm, sljit_u32 len)
+{
+ sljit_s32 negated;
+ sljit_u32 ones, right;
+ sljit_uw mask, uimm;
+ sljit_ins ins;
+
+ if (len & LOGICAL_IMM_CHECK) {
+ len &= ~LOGICAL_IMM_CHECK;
+ if (len == 32 && (imm == 0 || imm == -1))
+ return 0;
+ if (len == 16 && ((sljit_s32)imm == 0 || (sljit_s32)imm == -1))
+ return 0;
+ }
+
+ SLJIT_ASSERT((len == 32 && imm != 0 && imm != -1)
+ || (len == 16 && (sljit_s32)imm != 0 && (sljit_s32)imm != -1));
+
+ uimm = (sljit_uw)imm;
+ while (1) {
+ if (len <= 0) {
+ SLJIT_UNREACHABLE();
+ return 0;
+ }
+
+ mask = ((sljit_uw)1 << len) - 1;
+ if ((uimm & mask) != ((uimm >> len) & mask))
+ break;
+ len >>= 1;
+ }
+
+ len <<= 1;
+
+ negated = 0;
+ if (uimm & 0x1) {
+ negated = 1;
+ uimm = ~uimm;
+ }
+
+ if (len < 64)
+ uimm &= ((sljit_uw)1 << len) - 1;
+
+ /* Unsigned right shift. */
+ COUNT_TRAILING_ZERO(uimm, right);
+
+ /* Signed shift. We also know that the highest bit is set. */
+ imm = (sljit_sw)~uimm;
+ SLJIT_ASSERT(imm < 0);
+
+ COUNT_TRAILING_ZERO(imm, ones);
+
+ if (~imm)
+ return 0;
+
+ if (len == 64)
+ ins = 1 << 22;
+ else
+ ins = (0x3f - ((len << 1) - 1)) << 10;
+
+ if (negated)
+ return ins | ((len - ones - 1) << 10) | ((len - ones - right) << 16);
+
+ return ins | ((ones - 1) << 10) | ((len - right) << 16);
+}
+
+#undef COUNT_TRAILING_ZERO
+
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw simm)
+{
+ sljit_uw imm = (sljit_uw)simm;
+ sljit_u32 i, zeros, ones, first;
+ sljit_ins bitmask;
+
+ /* Handling simple immediates first. */
+ if (imm <= 0xffff)
+ return push_inst(compiler, MOVZ | RD(dst) | ((sljit_ins)imm << 5));
+
+ if (simm < 0 && simm >= -0x10000)
+ return push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)~imm & 0xffff) << 5));
+
+ if (imm <= 0xffffffffl) {
+ if ((imm & 0xffff) == 0)
+ return push_inst(compiler, MOVZ | RD(dst) | ((sljit_ins)(imm >> 16) << 5) | (1 << 21));
+ if ((imm & 0xffff0000l) == 0xffff0000)
+ return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | (((sljit_ins)~imm & 0xffff) << 5));
+ if ((imm & 0xffff) == 0xffff)
+ return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | (((sljit_ins)~imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));
+
+ bitmask = logical_imm(simm, 16);
+ if (bitmask != 0)
+ return push_inst(compiler, (ORRI ^ W_OP) | RD(dst) | RN(TMP_ZERO) | bitmask);
+
+ FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | (((sljit_ins)imm & 0xffff) << 5)));
+ return push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));
+ }
+
+ bitmask = logical_imm(simm, 32);
+ if (bitmask != 0)
+ return push_inst(compiler, ORRI | RD(dst) | RN(TMP_ZERO) | bitmask);
+
+ if (simm < 0 && simm >= -0x100000000l) {
+ if ((imm & 0xffff) == 0xffff)
+ return push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)~imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));
+
+ FAIL_IF(push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)~imm & 0xffff) << 5)));
+ return push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));
+ }
+
+ /* A large amount of number can be constructed from ORR and MOVx, but computing them is costly. */
+
+ zeros = 0;
+ ones = 0;
+ for (i = 4; i > 0; i--) {
+ if ((simm & 0xffff) == 0)
+ zeros++;
+ if ((simm & 0xffff) == 0xffff)
+ ones++;
+ simm >>= 16;
+ }
+
+ simm = (sljit_sw)imm;
+ first = 1;
+ if (ones > zeros) {
+ simm = ~simm;
+ for (i = 0; i < 4; i++) {
+ if (!(simm & 0xffff)) {
+ simm >>= 16;
+ continue;
+ }
+ if (first) {
+ first = 0;
+ FAIL_IF(push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)simm & 0xffff) << 5) | (i << 21)));
+ }
+ else
+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)~simm & 0xffff) << 5) | (i << 21)));
+ simm >>= 16;
+ }
+ return SLJIT_SUCCESS;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (!(simm & 0xffff)) {
+ simm >>= 16;
+ continue;
+ }
+ if (first) {
+ first = 0;
+ FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | (((sljit_ins)simm & 0xffff) << 5) | (i << 21)));
+ }
+ else
+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)simm & 0xffff) << 5) | (i << 21)));
+ simm >>= 16;
+ }
+ return SLJIT_SUCCESS;
+}
+
+#define ARG1_IMM 0x0010000
+#define ARG2_IMM 0x0020000
+#define INT_OP 0x0040000
+#define SET_FLAGS 0x0080000
+#define UNUSED_RETURN 0x0100000
+
+#define CHECK_FLAGS(flag_bits) \
+ if (flags & SET_FLAGS) { \
+ inv_bits |= flag_bits; \
+ if (flags & UNUSED_RETURN) \
+ dst = TMP_ZERO; \
+ }
+
+static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 dst, sljit_sw arg1, sljit_sw arg2)
+{
+ /* dst must be register, TMP_REG1
+ arg1 must be register, TMP_REG1, imm
+ arg2 must be register, TMP_REG2, imm */
+ sljit_ins inv_bits = (flags & INT_OP) ? W_OP : 0;
+ sljit_ins inst_bits;
+ sljit_s32 op = (flags & 0xffff);
+ sljit_s32 reg;
+ sljit_sw imm, nimm;
+
+ if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {
+ /* Both are immediates. */
+ flags &= ~ARG1_IMM;
+ if (arg1 == 0 && op != SLJIT_ADD && op != SLJIT_SUB)
+ arg1 = TMP_ZERO;
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));
+ arg1 = TMP_REG1;
+ }
+ }
+
+ if (flags & (ARG1_IMM | ARG2_IMM)) {
+ reg = (sljit_s32)((flags & ARG2_IMM) ? arg1 : arg2);
+ imm = (flags & ARG2_IMM) ? arg2 : arg1;
+
+ switch (op) {
+ case SLJIT_CLZ:
+ case SLJIT_CTZ:
+ case SLJIT_REV:
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+ case SLJIT_ADDC:
+ case SLJIT_SUBC:
+ case SLJIT_MUL:
+ case SLJIT_MULADD:
+ /* No form with immediate operand (except imm 0, which
+ is represented by a ZERO register). */
+ break;
+ case SLJIT_MOV:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG1);
+ return load_immediate(compiler, dst, imm);
+ case SLJIT_SUB:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ if (flags & ARG1_IMM)
+ break;
+ imm = -imm;
+ SLJIT_FALLTHROUGH
+ case SLJIT_ADD:
+ if (op != SLJIT_SUB)
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+
+ if (imm == 0) {
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, ((op == SLJIT_ADD ? ADDI : SUBI) ^ inv_bits) | RD(dst) | RN(reg));
+ }
+ if (imm > 0 && imm <= 0xfff) {
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | ((sljit_ins)imm << 10));
+ }
+ nimm = -imm;
+ if (nimm > 0 && nimm <= 0xfff) {
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | ((sljit_ins)nimm << 10));
+ }
+ if (imm > 0 && imm <= 0xffffff && !(imm & 0xfff)) {
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)imm >> 12) << 10) | (1 << 22));
+ }
+ if (nimm > 0 && nimm <= 0xffffff && !(nimm & 0xfff)) {
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)nimm >> 12) << 10) | (1 << 22));
+ }
+ if (imm > 0 && imm <= 0xffffff && !(flags & SET_FLAGS)) {
+ FAIL_IF(push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)imm >> 12) << 10) | (1 << 22)));
+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(dst) | (((sljit_ins)imm & 0xfff) << 10));
+ }
+ if (nimm > 0 && nimm <= 0xffffff && !(flags & SET_FLAGS)) {
+ FAIL_IF(push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)nimm >> 12) << 10) | (1 << 22)));
+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(dst) | (((sljit_ins)nimm & 0xfff) << 10));
+ }
+ break;
+ case SLJIT_AND:
+ inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32));
+ if (!inst_bits)
+ break;
+ CHECK_FLAGS(3 << 29);
+ return push_inst(compiler, (ANDI ^ inv_bits) | RD(dst) | RN(reg) | inst_bits);
+ case SLJIT_XOR:
+ if (imm == -1) {
+ FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(reg)));
+ goto set_flags;
+ }
+ SLJIT_FALLTHROUGH
+ case SLJIT_OR:
+ inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32));
+ if (!inst_bits)
+ break;
+ if (op == SLJIT_OR)
+ inst_bits |= ORRI;
+ else
+ inst_bits |= EORI;
+ FAIL_IF(push_inst(compiler, (inst_bits ^ inv_bits) | RD(dst) | RN(reg)));
+ goto set_flags;
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ if (flags & ARG1_IMM)
+ break;
+
+ if (flags & INT_OP) {
+ imm &= 0x1f;
+ inst_bits = (((sljit_ins)-imm & 0x1f) << 16) | ((31 - (sljit_ins)imm) << 10);
+ } else {
+ imm &= 0x3f;
+ inst_bits = ((sljit_ins)1 << 22) | (((sljit_ins)-imm & 0x3f) << 16) | ((63 - (sljit_ins)imm) << 10);
+ }
+
+ inv_bits |= inv_bits >> 9;
+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | inst_bits));
+ goto set_flags;
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ if (flags & ARG1_IMM)
+ break;
+
+ inv_bits |= inv_bits >> 9;
+ if (op >= SLJIT_ASHR)
+ inv_bits |= 1 << 30;
+
+ if (flags & INT_OP) {
+ imm &= 0x1f;
+ inst_bits = ((sljit_ins)imm << 16) | (31 << 10);
+ } else {
+ imm &= 0x3f;
+ inst_bits = ((sljit_ins)1 << 22) | ((sljit_ins)imm << 16) | (63 << 10);
+ }
+
+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | inst_bits));
+ goto set_flags;
+ case SLJIT_ROTL:
+ case SLJIT_ROTR:
+ if (flags & ARG1_IMM)
+ break;
+
+ if (op == SLJIT_ROTL)
+ imm = -imm;
+
+ imm &= (flags & INT_OP) ? 0x1f : 0x3f;
+ return push_inst(compiler, (EXTR ^ (inv_bits | (inv_bits >> 9))) | RD(dst) | RN(arg1) | RM(arg1) | ((sljit_ins)imm << 10));
+ default:
+ SLJIT_UNREACHABLE();
+ break;
+ }
+
+ if (flags & ARG2_IMM) {
+ if (arg2 == 0)
+ arg2 = TMP_ZERO;
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, arg2));
+ arg2 = TMP_REG2;
+ }
+ }
+ else {
+ if (arg1 == 0)
+ arg1 = TMP_ZERO;
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));
+ arg1 = TMP_REG1;
+ }
+ }
+ }
+
+ /* Both arguments are registers. */
+ switch (op) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ if (dst == arg2)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, MOV | RD(dst) | RM(arg2));
+ case SLJIT_MOV_U8:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ inv_bits |= inv_bits >> 9;
+ return push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg2) | (7 << 10));
+ case SLJIT_MOV_S8:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ inv_bits |= inv_bits >> 9;
+ return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (7 << 10));
+ case SLJIT_MOV_U16:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ inv_bits |= inv_bits >> 9;
+ return push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg2) | (15 << 10));
+ case SLJIT_MOV_S16:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ inv_bits |= inv_bits >> 9;
+ return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (15 << 10));
+ case SLJIT_MOV32:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ if (dst == arg2)
+ return SLJIT_SUCCESS;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_U32:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ return push_inst(compiler, (MOV ^ W_OP) | RD(dst) | RM(arg2));
+ case SLJIT_MOV_S32:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
+ return push_inst(compiler, SBFM | (1 << 22) | RD(dst) | RN(arg2) | (31 << 10));
+ case SLJIT_CLZ:
+ SLJIT_ASSERT(arg1 == TMP_REG1);
+ return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2));
+ case SLJIT_CTZ:
+ SLJIT_ASSERT(arg1 == TMP_REG1);
+ FAIL_IF(push_inst(compiler, (RBIT ^ inv_bits) | RD(dst) | RN(arg2)));
+ return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(dst));
+ case SLJIT_REV:
+ SLJIT_ASSERT(arg1 == TMP_REG1);
+ inv_bits |= inv_bits >> 21;
+ return push_inst(compiler, (REV ^ inv_bits) | RD(dst) | RN(arg2));
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+ SLJIT_ASSERT(arg1 == TMP_REG1 && dst != TMP_REG2);
+ FAIL_IF(push_inst(compiler, (REV16 ^ (sljit_ins)0x80000000) | RD(dst) | RN(arg2)));
+ if (dst == TMP_REG1 || (arg2 == TMP_REG2 && op == SLJIT_REV_U16))
+ return SLJIT_SUCCESS;
+ inv_bits |= inv_bits >> 9;
+ return push_inst(compiler, ((op == SLJIT_REV_U16 ? UBFM : SBFM) ^ inv_bits) | RD(dst) | RN(dst) | (15 << 10));
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+ SLJIT_ASSERT(arg1 == TMP_REG1 && dst != TMP_REG2);
+ FAIL_IF(push_inst(compiler, (REV ^ (sljit_ins)0x80000400) | RD(dst) | RN(arg2)));
+ if (op == SLJIT_REV_U32 || dst == TMP_REG1)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, SBFM | (1 << 22) | RD(dst) | RN(dst) | (31 << 10));
+ case SLJIT_ADD:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (ADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
+ case SLJIT_ADDC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (ADC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
+ case SLJIT_SUB:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
+ case SLJIT_SUBC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ CHECK_FLAGS(1 << 29);
+ return push_inst(compiler, (SBC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
+ case SLJIT_MUL:
+ compiler->status_flags_state = 0;
+ if (!(flags & SET_FLAGS))
+ return push_inst(compiler, (MADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO));
+ if (flags & INT_OP) {
+ FAIL_IF(push_inst(compiler, SMADDL | RD(dst) | RN(arg1) | RM(arg2) | (31 << 10)));
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_LR) | RN(TMP_ZERO) | RM(dst) | (2 << 22) | (31 << 10)));
+ return push_inst(compiler, SUBS | RD(TMP_ZERO) | RN(TMP_LR) | RM(dst) | (2 << 22) | (63 << 10));
+ }
+ FAIL_IF(push_inst(compiler, SMULH | RD(TMP_LR) | RN(arg1) | RM(arg2)));
+ FAIL_IF(push_inst(compiler, MADD | RD(dst) | RN(arg1) | RM(arg2) | RT2(TMP_ZERO)));
+ return push_inst(compiler, SUBS | RD(TMP_ZERO) | RN(TMP_LR) | RM(dst) | (2 << 22) | (63 << 10));
+ case SLJIT_AND:
+ CHECK_FLAGS(3 << 29);
+ return push_inst(compiler, (AND ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
+ case SLJIT_OR:
+ FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
+ break; /* Set flags. */
+ case SLJIT_XOR:
+ FAIL_IF(push_inst(compiler, (EOR ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
+ break; /* Set flags. */
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ FAIL_IF(push_inst(compiler, (LSLV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
+ break; /* Set flags. */
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ FAIL_IF(push_inst(compiler, (LSRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
+ break; /* Set flags. */
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ FAIL_IF(push_inst(compiler, (ASRV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2)));
+ break; /* Set flags. */
+ case SLJIT_ROTL:
+ FAIL_IF(push_inst(compiler, (SUB ^ inv_bits) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(arg2)));
+ arg2 = TMP_REG2;
+ SLJIT_FALLTHROUGH
+ case SLJIT_ROTR:
+ return push_inst(compiler, (RORV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
+ case SLJIT_MULADD:
+ compiler->status_flags_state = 0;
+ return push_inst(compiler, (MADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2) | RT2(dst));
+ default:
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
+ }
+
+set_flags:
+ if (flags & SET_FLAGS)
+ return push_inst(compiler, (SUBS ^ inv_bits) | RD(TMP_ZERO) | RN(dst) | RM(TMP_ZERO));
+ return SLJIT_SUCCESS;
+}
+
+#define STORE 0x10
+#define SIGNED 0x20
+
+#define BYTE_SIZE 0x0
+#define HALF_SIZE 0x1
+#define INT_SIZE 0x2
+#define WORD_SIZE 0x3
+
+#define MEM_SIZE_SHIFT(flags) ((sljit_ins)(flags) & 0x3)
+
+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,
+ sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
+{
+ sljit_u32 shift = MEM_SIZE_SHIFT(flags);
+ sljit_u32 type = (shift << 30);
+
+ if (!(flags & STORE))
+ type |= (flags & SIGNED) ? 0x00800000 : 0x00400000;
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ argw &= 0x3;
+
+ if (argw == 0 || argw == shift)
+ return push_inst(compiler, STRB | type | RT(reg)
+ | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0));
+
+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_ins)argw << 10)));
+ return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg));
+ }
+
+ arg &= REG_MASK;
+
+ if (!arg) {
+ FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~(0xfff << shift)));
+
+ argw = (argw >> shift) & 0xfff;
+
+ return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | ((sljit_ins)argw << 10));
+ }
+
+ if ((argw & ((1 << shift) - 1)) == 0) {
+ if (argw >= 0) {
+ if ((argw >> shift) <= 0xfff)
+ return push_inst(compiler, STRBI | type | RT(reg) | RN(arg) | ((sljit_ins)argw << (10 - shift)));
+
+ if (argw <= 0xffffff) {
+ FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)argw >> 12) << 10)));
+
+ argw = ((argw & 0xfff) >> shift);
+ return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | ((sljit_ins)argw << 10));
+ }
+ } else if (argw < -256 && argw >= -0xfff000) {
+ FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)(-argw + 0xfff) >> 12) << 10)));
+ argw = ((0x1000 + argw) & 0xfff) >> shift;
+ return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | ((sljit_ins)argw << 10));
+ }
+ }
+
+ if (argw <= 0xff && argw >= -0x100)
+ return push_inst(compiler, STURBI | type | RT(reg) | RN(arg) | (((sljit_ins)argw & 0x1ff) << 12));
+
+ if (((argw + 0x100) & 0xfff) <= 0x1ff && argw <= 0xfff0ff && argw >= -0xfff100) {
+ if (argw >= 0) {
+ if (argw & 0x100)
+ argw += 0x1000;
+
+ FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)argw >> 12) << 10)));
+ return push_inst(compiler, STURBI | type | RT(reg) | RN(tmp_reg) | (((sljit_ins)argw & 0x1ff) << 12));
+ } else {
+ if (!(argw & 0x100))
+ argw -= 0x1000;
+
+ FAIL_IF(push_inst(compiler, SUBI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)-argw >> 12) << 10)));
+ return push_inst(compiler, STURBI | type | RT(reg) | RN(tmp_reg) | (((sljit_ins)argw & 0x1ff) << 12));
+ }
+ }
+
+ FAIL_IF(load_immediate(compiler, tmp_reg, argw));
+
+ return push_inst(compiler, STRB | type | RT(reg) | RN(arg) | RM(tmp_reg));
+}
+
+/* --------------------------------------------------------------------- */
+/* Entry, exit */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches;
+ sljit_s32 fsaveds;
+ sljit_s32 prev, fprev, saved_regs_size, i, tmp;
+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
+ sljit_ins offs;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+
+ saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 2);
+ saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+
+ local_size = (local_size + saved_regs_size + 0xf) & ~0xf;
+ compiler->local_size = local_size;
+
+ if (local_size <= 512) {
+ FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)
+ | RN(SLJIT_SP) | (sljit_ins)((-(local_size >> 3) & 0x7f) << 15)));
+ offs = (sljit_ins)(local_size - 2 * SSIZE_OF(sw)) << (15 - 3);
+ local_size = 0;
+ } else {
+ saved_regs_size = ((saved_regs_size - 2 * SSIZE_OF(sw)) + 0xf) & ~0xf;
+
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)saved_regs_size << 10)));
+ offs = (sljit_ins)(saved_regs_size - 2 * SSIZE_OF(sw)) << (15 - 3);
+ local_size -= saved_regs_size;
+ SLJIT_ASSERT(local_size > 0);
+ }
+
+ prev = -1;
+
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
+ if (prev == -1) {
+ prev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));
+ offs -= (sljit_ins)2 << 15;
+ prev = -1;
+ }
+
+ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ if (prev == -1) {
+ prev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));
+ offs -= (sljit_ins)2 << 15;
+ prev = -1;
+ }
+
+ fprev = -1;
+
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ if (fprev == -1) {
+ fprev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, STP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));
+ offs -= (sljit_ins)2 << 15;
+ fprev = -1;
+ }
+
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ if (fprev == -1) {
+ fprev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, STP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));
+ offs -= (sljit_ins)2 << 15;
+ fprev = -1;
+ }
+
+ if (fprev != -1)
+ FAIL_IF(push_inst(compiler, STRI_F64 | VT(fprev) | RN(SLJIT_SP) | (offs >> 5) | (1 << 10)));
+
+ if (prev != -1)
+ FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5) | ((fprev == -1) ? (1 << 10) : 0)));
+
+
+#ifdef _WIN32
+ if (local_size > 4096)
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));
+#endif /* _WIN32 */
+
+ if (!(options & SLJIT_ENTER_REG_ARG)) {
+ arg_types >>= SLJIT_ARG_SHIFT;
+ saved_arg_count = 0;
+ tmp = SLJIT_R0;
+
+ while (arg_types) {
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S0 - saved_arg_count) | RM(tmp)));
+ saved_arg_count++;
+ }
+ tmp++;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+ }
+
+#ifdef _WIN32
+ if (local_size > 4096) {
+ if (local_size < 4 * 4096) {
+ /* No need for a loop. */
+
+ if (local_size >= 2 * 4096) {
+ if (local_size >= 3 * 4096) {
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));
+ }
+
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));
+ }
+ }
+ else {
+ FAIL_IF(push_inst(compiler, MOVZ | RD(TMP_REG1) | ((((sljit_ins)local_size >> 12) - 1) << 5)));
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));
+ FAIL_IF(push_inst(compiler, SUBI | (1 << 29) | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10)));
+ FAIL_IF(push_inst(compiler, B_CC | ((((sljit_ins) -3) & 0x7ffff) << 5) | 0x1 /* not-equal */));
+ }
+
+ local_size &= 0xfff;
+
+ if (local_size > 0)
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));
+ else
+ FAIL_IF(push_inst(compiler, STP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));
+ }
+
+ if (local_size > 0) {
+ if (local_size <= 512)
+ FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)
+ | RN(SLJIT_SP) | (sljit_ins)((-(local_size >> 3) & 0x7f) << 15)));
+ else {
+ if (local_size >= 4096)
+ local_size = (1 << (22 - 10));
+
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)local_size << 10)));
+ FAIL_IF(push_inst(compiler, STP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));
+ }
+ }
+
+#else /* !_WIN32 */
+
+ /* The local_size does not include saved registers size. */
+ if (local_size != 0) {
+ if (local_size > 0xfff) {
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (((sljit_ins)local_size >> 12) << 10) | (1 << 22)));
+ local_size &= 0xfff;
+ }
+
+ if (local_size > 512 || local_size == 0) {
+ if (local_size != 0)
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)local_size << 10)));
+
+ FAIL_IF(push_inst(compiler, STP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));
+ } else
+ FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)
+ | RN(SLJIT_SP) | (sljit_ins)((-(local_size >> 3) & 0x7f) << 15)));
+ }
+
+#endif /* _WIN32 */
+
+ return push_inst(compiler, ADDI | RD(TMP_FP) | RN(SLJIT_SP) | (0 << 10));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches;
+ sljit_s32 fsaveds;
+ sljit_s32 saved_regs_size;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+ saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 2);
+ saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+
+ compiler->local_size = (local_size + saved_regs_size + 0xf) & ~0xf;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)
+{
+ sljit_s32 local_size, prev, fprev, i, tmp;
+ sljit_ins offs;
+
+ local_size = compiler->local_size;
+
+ if (!is_return_to) {
+ if (local_size > 512 && local_size <= 512 + 496) {
+ FAIL_IF(push_inst(compiler, LDP_POST | RT(TMP_FP) | RT2(TMP_LR)
+ | RN(SLJIT_SP) | ((sljit_ins)(local_size - 512) << (15 - 3))));
+ local_size = 512;
+ } else
+ FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));
+ } else {
+ if (local_size > 512 && local_size <= 512 + 248) {
+ FAIL_IF(push_inst(compiler, LDRI_POST | RT(TMP_FP) | RN(SLJIT_SP) | ((sljit_ins)(local_size - 512) << 12)));
+ local_size = 512;
+ } else
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_FP) | RN(SLJIT_SP) | 0));
+ }
+
+ if (local_size > 512) {
+ local_size -= 512;
+ if (local_size > 0xfff) {
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP)
+ | (((sljit_ins)local_size >> 12) << 10) | (1 << 22)));
+ local_size &= 0xfff;
+ }
+
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)local_size << 10)));
+ local_size = 512;
+ }
+
+ offs = (sljit_ins)(local_size - 2 * SSIZE_OF(sw)) << (15 - 3);
+ prev = -1;
+
+ tmp = SLJIT_S0 - compiler->saveds;
+ for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {
+ if (prev == -1) {
+ prev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));
+ offs -= (sljit_ins)2 << 15;
+ prev = -1;
+ }
+
+ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ if (prev == -1) {
+ prev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));
+ offs -= (sljit_ins)2 << 15;
+ prev = -1;
+ }
+
+ fprev = -1;
+
+ tmp = SLJIT_FS0 - compiler->fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ if (fprev == -1) {
+ fprev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, LDP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));
+ offs -= (sljit_ins)2 << 15;
+ fprev = -1;
+ }
+
+ for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ if (fprev == -1) {
+ fprev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, LDP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));
+ offs -= (sljit_ins)2 << 15;
+ fprev = -1;
+ }
+
+ if (fprev != -1)
+ FAIL_IF(push_inst(compiler, LDRI_F64 | VT(fprev) | RN(SLJIT_SP) | (offs >> 5) | (1 << 10)));
+
+ if (prev != -1)
+ FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5) | ((fprev == -1) ? (1 << 10) : 0)));
+
+ /* This and the next call/jump instruction can be executed parallelly. */
+ return push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | (sljit_ins)(local_size << 10));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ FAIL_IF(emit_stack_frame_release(compiler, 0));
+
+ return push_inst(compiler, RET | RN(TMP_LR));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));
+ src = TMP_REG1;
+ srcw = 0;
+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src)));
+ src = TMP_REG1;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 1));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
+}
+
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
+{
+ sljit_ins inv_bits = (op & SLJIT_32) ? W_OP : 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op0(compiler, op));
+
+ op = GET_OPCODE(op);
+ switch (op) {
+ case SLJIT_BREAKPOINT:
+ return push_inst(compiler, BRK | (0xf000 << 5));
+ case SLJIT_NOP:
+ return push_inst(compiler, NOP);
+ case SLJIT_LMUL_UW:
+ case SLJIT_LMUL_SW:
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(SLJIT_R0)));
+ FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO)));
+ return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULH : SMULH) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1));
+ case SLJIT_DIVMOD_UW:
+ case SLJIT_DIVMOD_SW:
+ FAIL_IF(push_inst(compiler, (MOV ^ inv_bits) | RD(TMP_REG1) | RM(SLJIT_R0)));
+ FAIL_IF(push_inst(compiler, ((op == SLJIT_DIVMOD_UW ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)));
+ FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_R1) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO)));
+ return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1));
+ case SLJIT_DIV_UW:
+ case SLJIT_DIV_SW:
+ return push_inst(compiler, ((op == SLJIT_DIV_UW ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1));
+ case SLJIT_MEMORY_BARRIER:
+ return push_inst(compiler, DMB_SY);
+ case SLJIT_ENDBR:
+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
+ return SLJIT_SUCCESS;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r, flags, mem_flags;
+ sljit_s32 op_flags = GET_ALL_FLAGS(op);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ op = GET_OPCODE(op);
+ if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {
+ /* Both operands are registers. */
+ if (FAST_IS_REG(dst) && FAST_IS_REG(src))
+ return emit_op_imm(compiler, op | ((op_flags & SLJIT_32) ? INT_OP : 0), dst_r, TMP_REG1, src);
+
+ switch (op) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ mem_flags = WORD_SIZE;
+ break;
+ case SLJIT_MOV_U8:
+ mem_flags = BYTE_SIZE;
+ if (src == SLJIT_IMM)
+ srcw = (sljit_u8)srcw;
+ break;
+ case SLJIT_MOV_S8:
+ mem_flags = BYTE_SIZE | SIGNED;
+ if (src == SLJIT_IMM)
+ srcw = (sljit_s8)srcw;
+ break;
+ case SLJIT_MOV_U16:
+ mem_flags = HALF_SIZE;
+ if (src == SLJIT_IMM)
+ srcw = (sljit_u16)srcw;
+ break;
+ case SLJIT_MOV_S16:
+ mem_flags = HALF_SIZE | SIGNED;
+ if (src == SLJIT_IMM)
+ srcw = (sljit_s16)srcw;
+ break;
+ case SLJIT_MOV_U32:
+ mem_flags = INT_SIZE;
+ if (src == SLJIT_IMM)
+ srcw = (sljit_u32)srcw;
+ break;
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ mem_flags = INT_SIZE | SIGNED;
+ if (src == SLJIT_IMM)
+ srcw = (sljit_s32)srcw;
+ break;
+ default:
+ SLJIT_UNREACHABLE();
+ mem_flags = 0;
+ break;
+ }
+
+ if (src == SLJIT_IMM)
+ FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG1, srcw));
+ else if (!(src & SLJIT_MEM))
+ dst_r = src;
+ else
+ FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, src, srcw, TMP_REG2));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2);
+ return SLJIT_SUCCESS;
+ }
+
+ flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0;
+
+ switch (op) {
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+ mem_flags = HALF_SIZE;
+ break;
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+ mem_flags = INT_SIZE;
+ break;
+ default:
+ mem_flags = WORD_SIZE;
+
+ if (op_flags & SLJIT_32) {
+ flags |= INT_OP;
+ mem_flags = INT_SIZE;
+ }
+ break;
+ }
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, src, srcw, TMP_REG2));
+ src = TMP_REG2;
+ }
+
+ emit_op_imm(compiler, flags | op, dst_r, TMP_REG1, src);
+
+ if (SLJIT_UNLIKELY(dst & SLJIT_MEM))
+ return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 dst_r, flags, mem_flags;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
+ mem_flags = WORD_SIZE;
+
+ if (op & SLJIT_32) {
+ flags |= INT_OP;
+ mem_flags = INT_SIZE;
+ }
+
+ if (dst == TMP_REG2)
+ flags |= UNUSED_RETURN;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG1, src1, src1w, TMP_REG1));
+ src1 = TMP_REG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, src2, src2w, TMP_REG2));
+ src2 = TMP_REG2;
+ }
+
+ if (src1 == SLJIT_IMM)
+ flags |= ARG1_IMM;
+ else
+ src1w = src1;
+
+ if (src2 == SLJIT_IMM)
+ flags |= ARG2_IMM;
+ else
+ src2w = src2;
+
+ emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src1w, src2w);
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, mem_flags | STORE, dst_r, dst, dstw, TMP_REG2);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MULADD:
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, op, dst_reg, 0, src1, src1w, src2, src2w);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1_reg,
+ sljit_s32 src2_reg,
+ sljit_s32 src3, sljit_sw src3w)
+{
+ sljit_ins inv_bits, imm;
+ sljit_s32 is_left;
+ sljit_sw mask;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
+
+ is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);
+
+ if (src1_reg == src2_reg) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);
+ }
+
+ ADJUST_LOCAL_OFFSET(src3, src3w);
+
+ inv_bits = (op & SLJIT_32) ? W_OP : 0;
+
+ if (src3 == SLJIT_IMM) {
+ mask = inv_bits ? 0x1f : 0x3f;
+ src3w &= mask;
+
+ if (src3w == 0)
+ return SLJIT_SUCCESS;
+
+ if (is_left)
+ src3w = (src3w ^ mask) + 1;
+
+ return push_inst(compiler, (EXTR ^ (inv_bits | (inv_bits >> 9))) | RD(dst_reg)
+ | RN(is_left ? src1_reg : src2_reg) | RM(is_left ? src2_reg : src1_reg) | ((sljit_ins)src3w << 10));
+ }
+
+ if (src3 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG2, src3, src3w, TMP_REG2));
+ src3 = TMP_REG2;
+ } else if (dst_reg == src3) {
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src3)));
+ src3 = TMP_REG2;
+ }
+
+ FAIL_IF(push_inst(compiler, ((is_left ? LSLV : LSRV) ^ inv_bits) | RD(dst_reg) | RN(src1_reg) | RM(src3)));
+
+ if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {
+ /* Shift left/right by 1. */
+ if (is_left)
+ imm = (sljit_ins)(inv_bits ? ((1 << 16) | (31 << 10)) : ((1 << 16) | (63 << 10) | (1 << 22)));
+ else
+ imm = (sljit_ins)(inv_bits ? ((31 << 16) | (30 << 10)) : ((63 << 16) | (62 << 10) | (1 << 22)));
+
+ FAIL_IF(push_inst(compiler, (UBFM ^ (inv_bits | (inv_bits >> 9))) | RD(TMP_REG1) | RN(src2_reg) | imm));
+
+ /* Set imm to mask. */
+ imm = (sljit_ins)(inv_bits ? (4 << 10) : ((5 << 10) | (1 << 22)));
+ FAIL_IF(push_inst(compiler, (EORI ^ inv_bits) | RD(TMP_REG2) | RN(src3) | imm));
+
+ src2_reg = TMP_REG1;
+ } else
+ FAIL_IF(push_inst(compiler, (SUB ^ inv_bits) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(src3)));
+
+ FAIL_IF(push_inst(compiler, ((is_left ? LSRV : LSLV) ^ inv_bits) | RD(TMP_REG1) | RN(src2_reg) | RM(TMP_REG2)));
+ return push_inst(compiler, (ORR ^ inv_bits) | RD(dst_reg) | RN(dst_reg) | RM(TMP_REG1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r, tmp_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= 0x3f;
+
+ if (src2 == SLJIT_IMM) {
+ src2w = (sljit_sw)((sljit_uw)src2w << shift_arg);
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, src1w));
+ src1 = TMP_REG2;
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src1, src1w, TMP_REG2));
+ src1 = TMP_REG2;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ tmp_r = (src1 == TMP_REG2) ? TMP_REG1 : TMP_REG2;
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, tmp_r, src2, src2w, tmp_r));
+ src2 = tmp_r;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RN(src1) | RM(src2) | ((sljit_ins)shift_arg << 10)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ switch (op) {
+ case SLJIT_FAST_RETURN:
+ if (FAST_IS_REG(src)) {
+ if (src != TMP_LR)
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_LR) | RM(src)));
+ } else
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw, TMP_REG1));
+
+ return push_inst(compiler, RET | RN(TMP_LR));
+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
+ return SLJIT_SUCCESS;
+ case SLJIT_PREFETCH_L1:
+ case SLJIT_PREFETCH_L2:
+ case SLJIT_PREFETCH_L3:
+ case SLJIT_PREFETCH_ONCE:
+ SLJIT_ASSERT(reg_map[1] == 0 && reg_map[3] == 2 && reg_map[5] == 4);
+
+ /* The reg_map[op] should provide the appropriate constant. */
+ if (op == SLJIT_PREFETCH_L1)
+ op = 1;
+ else if (op == SLJIT_PREFETCH_L2)
+ op = 3;
+ else if (op == SLJIT_PREFETCH_L3)
+ op = 5;
+ else
+ op = 2;
+
+ /* Signed word sized load is the prefetch instruction. */
+ return emit_op_mem(compiler, WORD_SIZE | SIGNED, op, src, srcw, TMP_REG1);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 dst_r = TMP_LR;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ switch (op) {
+ case SLJIT_FAST_ENTER:
+ if (FAST_IS_REG(dst)) {
+ if (dst == TMP_LR)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, MOV | RD(dst) | RM(TMP_LR));
+ }
+ break;
+ case SLJIT_GET_RETURN_ADDRESS:
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, dst_r, SLJIT_MEM1(SLJIT_SP), 0x8, TMP_REG2));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
+{
+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
+
+ if (type == SLJIT_GP_REGISTER)
+ return reg_map[reg];
+
+ if (type != SLJIT_FLOAT_REGISTER && type != SLJIT_SIMD_REG_64 && type != SLJIT_SIMD_REG_128)
+ return -1;
+
+ return freg_map[reg];
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_u32 size)
+{
+ SLJIT_UNUSED_ARG(size);
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
+
+ return push_inst(compiler, *(sljit_ins*)instruction);
+}
+
+/* --------------------------------------------------------------------- */
+/* Floating point operators */
+/* --------------------------------------------------------------------- */
+
+static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
+{
+ sljit_u32 shift = MEM_SIZE_SHIFT(flags);
+ sljit_ins type = (shift << 30);
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+
+ if (!(flags & STORE))
+ type |= 0x00400000;
+
+ if (arg & OFFS_REG_MASK) {
+ argw &= 3;
+ if (argw == 0 || argw == shift)
+ return push_inst(compiler, STR_FR | type | VT(reg)
+ | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0));
+
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_ins)argw << 10)));
+ return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG2));
+ }
+
+ arg &= REG_MASK;
+
+ if (!arg) {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, argw & ~(0xfff << shift)));
+
+ argw = (argw >> shift) & 0xfff;
+
+ return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG2) | ((sljit_ins)argw << 10));
+ }
+
+ if (argw >= 0 && (argw & ((1 << shift) - 1)) == 0) {
+ if ((argw >> shift) <= 0xfff)
+ return push_inst(compiler, STR_FI | type | VT(reg) | RN(arg) | ((sljit_ins)argw << (10 - shift)));
+
+ if (argw <= 0xffffff) {
+ FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(TMP_REG2) | RN(arg) | (((sljit_ins)argw >> 12) << 10)));
+
+ argw = ((argw & 0xfff) >> shift);
+ return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG2) | ((sljit_ins)argw << 10));
+ }
+ }
+
+ if (argw <= 255 && argw >= -256)
+ return push_inst(compiler, STUR_FI | type | VT(reg) | RN(arg) | (((sljit_ins)argw & 0x1ff) << 12));
+
+ FAIL_IF(load_immediate(compiler, TMP_REG2, argw));
+ return push_inst(compiler, STR_FR | type | VT(reg) | RN(arg) | RM(TMP_REG2));
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;
+
+ if (GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64)
+ inv_bits |= W_OP;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) ? INT_SIZE : WORD_SIZE, TMP_FREG1, src, srcw));
+ src = TMP_FREG1;
+ }
+
+ FAIL_IF(push_inst(compiler, (FCVTZS ^ inv_bits) | RD(dst_r) | VN(src)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, ((GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) ? INT_SIZE : WORD_SIZE) | STORE, TMP_REG1, dst, dstw, TMP_REG2);
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (src & SLJIT_MEM) {
+ emit_op_mem(compiler, (ins & W_OP) ? WORD_SIZE : INT_SIZE, TMP_REG1, src, srcw, TMP_REG1);
+ src = TMP_REG1;
+ } else if (src == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ src = TMP_REG1;
+ }
+
+ FAIL_IF(push_inst(compiler, ins | VD(dst_r) | RN(src)));
+
+ if (dst & SLJIT_MEM)
+ return emit_fop_mem(compiler, ((ins & (1 << 22)) ? WORD_SIZE : INT_SIZE) | STORE, TMP_FREG1, dst, dstw);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;
+
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) {
+ inv_bits |= W_OP;
+
+ if (src == SLJIT_IMM)
+ srcw = (sljit_s32)srcw;
+ }
+
+ return sljit_emit_fop1_conv_f64_from_w(compiler, SCVTF ^ inv_bits, dst, dstw, src, srcw);
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;
+
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {
+ inv_bits |= W_OP;
+
+ if (src == SLJIT_IMM)
+ srcw = (sljit_u32)srcw;
+ }
+
+ return sljit_emit_fop1_conv_f64_from_w(compiler, UCVTF ^ inv_bits, dst, dstw, src, srcw);
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 mem_flags = (op & SLJIT_32) ? INT_SIZE : WORD_SIZE;
+ sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w));
+ src1 = TMP_FREG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w));
+ src2 = TMP_FREG2;
+ }
+
+ FAIL_IF(push_inst(compiler, (FCMP ^ inv_bits) | VN(src1) | VM(src2)));
+
+ if (GET_FLAG_TYPE(op) != SLJIT_UNORDERED_OR_EQUAL)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst(compiler, CSINC | (0x0 << 12) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(TMP_ZERO)));
+ return push_inst(compiler, CCMPI | (0x0 << 16) | (0x7 << 12) | RN(TMP_REG1) | 0x4);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r, mem_flags = (op & SLJIT_32) ? INT_SIZE : WORD_SIZE;
+ sljit_ins inv_bits;
+
+ CHECK_ERROR();
+
+ SLJIT_COMPILE_ASSERT((INT_SIZE ^ 0x1) == WORD_SIZE, must_be_one_bit_difference);
+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
+
+ inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) ? (mem_flags ^ 0x1) : mem_flags, dst_r, src, srcw));
+ src = dst_r;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_F64:
+ if (src != dst_r) {
+ if (!(dst & SLJIT_MEM))
+ FAIL_IF(push_inst(compiler, (FMOV ^ inv_bits) | VD(dst_r) | VN(src)));
+ else
+ dst_r = src;
+ }
+ break;
+ case SLJIT_NEG_F64:
+ FAIL_IF(push_inst(compiler, (FNEG ^ inv_bits) | VD(dst_r) | VN(src)));
+ break;
+ case SLJIT_ABS_F64:
+ FAIL_IF(push_inst(compiler, (FABS ^ inv_bits) | VD(dst_r) | VN(src)));
+ break;
+ case SLJIT_CONV_F64_FROM_F32:
+ FAIL_IF(push_inst(compiler, FCVT | (sljit_ins)((op & SLJIT_32) ? (1 << 22) : (1 << 15)) | VD(dst_r) | VN(src)));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_fop_mem(compiler, mem_flags | STORE, dst_r, dst, dstw);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 dst_r, mem_flags = (op & SLJIT_32) ? INT_SIZE : WORD_SIZE;
+ sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w));
+ src1 = TMP_FREG1;
+ }
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, mem_flags, TMP_FREG2, src2, src2w));
+ src2 = TMP_FREG2;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD_F64:
+ FAIL_IF(push_inst(compiler, (FADD ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));
+ break;
+ case SLJIT_SUB_F64:
+ FAIL_IF(push_inst(compiler, (FSUB ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));
+ break;
+ case SLJIT_MUL_F64:
+ FAIL_IF(push_inst(compiler, (FMUL ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));
+ break;
+ case SLJIT_DIV_F64:
+ FAIL_IF(push_inst(compiler, (FDIV ^ inv_bits) | VD(dst_r) | VN(src1) | VM(src2)));
+ break;
+ case SLJIT_COPYSIGN_F64:
+ FAIL_IF(push_inst(compiler, (FMOV_R ^ ((op & SLJIT_32) ? (W_OP | (1 << 22)) : 0)) | VN(src2) | RD(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, (FABS ^ inv_bits) | VD(dst_r) | VN(src1)));
+ FAIL_IF(push_inst(compiler, TBZ | ((op & SLJIT_32) ? 0 : ((sljit_ins)1 << 31)) | (0x1f << 19) | (2 << 5) | RT(TMP_REG1)));
+ return push_inst(compiler, (FNEG ^ inv_bits) | VD(dst_r) | VN(dst_r));
+ }
+
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ return emit_fop_mem(compiler, mem_flags | STORE, TMP_FREG1, dst, dstw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f32 value)
+{
+ sljit_u32 exp;
+ union {
+ sljit_u32 imm;
+ sljit_f32 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset32(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm == 0)
+ return push_inst(compiler, (FMOV_R ^ (W_OP | (1 << 22))) | RN(TMP_ZERO) | VD(freg) | (1 << 16));
+
+ if ((u.imm << (32 - 19)) == 0) {
+ exp = (u.imm >> (23 + 2)) & 0x3f;
+
+ if (exp == 0x20 || exp == 0x1f)
+ return push_inst(compiler, (FMOV_I ^ (1 << 22)) | (sljit_ins)((((u.imm >> 24) & 0x80) | ((u.imm >> 19) & 0x7f)) << 13) | VD(freg));
+ }
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_s32)u.imm));
+ return push_inst(compiler, (FMOV_R ^ (W_OP | (1 << 22))) | RN(TMP_REG1) | VD(freg) | (1 << 16));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value)
+{
+ sljit_uw exp;
+ union {
+ sljit_uw imm;
+ sljit_f64 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset64(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm == 0)
+ return push_inst(compiler, FMOV_R | RN(TMP_ZERO) | VD(freg) | (sljit_ins)1 << 16);
+
+ if ((u.imm << (64 - 48)) == 0) {
+ exp = (u.imm >> (52 + 2)) & 0x1ff;
+
+ if (exp == 0x100 || exp == 0xff)
+ return push_inst(compiler, FMOV_I | (sljit_ins)((((u.imm >> 56) & 0x80) | ((u.imm >> 48) & 0x7f)) << 13) | VD(freg));
+ }
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_sw)u.imm));
+ return push_inst(compiler, FMOV_R | RN(TMP_REG1) | VD(freg) | (1 << 16));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg)
+{
+ sljit_ins inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
+
+ if (GET_OPCODE(op) == SLJIT_COPY_TO_F64)
+ inst = FMOV_R | RN(reg) | VD(freg) | (1 << 16);
+ else
+ inst = FMOV_R | VN(freg) | RD(reg);
+
+ if (op & SLJIT_32)
+ inst ^= W_OP | (1 << 22);
+
+ return push_inst(compiler, inst);
+}
+
+/* --------------------------------------------------------------------- */
+/* Conditional instructions */
+/* --------------------------------------------------------------------- */
+
+static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
+{
+ switch (type) {
+ case SLJIT_EQUAL:
+ case SLJIT_ATOMIC_STORED:
+ case SLJIT_F_EQUAL:
+ case SLJIT_ORDERED_EQUAL:
+ case SLJIT_UNORDERED_OR_EQUAL:
+ return 0x1;
+
+ case SLJIT_NOT_EQUAL:
+ case SLJIT_ATOMIC_NOT_STORED:
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_NOT_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ return 0x0;
+
+ case SLJIT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
+ return 0x3;
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_LESS:
+ return 0x2;
+
+ case SLJIT_NOT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
+ return 0x2;
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_GREATER_EQUAL:
+ return 0x3;
+
+ case SLJIT_GREATER:
+ case SLJIT_UNORDERED_OR_GREATER:
+ return 0x9;
+
+ case SLJIT_LESS_EQUAL:
+ case SLJIT_F_LESS_EQUAL:
+ case SLJIT_ORDERED_LESS_EQUAL:
+ return 0x8;
+
+ case SLJIT_SIG_LESS:
+ case SLJIT_UNORDERED_OR_LESS:
+ return 0xa;
+
+ case SLJIT_SIG_GREATER_EQUAL:
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_ORDERED_GREATER_EQUAL:
+ return 0xb;
+
+ case SLJIT_SIG_GREATER:
+ case SLJIT_F_GREATER:
+ case SLJIT_ORDERED_GREATER:
+ return 0xd;
+
+ case SLJIT_SIG_LESS_EQUAL:
+ case SLJIT_UNORDERED_OR_LESS_EQUAL:
+ return 0xc;
+
+ case SLJIT_OVERFLOW:
+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
+ return 0x0;
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_UNORDERED:
+ return 0x7;
+
+ case SLJIT_NOT_OVERFLOW:
+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
+ return 0x1;
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_ORDERED:
+ return 0x6;
+
+ case SLJIT_F_LESS:
+ case SLJIT_ORDERED_LESS:
+ return 0x5;
+
+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:
+ return 0x4;
+
+ default:
+ SLJIT_UNREACHABLE();
+ return 0xe;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_label(compiler));
+
+ if (compiler->last_label && compiler->last_label->size == compiler->size)
+ return compiler->last_label;
+
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+ PTR_FAIL_IF(!label);
+ set_label(label, compiler);
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, i;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (alignment <= SLJIT_LABEL_ALIGN_4) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);
+
+ for (i = (mask >> 2); i != 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ for (i = (buffers->size + 3) >> 2; i > 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
+{
+ struct sljit_jump *jump;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_jump(compiler, type));
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ type &= 0xff;
+
+ if (type < SLJIT_JUMP) {
+ jump->flags |= IS_COND;
+ PTR_FAIL_IF(push_inst(compiler, B_CC | (6 << 5) | get_cc(compiler, type)));
+ } else if (type >= SLJIT_FAST_CALL)
+ jump->flags |= IS_BL;
+
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG2)));
+
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += JUMP_MAX_SIZE - 1;
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types)
+{
+ SLJIT_UNUSED_ARG(arg_types);
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
+
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_jump(compiler, type);
+}
+
+static SLJIT_INLINE struct sljit_jump* emit_cmp_to0(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 src, sljit_sw srcw)
+{
+ struct sljit_jump *jump;
+ sljit_ins inv_bits = (type & SLJIT_32) ? W_OP : 0;
+
+ SLJIT_ASSERT((type & 0xff) == SLJIT_EQUAL || (type & 0xff) == SLJIT_NOT_EQUAL);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ jump->flags |= IS_CBZ | IS_COND;
+
+ if (src & SLJIT_MEM) {
+ PTR_FAIL_IF(emit_op_mem(compiler, inv_bits ? INT_SIZE : WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));
+ src = TMP_REG1;
+ }
+ else if (src == SLJIT_IMM) {
+ PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ src = TMP_REG1;
+ }
+
+ SLJIT_ASSERT(FAST_IS_REG(src));
+
+ if ((type & 0xff) == SLJIT_EQUAL)
+ inv_bits |= 1 << 24;
+
+ PTR_FAIL_IF(push_inst(compiler, (CBZ ^ inv_bits) | (6 << 5) | RT(src)));
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(push_inst(compiler, BR | RN(TMP_REG2)));
+
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += JUMP_MAX_SIZE - 1;
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
+{
+ struct sljit_jump *jump;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
+
+ if (src != SLJIT_IMM) {
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2));
+ src = TMP_REG2;
+ }
+ return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(src));
+ }
+
+ /* These jumps are converted to jump/call instructions when possible. */
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF(!jump);
+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
+ jump->u.target = (sljit_uw)srcw;
+
+ jump->addr = compiler->size;
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += JUMP_MAX_SIZE - 1;
+ return push_inst(compiler, ((type >= SLJIT_FAST_CALL) ? BLR : BR) | RN(TMP_REG2));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types,
+ sljit_s32 src, sljit_sw srcw)
+{
+ SLJIT_UNUSED_ARG(arg_types);
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));
+ src = TMP_REG1;
+ }
+
+ if (type & SLJIT_CALL_RETURN) {
+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src)));
+ src = TMP_REG1;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 0));
+ type = SLJIT_JUMP;
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, type, src, srcw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 type)
+{
+ sljit_s32 dst_r, src_r, flags, mem_flags;
+ sljit_ins cc;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ cc = get_cc(compiler, type);
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (GET_OPCODE(op) < SLJIT_ADD) {
+ FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(dst_r) | RN(TMP_ZERO) | RM(TMP_ZERO)));
+
+ if (dst & SLJIT_MEM) {
+ mem_flags = (GET_OPCODE(op) == SLJIT_MOV ? WORD_SIZE : INT_SIZE) | STORE;
+ return emit_op_mem(compiler, mem_flags, TMP_REG1, dst, dstw, TMP_REG2);
+ }
+
+ return SLJIT_SUCCESS;
+ }
+
+ flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
+ mem_flags = WORD_SIZE;
+
+ if (op & SLJIT_32) {
+ flags |= INT_OP;
+ mem_flags = INT_SIZE;
+ }
+
+ src_r = dst;
+
+ if (dst & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG1, dst, dstw, TMP_REG1));
+ src_r = TMP_REG1;
+ }
+
+ FAIL_IF(push_inst(compiler, CSINC | (cc << 12) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(TMP_ZERO)));
+ emit_op_imm(compiler, flags | GET_OPCODE(op), dst_r, src_r, TMP_REG2);
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, mem_flags | STORE, TMP_REG1, dst, dstw, TMP_REG2);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_reg)
+{
+ sljit_ins inv_bits = (type & SLJIT_32) ? W_OP : 0;
+ sljit_ins op = CSEL;
+ sljit_ins cmp = 0;
+ sljit_ins cc;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ if (src1 == SLJIT_IMM) {
+ if (type & SLJIT_32)
+ src1w = (sljit_s32)src1w;
+
+ if (src1w <= 1 && src1w >= -1) {
+ src1 = TMP_ZERO;
+ cmp = (SUBI ^ inv_bits) | (1 << 29) | RD(TMP_ZERO);
+
+ if (src1w == 1) {
+ op = CSINC;
+ cmp = (SUBI ^ inv_bits) | (1 << 29) | RD(TMP_ZERO) | (1 << 10);
+ } else if (src1w == -1) {
+ op = CSINV;
+ cmp = (ADDI ^ inv_bits) | (1 << 29) | RD(TMP_ZERO) | (1 << 10);
+ }
+
+ src1w = 0;
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, src1w));
+ src1 = TMP_REG2;
+ }
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src1, src1w, TMP_REG2));
+ src1 = TMP_REG2;
+ }
+
+ if (type & SLJIT_COMPARE_SELECT) {
+ type ^= 0x1;
+ if (cmp == 0)
+ cmp = (SUB ^ inv_bits) | (1 << 29) | RD(TMP_ZERO) | RM(src1);
+ FAIL_IF(push_inst(compiler, cmp | RN(src2_reg)));
+ }
+
+ cc = get_cc(compiler, type & ~(SLJIT_32 | SLJIT_COMPARE_SELECT));
+ return push_inst(compiler, (op ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(src2_reg) | RM(src1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_freg)
+{
+ sljit_ins inv_bits = (type & SLJIT_32) ? (1 << 22) : 0;
+ sljit_ins cc;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (type & SLJIT_32) ? INT_SIZE : WORD_SIZE, TMP_FREG2, src1, src1w));
+ src1 = TMP_FREG2;
+ }
+
+ cc = get_cc(compiler, type & ~SLJIT_32);
+ return push_inst(compiler, (FCSEL ^ inv_bits) | (cc << 12) | VD(dst_freg) | VN(src2_freg) | VM(src1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_u32 inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
+
+ if (!(reg & REG_PAIR_MASK))
+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
+
+ ADJUST_LOCAL_OFFSET(mem, memw);
+
+ if (!(mem & REG_MASK)) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, memw & ~0x1f8));
+
+ mem = SLJIT_MEM1(TMP_REG1);
+ memw &= 0x1f8;
+ } else if (mem & OFFS_REG_MASK) {
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(mem & REG_MASK) | RM(OFFS_REG(mem)) | ((sljit_ins)(memw & 0x3) << 10)));
+
+ mem = SLJIT_MEM1(TMP_REG1);
+ memw = 0;
+ } else if ((memw & 0x7) != 0 || memw > 0x1f8 || memw < -0x200) {
+ inst = ADDI;
+
+ if (memw < 0) {
+ /* Remains negative for integer min. */
+ memw = -memw;
+ inst = SUBI;
+ } else if ((memw & 0x7) == 0 && memw <= 0x7ff0) {
+ if (!(type & SLJIT_MEM_STORE) && (mem & REG_MASK) == REG_PAIR_FIRST(reg)) {
+ FAIL_IF(push_inst(compiler, LDRI | RD(REG_PAIR_SECOND(reg)) | RN(mem & REG_MASK) | ((sljit_ins)memw << 7)));
+ return push_inst(compiler, LDRI | RD(REG_PAIR_FIRST(reg)) | RN(mem & REG_MASK) | ((sljit_ins)(memw + 0x8) << 7));
+ }
+
+ inst = (type & SLJIT_MEM_STORE) ? STRI : LDRI;
+
+ FAIL_IF(push_inst(compiler, inst | RD(REG_PAIR_FIRST(reg)) | RN(mem & REG_MASK) | ((sljit_ins)memw << 7)));
+ return push_inst(compiler, inst | RD(REG_PAIR_SECOND(reg)) | RN(mem & REG_MASK) | ((sljit_ins)(memw + 0x8) << 7));
+ }
+
+ if ((sljit_uw)memw <= 0xfff) {
+ FAIL_IF(push_inst(compiler, inst | RD(TMP_REG1) | RN(mem & REG_MASK) | ((sljit_ins)memw << 10)));
+ memw = 0;
+ } else if ((sljit_uw)memw <= 0xffffff) {
+ FAIL_IF(push_inst(compiler, inst | (1 << 22) | RD(TMP_REG1) | RN(mem & REG_MASK) | (((sljit_ins)memw >> 12) << 10)));
+
+ if ((memw & 0xe07) != 0) {
+ FAIL_IF(push_inst(compiler, inst | RD(TMP_REG1) | RN(TMP_REG1) | (((sljit_ins)memw & 0xfff) << 10)));
+ memw = 0;
+ } else {
+ memw &= 0xfff;
+ }
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, memw));
+ FAIL_IF(push_inst(compiler, (inst == ADDI ? ADD : SUB) | RD(TMP_REG1) | RN(mem & REG_MASK) | RM(TMP_REG1)));
+ memw = 0;
+ }
+
+ mem = SLJIT_MEM1(TMP_REG1);
+
+ if (inst == SUBI)
+ memw = -memw;
+ }
+
+ SLJIT_ASSERT((memw & 0x7) == 0 && memw <= 0x1f8 && memw >= -0x200);
+ return push_inst(compiler, ((type & SLJIT_MEM_STORE) ? STP : LDP) | RT(REG_PAIR_FIRST(reg)) | RT2(REG_PAIR_SECOND(reg)) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x3f8) << 12));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_u32 sign = 0, inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));
+
+ if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_MEM_SUPP)
+ return SLJIT_SUCCESS;
+
+ switch (type & 0xff) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400;
+ break;
+ case SLJIT_MOV_S8:
+ sign = 1;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_U8:
+ inst = STURBI | (MEM_SIZE_SHIFT(BYTE_SIZE) << 30) | 0x400;
+ break;
+ case SLJIT_MOV_S16:
+ sign = 1;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_U16:
+ inst = STURBI | (MEM_SIZE_SHIFT(HALF_SIZE) << 30) | 0x400;
+ break;
+ case SLJIT_MOV_S32:
+ sign = 1;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV32:
+ inst = STURBI | (MEM_SIZE_SHIFT(INT_SIZE) << 30) | 0x400;
+ break;
+ default:
+ SLJIT_UNREACHABLE();
+ inst = STURBI | (MEM_SIZE_SHIFT(WORD_SIZE) << 30) | 0x400;
+ break;
+ }
+
+ if (!(type & SLJIT_MEM_STORE))
+ inst |= sign ? 0x00800000 : 0x00400000;
+
+ if (!(type & SLJIT_MEM_POST))
+ inst |= 0x800;
+
+ return push_inst(compiler, inst | RT(reg) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x1ff) << 12));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 freg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_u32 inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw));
+
+ if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_MEM_SUPP)
+ return SLJIT_SUCCESS;
+
+ inst = STUR_FI | 0x80000400;
+
+ if (!(type & SLJIT_32))
+ inst |= 0x40000000;
+
+ if (!(type & SLJIT_MEM_STORE))
+ inst |= 0x00400000;
+
+ if (!(type & SLJIT_MEM_POST))
+ inst |= 0x800;
+
+ return push_inst(compiler, inst | VT(freg) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x1ff) << 12));
+}
+
+static sljit_s32 sljit_emit_simd_mem_offset(struct sljit_compiler *compiler, sljit_s32 *mem_ptr, sljit_sw memw)
+{
+ sljit_ins ins;
+ sljit_s32 mem = *mem_ptr;
+
+ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
+ *mem_ptr = TMP_REG2;
+ return push_inst(compiler, ADD | RD(TMP_REG2) | RN(mem & REG_MASK) | RM(OFFS_REG(mem)) | ((sljit_ins)(memw & 0x3) << 10));
+ }
+
+ if (!(mem & REG_MASK)) {
+ *mem_ptr = TMP_REG2;
+ return load_immediate(compiler, TMP_REG2, memw);
+ }
+
+ mem &= REG_MASK;
+
+ if (memw == 0) {
+ *mem_ptr = mem;
+ return SLJIT_SUCCESS;
+ }
+
+ *mem_ptr = TMP_REG2;
+
+ if (memw < -0xffffff || memw > 0xffffff) {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, memw));
+ return push_inst(compiler, ADD | RD(TMP_REG2) | RN(TMP_REG2) | RM(mem));
+ }
+
+ ins = ADDI;
+
+ if (memw < 0) {
+ memw = -memw;
+ ins = SUBI;
+ }
+
+ if (memw > 0xfff) {
+ FAIL_IF(push_inst(compiler, ins | (1 << 22) | RD(TMP_REG2) | RN(mem) | ((sljit_ins)(memw >> 12) << 10)));
+
+ memw &= 0xfff;
+ if (memw == 0)
+ return SLJIT_SUCCESS;
+
+ mem = TMP_REG2;
+ }
+
+ return push_inst(compiler, ins | RD(TMP_REG2) | RN(mem) | ((sljit_ins)memw << 10));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw));
+
+ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (!(srcdst & SLJIT_MEM)) {
+ if (type & SLJIT_SIMD_STORE)
+ ins = VD(srcdst) | VN(vreg) | VM(vreg);
+ else
+ ins = VD(vreg) | VN(srcdst) | VM(srcdst);
+
+ if (reg_size == 4)
+ ins |= (1 << 30);
+
+ return push_inst(compiler, ORR_v | ins);
+ }
+
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));
+
+ if (elem_size > 3)
+ elem_size = 3;
+
+ ins = (type & SLJIT_SIMD_STORE) ? ST1 : LD1;
+
+ if (reg_size == 4)
+ ins |= (1 << 30);
+
+ return push_inst(compiler, ins | ((sljit_ins)elem_size << 10) | RN(srcdst) | VT(vreg));
+}
+
+static sljit_ins simd_get_imm(sljit_s32 elem_size, sljit_uw value)
+{
+ sljit_ins result;
+
+ if (elem_size > 2 && (sljit_u32)value == (value >> 32)) {
+ elem_size = 2;
+ value = (sljit_u32)value;
+ }
+
+ if (elem_size == 2 && (sljit_u16)value == (value >> 16)) {
+ elem_size = 1;
+ value = (sljit_u16)value;
+ }
+
+ if (elem_size == 1 && (sljit_u8)value == (value >> 8)) {
+ elem_size = 0;
+ value = (sljit_u8)value;
+ }
+
+ switch (elem_size) {
+ case 0:
+ SLJIT_ASSERT(value <= 0xff);
+ result = 0xe000;
+ break;
+ case 1:
+ SLJIT_ASSERT(value <= 0xffff);
+ result = 0;
+
+ while (1) {
+ if (value <= 0xff) {
+ result |= 0x8000;
+ break;
+ }
+
+ if ((value & 0xff) == 0) {
+ value >>= 8;
+ result |= 0xa000;
+ break;
+ }
+
+ if (result != 0)
+ return ~(sljit_ins)0;
+
+ value ^= (sljit_uw)0xffff;
+ result = (1 << 29);
+ }
+ break;
+ case 2:
+ SLJIT_ASSERT(value <= 0xffffffff);
+ result = 0;
+
+ while (1) {
+ if (value <= 0xff) {
+ result |= 0x0000;
+ break;
+ }
+
+ if ((value & ~(sljit_uw)0xff00) == 0) {
+ value >>= 8;
+ result |= 0x2000;
+ break;
+ }
+
+ if ((value & ~(sljit_uw)0xff0000) == 0) {
+ value >>= 16;
+ result |= 0x4000;
+ break;
+ }
+
+ if ((value & ~(sljit_uw)0xff000000) == 0) {
+ value >>= 24;
+ result |= 0x6000;
+ break;
+ }
+
+ if ((value & (sljit_uw)0xff) == 0xff && (value >> 16) == 0) {
+ value >>= 8;
+ result |= 0xc000;
+ break;
+ }
+
+ if ((value & (sljit_uw)0xffff) == 0xffff && (value >> 24) == 0) {
+ value >>= 16;
+ result |= 0xd000;
+ break;
+ }
+
+ if (result != 0)
+ return ~(sljit_ins)0;
+
+ value ^= (sljit_uw)0xffffffff;
+ result = (1 << 29);
+ }
+ break;
+ default:
+ return ~(sljit_ins)0;
+ }
+
+ return (((sljit_ins)value & 0x1f) << 5) | (((sljit_ins)value & 0xe0) << 11) | result;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins, imm;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw));
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));
+
+ ins = (sljit_ins)elem_size << 10;
+
+ if (reg_size == 4)
+ ins |= (sljit_ins)1 << 30;
+
+ return push_inst(compiler, LD1R | ins | RN(src) | VT(vreg));
+ }
+
+ ins = (sljit_ins)1 << (16 + elem_size);
+
+ if (reg_size == 4)
+ ins |= (sljit_ins)1 << 30;
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (src == SLJIT_IMM)
+ return push_inst(compiler, MOVI | (ins & ((sljit_ins)1 << 30)) | VD(vreg));
+
+ return push_inst(compiler, DUP_e | ins | VD(vreg) | VN(src));
+ }
+
+ if (src == SLJIT_IMM) {
+ if (elem_size < 3)
+ srcw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1;
+
+ imm = simd_get_imm(elem_size, (sljit_uw)srcw);
+
+ if (imm != ~(sljit_ins)0) {
+ imm |= ins & ((sljit_ins)1 << 30);
+
+ return push_inst(compiler, MOVI | imm | VD(vreg));
+ }
+
+ FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));
+ src = TMP_REG2;
+ }
+
+ return push_inst(compiler, DUP_g | ins | VD(vreg) | RN(src));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg, sljit_s32 lane_index,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw));
+
+ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (type & SLJIT_SIMD_LANE_ZERO) {
+ ins = (reg_size == 3) ? 0 : ((sljit_ins)1 << 30);
+
+ if ((type & SLJIT_SIMD_FLOAT) && vreg == srcdst) {
+ FAIL_IF(push_inst(compiler, ORR_v | ins | VD(TMP_FREG1) | VN(vreg) | VM(vreg)));
+ srcdst = TMP_FREG1;
+ srcdstw = 0;
+ }
+
+ FAIL_IF(push_inst(compiler, MOVI | ins | VD(vreg)));
+ }
+
+ if (srcdst & SLJIT_MEM) {
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));
+
+ if (elem_size == 3)
+ ins = 0x8400;
+ else if (elem_size == 0)
+ ins = 0;
+ else
+ ins = (sljit_ins)0x2000 << elem_size;
+
+ lane_index = lane_index << elem_size;
+ ins |= (sljit_ins)(((lane_index & 0x8) << 27) | ((lane_index & 0x7) << 10));
+
+ return push_inst(compiler, ((type & SLJIT_SIMD_STORE) ? ST1_s : LD1_s) | ins | RN(srcdst) | VT(vreg));
+ }
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (type & SLJIT_SIMD_STORE)
+ ins = INS_e | ((sljit_ins)1 << (16 + elem_size)) | ((sljit_ins)lane_index << (11 + elem_size)) | VD(srcdst) | VN(vreg);
+ else
+ ins = INS_e | ((((sljit_ins)lane_index << 1) | 1) << (16 + elem_size)) | VD(vreg) | VN(srcdst);
+
+ return push_inst(compiler, ins);
+ }
+
+ if (srcdst == SLJIT_IMM) {
+ if (elem_size < 3)
+ srcdstw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1;
+
+ FAIL_IF(load_immediate(compiler, TMP_REG2, srcdstw));
+ srcdst = TMP_REG2;
+ }
+
+ if (type & SLJIT_SIMD_STORE) {
+ ins = RD(srcdst) | VN(vreg);
+
+ if ((type & SLJIT_SIMD_LANE_SIGNED) && (elem_size < 2 || (elem_size == 2 && !(type & SLJIT_32)))) {
+ ins |= SMOV;
+
+ if (!(type & SLJIT_32))
+ ins |= (sljit_ins)1 << 30;
+ } else
+ ins |= UMOV;
+ } else
+ ins = INS | VD(vreg) | RN(srcdst);
+
+ if (elem_size == 3)
+ ins |= (sljit_ins)1 << 30;
+
+ return push_inst(compiler, ins | ((((sljit_ins)lane_index << 1) | 1) << (16 + elem_size)));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_s32 src_lane_index)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index));
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ ins = (((sljit_ins)src_lane_index << 1) | 1) << (16 + elem_size);
+
+ if (reg_size == 4)
+ ins |= (sljit_ins)1 << 30;
+
+ return push_inst(compiler, DUP_e | ins | VD(vreg) | VN(src));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw));
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size != 2 || elem2_size != 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));
+
+ if (reg_size == 4 && elem2_size - elem_size == 1)
+ FAIL_IF(push_inst(compiler, LD1 | ((sljit_ins)elem_size << 10) | RN(src) | VT(vreg)));
+ else
+ FAIL_IF(push_inst(compiler, LD1_s | ((sljit_ins)0x2000 << (reg_size - elem2_size + elem_size)) | RN(src) | VT(vreg)));
+ src = vreg;
+ }
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ SLJIT_ASSERT(reg_size == 4);
+ return push_inst(compiler, FCVTL | (1 << 22) | VD(vreg) | VN(src));
+ }
+
+ do {
+ FAIL_IF(push_inst(compiler, ((type & SLJIT_SIMD_EXTEND_SIGNED) ? SSHLL : USHLL)
+ | ((sljit_ins)1 << (19 + elem_size)) | VD(vreg) | VN(src)));
+ src = vreg;
+ } while (++elem_size < elem2_size);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins, imms;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw));
+
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ switch (elem_size) {
+ case 0:
+ imms = 0x643219;
+ ins = USHR | (0x9 << 16);
+ break;
+ case 1:
+ imms = (reg_size == 4) ? 0x643219 : 0x6231;
+ ins = USHR | (0x11 << 16);
+ break;
+ case 2:
+ imms = (reg_size == 4) ? 0x6231 : 0x61;
+ ins = USHR | (0x21 << 16);
+ break;
+ default:
+ imms = 0x61;
+ ins = USHR | (0x41 << 16);
+ break;
+ }
+
+ if (reg_size == 4)
+ ins |= (1 << 30);
+
+ FAIL_IF(push_inst(compiler, ins | VD(TMP_FREG1) | VN(vreg)));
+
+ if (reg_size == 4 && elem_size > 0)
+ FAIL_IF(push_inst(compiler, XTN | ((sljit_ins)(elem_size - 1) << 22) | VD(TMP_FREG1) | VN(TMP_FREG1)));
+
+ if (imms >= 0x100) {
+ ins = (reg_size == 4 && elem_size == 0) ? (1 << 30) : 0;
+
+ do {
+ FAIL_IF(push_inst(compiler, USRA | ins | ((imms & 0xff) << 16) | VD(TMP_FREG1) | VN(TMP_FREG1)));
+ imms >>= 8;
+ } while (imms >= 0x100);
+ }
+
+ FAIL_IF(push_inst(compiler, USRA | (1 << 30) | (imms << 16) | VD(TMP_FREG1) | VN(TMP_FREG1)));
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ ins = (0x1 << 16);
+
+ if (reg_size == 4 && elem_size == 0) {
+ FAIL_IF(push_inst(compiler, INS_e | (0x3 << 16) | (0x8 << 11) | VD(TMP_FREG1) | VN(TMP_FREG1)));
+ ins = (0x2 << 16);
+ }
+
+ FAIL_IF(push_inst(compiler, UMOV | ins | RD(dst_r) | VN(TMP_FREG1)));
+
+ if (dst_r == TMP_REG2)
+ return emit_op_mem(compiler, STORE | ((type & SLJIT_32) ? INT_SIZE : WORD_SIZE), TMP_REG2, dst, dstw, TMP_REG1);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ switch (SLJIT_SIMD_GET_OPCODE(type)) {
+ case SLJIT_SIMD_OP2_AND:
+ ins = AND_v;
+ break;
+ case SLJIT_SIMD_OP2_OR:
+ ins = ORR_v;
+ break;
+ case SLJIT_SIMD_OP2_XOR:
+ ins = EOR_v;
+ break;
+ case SLJIT_SIMD_OP2_SHUFFLE:
+ ins = TBL_v;
+ break;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ if (elem_size > 3)
+ elem_size = 3;
+
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src2, src2w));
+ push_inst(compiler, LD1 | (reg_size == 4 ? (1 << 30) : 0) | ((sljit_ins)elem_size << 10) | RN(src2) | VT(TMP_FREG1));
+ src2 = TMP_FREG1;
+ }
+
+ if (reg_size == 4)
+ ins |= (sljit_ins)1 << 30;
+
+ return push_inst(compiler, ins | VD(dst_vreg) | VN(src1_vreg) | VM(src2));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 mem_reg)
+{
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));
+
+#ifndef __ARM_FEATURE_ATOMICS
+ if (op & SLJIT_ATOMIC_USE_CAS)
+ return SLJIT_ERR_UNSUPPORTED;
+#endif /* ARM_FEATURE_ATOMICS */
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_S8:
+ case SLJIT_MOV_S16:
+ case SLJIT_MOV_S32:
+ return SLJIT_ERR_UNSUPPORTED;
+
+ case SLJIT_MOV32:
+ case SLJIT_MOV_U32:
+#ifdef __ARM_FEATURE_ATOMICS
+ if (!(op & SLJIT_ATOMIC_USE_LS))
+ ins = LDR ^ (1 << 30);
+ else
+#endif /* ARM_FEATURE_ATOMICS */
+ ins = LDXR ^ (1 << 30);
+ break;
+ case SLJIT_MOV_U8:
+#ifdef __ARM_FEATURE_ATOMICS
+ if (!(op & SLJIT_ATOMIC_USE_LS))
+ ins = LDRB;
+ else
+#endif /* ARM_FEATURE_ATOMICS */
+ ins = LDXRB;
+ break;
+ case SLJIT_MOV_U16:
+#ifdef __ARM_FEATURE_ATOMICS
+ if (!(op & SLJIT_ATOMIC_USE_LS))
+ ins = LDRH;
+ else
+#endif /* ARM_FEATURE_ATOMICS */
+ ins = LDXRH;
+ break;
+ default:
+#ifdef __ARM_FEATURE_ATOMICS
+ if (!(op & SLJIT_ATOMIC_USE_LS))
+ ins = LDR;
+ else
+#endif /* ARM_FEATURE_ATOMICS */
+ ins = LDXR;
+ break;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, ins | RN(mem_reg) | RT(dst_reg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src_reg,
+ sljit_s32 mem_reg,
+ sljit_s32 temp_reg)
+{
+ sljit_ins ins;
+ sljit_ins cmp = 0;
+ SLJIT_UNUSED_ARG(temp_reg); /* !__ARM_FEATURE_ATOMICS */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));
+
+#ifdef __ARM_FEATURE_ATOMICS
+ if (!(op & SLJIT_ATOMIC_USE_LS)) {
+ if (op & SLJIT_SET_ATOMIC_STORED)
+ cmp = (SUBS ^ W_OP) | RD(TMP_ZERO);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_S8:
+ case SLJIT_MOV_S16:
+ case SLJIT_MOV_S32:
+ return SLJIT_ERR_UNSUPPORTED;
+
+ case SLJIT_MOV32:
+ case SLJIT_MOV_U32:
+ ins = CAS ^ (1 << 30);
+ break;
+ case SLJIT_MOV_U16:
+ ins = CASH;
+ break;
+ case SLJIT_MOV_U8:
+ ins = CASB;
+ break;
+ default:
+ ins = CAS;
+ if (cmp)
+ cmp ^= W_OP;
+ break;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ if (cmp)
+ FAIL_IF(push_inst(compiler, ((MOV ^ W_OP) ^ (cmp & W_OP)) | RM(temp_reg) | RD(TMP_REG2)));
+
+ FAIL_IF(push_inst(compiler, ins | RM(temp_reg) | RN(mem_reg) | RD(src_reg)));
+ if (!cmp)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, cmp | RM(TMP_REG2) | RN(temp_reg));
+ }
+#else /* !__ARM_FEATURE_ATOMICS */
+ if (op & SLJIT_ATOMIC_USE_CAS)
+ return SLJIT_ERR_UNSUPPORTED;
+#endif /* __ARM_FEATURE_ATOMICS */
+
+ if (op & SLJIT_SET_ATOMIC_STORED)
+ cmp = (SUBI ^ W_OP) | (1 << 29);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_S8:
+ case SLJIT_MOV_S16:
+ case SLJIT_MOV_S32:
+ return SLJIT_ERR_UNSUPPORTED;
+
+ case SLJIT_MOV32:
+ case SLJIT_MOV_U32:
+ ins = STXR ^ (1 << 30);
+ break;
+ case SLJIT_MOV_U8:
+ ins = STXRB;
+ break;
+ case SLJIT_MOV_U16:
+ ins = STXRH;
+ break;
+ default:
+ ins = STXR;
+ break;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst(compiler, ins | RM(TMP_REG2) | RN(mem_reg) | RT(src_reg)));
+ if (!cmp)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, cmp | RD(TMP_ZERO) | RN(TMP_REG2));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
+{
+ sljit_s32 dst_reg;
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);
+
+ dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ /* Not all instruction forms support accessing SP register. */
+ if (offset <= 0xffffff && offset >= -0xffffff) {
+ ins = ADDI;
+ if (offset < 0) {
+ offset = -offset;
+ ins = SUBI;
+ }
+
+ if (offset <= 0xfff)
+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (sljit_ins)(offset << 10)));
+ else {
+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (sljit_ins)((offset & 0xfff000) >> (12 - 10)) | (1 << 22)));
+
+ offset &= 0xfff;
+ if (offset != 0)
+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(dst_reg) | (sljit_ins)(offset << 10)));
+ }
+ }
+ else {
+ FAIL_IF(load_immediate (compiler, dst_reg, offset));
+ /* Add extended register form. */
+ FAIL_IF(push_inst(compiler, ADDE | (0x3 << 13) | RD(dst_reg) | RN(SLJIT_SP) | RM(dst_reg)));
+ }
+
+ if (SLJIT_UNLIKELY(dst & SLJIT_MEM))
+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG1);
+ return SLJIT_SUCCESS;
+}
+
+#define SLJIT_EMIT_CONST_U8(c) \
+ (((c) & 0x100) != 0 ? (MOVN | (sljit_ins)((~(c) & 0xff) << 5)) : (MOVZ | (sljit_ins)(((c) & 0xff) << 5)))
+#define SLJIT_EMIT_CONST_S32(c) \
+ (((c) < 0) ? (MOVN | (sljit_ins)((~(c) & 0xffff) << 5)) : (MOVZ | (sljit_ins)(((c) & 0xffff) << 5)))
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
+{
+ struct sljit_const *const_;
+ sljit_s32 dst_r;
+ sljit_s32 mem_flags = WORD_SIZE | STORE;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+ PTR_FAIL_IF(!const_);
+ set_const(const_, compiler);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ PTR_FAIL_IF(push_inst(compiler, SLJIT_EMIT_CONST_U8(init_value) | RD(dst_r)));
+ mem_flags = BYTE_SIZE | STORE;
+ break;
+
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ if (GET_OPCODE(op) == SLJIT_MOV32) {
+ init_value = (sljit_u32)init_value;
+ mem_flags = INT_SIZE | STORE;
+ } else
+ init_value = (sljit_s32)init_value;
+
+ PTR_FAIL_IF(push_inst(compiler, SLJIT_EMIT_CONST_S32(init_value) | RD(dst_r)));
+ PTR_FAIL_IF(push_inst(compiler, MOVK | (1 << 21) | (sljit_ins)((init_value >> 11) & 0x1fffe0) | RD(dst_r)));
+ break;
+
+ default:
+ PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, (sljit_uw)init_value));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, dst, dstw, TMP_REG2));
+ return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_jump *jump;
+ sljit_s32 dst_r, target_r;
+ SLJIT_UNUSED_ARG(op);
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = TMP_REG2;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2));
+ }
+
+ PTR_FAIL_IF(push_inst(compiler, RD(target_r)));
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_mov_addr(jump, compiler, 1);
+
+ compiler->size += 3;
+
+ if (op == SLJIT_ADD_ABS_ADDR)
+ PTR_FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RN(dst_r) | RM(TMP_REG2)));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
+
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
+{
+ sljit_ins* inst = (sljit_ins*)addr;
+ sljit_u32 dst;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);
+
+ dst = inst[0] & 0x1f;
+ SLJIT_ASSERT((inst[0] & 0xffe00000) == MOVZ && (inst[1] & 0xffe00000) == (MOVK | (1 << 21)));
+ inst[0] = MOVZ | dst | (((sljit_u32)new_target & 0xffff) << 5);
+ inst[1] = MOVK | dst | (((sljit_u32)(new_target >> 16) & 0xffff) << 5) | (1 << 21);
+ inst[2] = MOVK | dst | (((sljit_u32)(new_target >> 32) & 0xffff) << 5) | (2 << 21);
+ inst[3] = MOVK | dst | ((sljit_u32)(new_target >> 48) << 5) | (3 << 21);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 4);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
+{
+ sljit_ins* inst;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ inst = (sljit_ins*)addr;
+ SLJIT_ASSERT((inst[0] & 0xffe00000) == MOVZ || (inst[0] & 0xffe00000) == MOVN);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
+ inst[0] = SLJIT_EMIT_CONST_U8(new_constant) | (inst[0] & 0x1f);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
+ return;
+
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ if (GET_OPCODE(op) == SLJIT_MOV32)
+ new_constant = (sljit_u32)new_constant;
+ else
+ new_constant = (sljit_s32)new_constant;
+
+ inst = (sljit_ins*)addr;
+ SLJIT_ASSERT(((inst[0] & 0xffe00000) == MOVZ || (inst[0] & 0xffe00000) == MOVN) && (inst[1] & 0xffe00000) == (MOVK | (1 << 21)));
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ inst[0] = SLJIT_EMIT_CONST_S32(new_constant) | (inst[0] & 0x1f);
+ inst[1] = MOVK | (1 << 21) | (sljit_ins)((new_constant >> 11) & 0x1fffe0) | (inst[1] & 0x1f);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ return;
+
+ default:
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ return;
+ }
+}
diff --git a/deps/sljit/sljit_src/sljitNativeARM_T2_32.c b/deps/sljit/sljit_src/sljitNativeARM_T2_32.c
new file mode 100644
index 0000000..6608457
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativeARM_T2_32.c
@@ -0,0 +1,4625 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
+{
+#ifdef __SOFTFP__
+ return "ARM-Thumb2" SLJIT_CPUINFO " ABI:softfp";
+#else
+ return "ARM-Thumb2" SLJIT_CPUINFO " ABI:hardfp";
+#endif
+}
+
+/* Length of an instruction word. */
+typedef sljit_u32 sljit_ins;
+
+/* Last register + 1. */
+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
+#define TMP_PC (SLJIT_NUMBER_OF_REGISTERS + 4)
+
+#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
+
+/* See sljit_emit_enter and sljit_emit_op0 if you want to change them. */
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
+ 0, 0, 1, 2, 3, 11, 10, 9, 8, 7, 6, 5, 4, 13, 12, 14, 15
+};
+
+static const sljit_u8 freg_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) + 1] = {
+ 0,
+ 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6,
+ 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6
+};
+
+static const sljit_u8 freg_ebit_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1) + 1] = {
+ 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1
+};
+
+#define COPY_BITS(src, from, to, bits) \
+ ((from >= to ? ((sljit_ins)(src) >> (from - to)) : ((sljit_ins)(src) << (to - from))) & (((1 << bits) - 1) << to))
+
+#define NEGATE(uimm) ((sljit_uw)-(sljit_sw)(uimm))
+
+/* Thumb16 encodings. */
+#define RD3(rd) ((sljit_ins)reg_map[rd])
+#define RN3(rn) ((sljit_ins)reg_map[rn] << 3)
+#define RM3(rm) ((sljit_ins)reg_map[rm] << 6)
+#define RDN3(rdn) ((sljit_ins)reg_map[rdn] << 8)
+#define IMM3(imm) ((sljit_ins)imm << 6)
+#define IMM8(imm) ((sljit_ins)imm)
+
+/* Thumb16 helpers. */
+#define SET_REGS44(rd, rn) \
+ (((sljit_ins)reg_map[rn] << 3) | ((sljit_ins)reg_map[rd] & 0x7) | (((sljit_ins)reg_map[rd] & 0x8) << 4))
+#define IS_2_LO_REGS(reg1, reg2) \
+ (reg_map[reg1] <= 7 && reg_map[reg2] <= 7)
+#define IS_3_LO_REGS(reg1, reg2, reg3) \
+ (reg_map[reg1] <= 7 && reg_map[reg2] <= 7 && reg_map[reg3] <= 7)
+
+/* Thumb32 encodings. */
+#define RM4(rm) ((sljit_ins)reg_map[rm])
+#define RD4(rd) ((sljit_ins)reg_map[rd] << 8)
+#define RT4(rt) ((sljit_ins)reg_map[rt] << 12)
+#define RN4(rn) ((sljit_ins)reg_map[rn] << 16)
+
+#define VM4(vm) (((sljit_ins)freg_map[vm]) | ((sljit_ins)freg_ebit_map[vm] << 5))
+#define VD4(vd) (((sljit_ins)freg_map[vd] << 12) | ((sljit_ins)freg_ebit_map[vd] << 22))
+#define VN4(vn) (((sljit_ins)freg_map[vn] << 16) | ((sljit_ins)freg_ebit_map[vn] << 7))
+
+#define IMM5(imm) \
+ (COPY_BITS(imm, 2, 12, 3) | (((sljit_ins)imm & 0x3) << 6))
+#define IMM12(imm) \
+ (COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | ((sljit_ins)imm & 0xff))
+
+/* --------------------------------------------------------------------- */
+/* Instruction forms */
+/* --------------------------------------------------------------------- */
+
+/* dot '.' changed to _
+ I immediate form (possibly followed by number of immediate bits). */
+#define ADCI 0xf1400000
+#define ADCS 0x4140
+#define ADC_W 0xeb400000
+#define ADD 0x4400
+#define ADDS 0x1800
+#define ADDSI3 0x1c00
+#define ADDSI8 0x3000
+#define ADDWI 0xf2000000
+#define ADD_SP 0x4485
+#define ADD_SP_I 0xb000
+#define ADD_W 0xeb000000
+#define ADD_WI 0xf1000000
+#define ANDI 0xf0000000
+#define ANDS 0x4000
+#define AND_W 0xea000000
+#define ASRS 0x4100
+#define ASRSI 0x1000
+#define ASR_W 0xfa40f000
+#define ASR_WI 0xea4f0020
+#define BCC 0xd000
+#define BICI 0xf0200000
+#define BKPT 0xbe00
+#define BLX 0x4780
+#define BX 0x4700
+#define CLZ 0xfab0f080
+#define CMNI_W 0xf1100f00
+#define CMP 0x4280
+#define CMPI 0x2800
+#define CMPI_W 0xf1b00f00
+#define CMP_X 0x4500
+#define CMP_W 0xebb00f00
+#define DMB_SY 0xf3bf8f5f
+#define EORI 0xf0800000
+#define EORS 0x4040
+#define EOR_W 0xea800000
+#define IT 0xbf00
+#define LDR 0xf8d00000
+#define LDR_SP 0x9800
+#define LDRD 0xe9500000
+#define LDREX 0xe8500f00
+#define LDREXB 0xe8d00f4f
+#define LDREXH 0xe8d00f5f
+#define LDRI 0xf8500800
+#define LSLS 0x4080
+#define LSLSI 0x0000
+#define LSL_W 0xfa00f000
+#define LSL_WI 0xea4f0000
+#define LSRS 0x40c0
+#define LSRSI 0x0800
+#define LSR_W 0xfa20f000
+#define LSR_WI 0xea4f0010
+#define MLA 0xfb000000
+#define MOV 0x4600
+#define MOVI 0x2000
+#define MOVS 0x0000
+#define MOVSI 0x2000
+#define MOVT 0xf2c00000
+#define MOVW 0xf2400000
+#define MOV_W 0xea4f0000
+#define MOV_WI 0xf04f0000
+#define MUL 0xfb00f000
+#define MVNS 0x43c0
+#define MVN_W 0xea6f0000
+#define MVN_WI 0xf06f0000
+#define NOP 0xbf00
+#define ORNI 0xf0600000
+#define ORRI 0xf0400000
+#define ORRS 0x4300
+#define ORR_W 0xea400000
+#define POP 0xbc00
+#define POP_W 0xe8bd0000
+#define PUSH 0xb400
+#define PUSH_W 0xe92d0000
+#define REV 0xba00
+#define REV_W 0xfa90f080
+#define REV16 0xba40
+#define REV16_W 0xfa90f090
+#define RBIT 0xfa90f0a0
+#define RORS 0x41c0
+#define ROR_W 0xfa60f000
+#define ROR_WI 0xea4f0030
+#define RSB_WI 0xf1c00000
+#define RSBSI 0x4240
+#define SBCI 0xf1600000
+#define SBCS 0x4180
+#define SBC_W 0xeb600000
+#define SDIV 0xfb90f0f0
+#define SMULL 0xfb800000
+#define STR_SP 0x9000
+#define STRD 0xe9400000
+#define STREX 0xe8400000
+#define STREXB 0xe8c00f40
+#define STREXH 0xe8c00f50
+#define SUBS 0x1a00
+#define SUBSI3 0x1e00
+#define SUBSI8 0x3800
+#define SUB_W 0xeba00000
+#define SUBWI 0xf2a00000
+#define SUB_SP_I 0xb080
+#define SUB_WI 0xf1a00000
+#define SXTB 0xb240
+#define SXTB_W 0xfa4ff080
+#define SXTH 0xb200
+#define SXTH_W 0xfa0ff080
+#define TST 0x4200
+#define TSTI 0xf0000f00
+#define TST_W 0xea000f00
+#define UDIV 0xfbb0f0f0
+#define UMULL 0xfba00000
+#define UXTB 0xb2c0
+#define UXTB_W 0xfa5ff080
+#define UXTH 0xb280
+#define UXTH_W 0xfa1ff080
+#define VABS_F32 0xeeb00ac0
+#define VADD_F32 0xee300a00
+#define VAND 0xef000110
+#define VCMP_F32 0xeeb40a40
+#define VCVT_F32_S32 0xeeb80ac0
+#define VCVT_F32_U32 0xeeb80a40
+#define VCVT_F64_F32 0xeeb70ac0
+#define VCVT_S32_F32 0xeebd0ac0
+#define VDIV_F32 0xee800a00
+#define VDUP 0xee800b10
+#define VDUP_s 0xffb00c00
+#define VEOR 0xff000110
+#define VLD1 0xf9200000
+#define VLD1_r 0xf9a00c00
+#define VLD1_s 0xf9a00000
+#define VLDR_F32 0xed100a00
+#define VMOV_F32 0xeeb00a40
+#define VMOV 0xee000a10
+#define VMOV2 0xec400a10
+#define VMOV_i 0xef800010
+#define VMOV_s 0xee000b10
+#define VMOVN 0xffb20200
+#define VMRS 0xeef1fa10
+#define VMUL_F32 0xee200a00
+#define VNEG_F32 0xeeb10a40
+#define VORR 0xef200110
+#define VPOP 0xecbd0b00
+#define VPUSH 0xed2d0b00
+#define VSHLL 0xef800a10
+#define VSHR 0xef800010
+#define VSRA 0xef800110
+#define VST1 0xf9000000
+#define VST1_s 0xf9800000
+#define VSTR_F32 0xed000a00
+#define VSUB_F32 0xee300a40
+#define VTBL 0xffb00800
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+
+static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32)
+{
+ if (compiler->scratches == -1)
+ return 0;
+
+ if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0))
+ fr -= SLJIT_F64_SECOND(0);
+
+ return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->real_fscratches))
+ || (fr > (SLJIT_FS0 - compiler->real_fsaveds) && fr <= SLJIT_FS0)
+ || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));
+}
+
+static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type)
+{
+ sljit_s32 vr_low = vr;
+
+ if (compiler->scratches == -1)
+ return 0;
+
+ if (SLJIT_SIMD_GET_REG_SIZE(type) == 4) {
+ vr += (vr & 0x1);
+ vr_low = vr - 1;
+ }
+
+ return (vr >= SLJIT_VR0 && vr < (SLJIT_VR0 + compiler->vscratches))
+ || (vr_low > (SLJIT_VS0 - compiler->vsaveds) && vr_low <= SLJIT_VS0)
+ || (vr >= SLJIT_TMP_VREGISTER_BASE && vr < (SLJIT_TMP_VREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS));
+}
+
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+static sljit_s32 push_inst16(struct sljit_compiler *compiler, sljit_ins inst)
+{
+ sljit_u16 *ptr;
+ SLJIT_ASSERT(!(inst & 0xffff0000));
+
+ ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_u16));
+ FAIL_IF(!ptr);
+ *ptr = (sljit_u16)(inst);
+ compiler->size++;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 push_inst32(struct sljit_compiler *compiler, sljit_ins inst)
+{
+ sljit_u16 *ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ *ptr++ = (sljit_u16)(inst >> 16);
+ *ptr = (sljit_u16)(inst);
+ compiler->size += 2;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_imm32_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm)
+{
+ FAIL_IF(push_inst32(compiler, MOVW | RD4(dst)
+ | COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)));
+ return push_inst32(compiler, MOVT | RD4(dst)
+ | COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));
+}
+
+/* Dst must be in bits[11-8] */
+static void set_imm32_const(sljit_u16 *inst, sljit_ins dst, sljit_uw new_imm)
+{
+ inst[0] = (sljit_u16)((MOVW >> 16) | COPY_BITS(new_imm, 12, 0, 4) | COPY_BITS(new_imm, 11, 10, 1));
+ inst[1] = (sljit_u16)(dst | COPY_BITS(new_imm, 8, 12, 3) | (new_imm & 0xff));
+ inst[2] = (sljit_u16)((MOVT >> 16) | COPY_BITS(new_imm, 12 + 16, 0, 4) | COPY_BITS(new_imm, 11 + 16, 10, 1));
+ inst[3] = (sljit_u16)(dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16));
+}
+
+static SLJIT_INLINE void modify_imm32_const(sljit_u16 *inst, sljit_uw new_imm)
+{
+ sljit_ins dst = inst[1] & 0x0f00;
+ SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00));
+ set_imm32_const(inst, dst, new_imm);
+}
+
+static SLJIT_INLINE sljit_u16* detect_jump_type(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset)
+{
+ sljit_sw diff;
+ sljit_uw target_addr;
+ sljit_uw jump_addr = (sljit_uw)code_ptr;
+ sljit_uw orig_addr = jump->addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ jump->addr = jump_addr;
+ if (jump->flags & SLJIT_REWRITABLE_JUMP)
+ goto exit;
+
+ if (jump->flags & JUMP_ADDR) {
+ /* Branch to ARM code is not optimized yet. */
+ if (!(jump->u.target & 0x1))
+ goto exit;
+ target_addr = jump->u.target;
+ } else {
+ SLJIT_ASSERT(jump->u.label != NULL);
+ target_addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
+
+ if (jump->u.label->size > orig_addr)
+ jump_addr = (sljit_uw)(code + orig_addr);
+ }
+
+ diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr + 4, executable_offset);
+
+ if (jump->flags & IS_COND) {
+ SLJIT_ASSERT(!(jump->flags & IS_BL));
+ /* Size of the prefix IT instruction. */
+ diff += SSIZE_OF(u16);
+ if (diff <= 0xff && diff >= -0x100) {
+ jump->flags |= PATCH_TYPE1;
+ jump->addr = (sljit_uw)(code_ptr - 1);
+ return code_ptr - 1;
+ }
+ if (diff <= 0xfffff && diff >= -0x100000) {
+ jump->flags |= PATCH_TYPE2;
+ jump->addr = (sljit_uw)(code_ptr - 1);
+ return code_ptr;
+ }
+ diff -= SSIZE_OF(u16);
+ } else if (jump->flags & IS_BL) {
+ /* Branch and link. */
+ if (diff <= 0xffffff && diff >= -0x1000000) {
+ jump->flags |= PATCH_TYPE5;
+ return code_ptr + 1;
+ }
+ goto exit;
+ } else if (diff <= 0x7ff && diff >= -0x800) {
+ jump->flags |= PATCH_TYPE3;
+ return code_ptr;
+ }
+
+ if (diff <= 0xffffff && diff >= -0x1000000) {
+ jump->flags |= PATCH_TYPE4;
+ return code_ptr + 1;
+ }
+
+exit:
+ code_ptr[4] = code_ptr[0];
+
+ if (jump->flags & IS_COND) {
+ code_ptr[3] = code_ptr[-1];
+ jump->addr = (sljit_uw)(code_ptr - 1);
+ }
+
+ return code_ptr + 4;
+}
+
+static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset)
+{
+ sljit_uw addr;
+ sljit_uw jump_addr = (sljit_uw)code_ptr;
+ sljit_sw diff;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ if (jump->flags & JUMP_ADDR)
+ addr = jump->u.target;
+ else {
+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
+
+ if (jump->u.label->size > jump->addr)
+ jump_addr = (sljit_uw)(code + jump->addr);
+ }
+
+ /* The pc+4 offset is represented by the 2 * SSIZE_OF(sljit_u16) below. */
+ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);
+
+ /* Note: ADR with imm8 does not set the last bit (Thumb2 flag). */
+
+ if (diff <= 0xffd + 2 * SSIZE_OF(u16) && diff >= -0xfff + 2 * SSIZE_OF(u16)) {
+ jump->flags |= PATCH_TYPE6;
+ return 1;
+ }
+
+ return 3;
+}
+
+static SLJIT_INLINE void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset)
+{
+ sljit_s32 type = (jump->flags >> 4) & 0xf;
+ sljit_u16 *jump_inst = (sljit_u16*)jump->addr;
+ sljit_sw diff;
+ sljit_ins ins;
+
+ diff = (sljit_sw)((jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr);
+
+ if ((jump->flags & (JUMP_MOV_ADDR | IS_ABS)) == (JUMP_MOV_ADDR | IS_ABS))
+ diff &= ~(sljit_sw)1;
+
+ if (SLJIT_UNLIKELY(type == 0)) {
+ ins = (jump->flags & JUMP_MOV_ADDR) ? *jump_inst : RDN3(TMP_REG1);
+ set_imm32_const((sljit_u16*)jump->addr, ins, (sljit_uw)diff);
+ return;
+ }
+
+ if (SLJIT_UNLIKELY(type == 6)) {
+ SLJIT_ASSERT(jump->flags & JUMP_MOV_ADDR);
+ diff -= (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_inst + 2, executable_offset) & ~(sljit_sw)0x3;
+
+ SLJIT_ASSERT(diff <= 0xfff && diff >= -0xfff);
+
+ ins = ADDWI >> 16;
+ if (diff <= 0) {
+ diff = -diff;
+ ins = SUBWI >> 16;
+ }
+
+ jump_inst[1] = (sljit_u16)(jump_inst[0] | COPY_BITS(diff, 8, 12, 3) | (diff & 0xff));
+ jump_inst[0] = (sljit_u16)(ins | 0xf | COPY_BITS(diff, 11, 10, 1));
+ return;
+ }
+
+ SLJIT_ASSERT((diff & 0x1) != 0 && !(jump->flags & JUMP_MOV_ADDR));
+ diff = (diff - (sljit_sw)(jump->addr + sizeof(sljit_u32)) - executable_offset) >> 1;
+
+ switch (type) {
+ case 1:
+ /* Encoding T1 of 'B' instruction */
+ SLJIT_ASSERT(diff <= 0x7f && diff >= -0x80 && (jump->flags & IS_COND));
+ jump_inst[0] = (sljit_u16)(0xd000 | (jump->flags & 0xf00) | ((sljit_ins)diff & 0xff));
+ return;
+ case 2:
+ /* Encoding T3 of 'B' instruction */
+ SLJIT_ASSERT(diff <= 0x7ffff && diff >= -0x80000 && (jump->flags & IS_COND));
+ jump_inst[0] = (sljit_u16)(0xf000 | COPY_BITS(jump->flags, 8, 6, 4) | COPY_BITS(diff, 11, 0, 6) | COPY_BITS(diff, 19, 10, 1));
+ jump_inst[1] = (sljit_u16)(0x8000 | COPY_BITS(diff, 17, 13, 1) | COPY_BITS(diff, 18, 11, 1) | ((sljit_ins)diff & 0x7ff));
+ return;
+ case 3:
+ /* Encoding T2 of 'B' instruction */
+ SLJIT_ASSERT(diff <= 0x3ff && diff >= -0x400 && !(jump->flags & IS_COND));
+ jump_inst[0] = (sljit_u16)(0xe000 | (diff & 0x7ff));
+ return;
+ }
+
+ SLJIT_ASSERT(diff <= 0x7fffff && diff >= -0x800000);
+
+ /* Really complex instruction form for branches. Negate with sign bit. */
+ diff ^= ((diff >> 2) & 0x600000) ^ 0x600000;
+
+ jump_inst[0] = (sljit_u16)(0xf000 | COPY_BITS(diff, 11, 0, 10) | COPY_BITS(diff, 23, 10, 1));
+ jump_inst[1] = (sljit_u16)((diff & 0x7ff) | COPY_BITS(diff, 22, 13, 1) | COPY_BITS(diff, 21, 11, 1));
+
+ SLJIT_ASSERT(type == 4 || type == 5);
+
+ /* The others have a common form. */
+ if (type == 4) /* Encoding T4 of 'B' instruction */
+ jump_inst[1] |= 0x9000;
+ else /* Encoding T1 of 'BL' instruction */
+ jump_inst[1] |= 0xd000;
+}
+
+static SLJIT_INLINE sljit_u16 *process_extended_label(sljit_u16 *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_u16*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
+static void reduce_code_size(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+ SLJIT_NEXT_DEFINE_TYPES;
+ sljit_uw total_size;
+ sljit_uw size_reduce = 0;
+ sljit_sw diff;
+
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ SLJIT_NEXT_INIT_TYPES();
+
+ while (1) {
+ SLJIT_GET_NEXT_MIN();
+
+ if (next_min_addr == SLJIT_MAX_ADDRESS)
+ break;
+
+ if (next_min_addr == next_label_size) {
+ label->size -= size_reduce;
+
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ if (next_min_addr == next_const_addr) {
+ const_->addr -= size_reduce;
+ const_ = const_->next;
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+ continue;
+ }
+
+ if (next_min_addr != next_jump_addr)
+ continue;
+
+ jump->addr -= size_reduce;
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+ total_size = JUMP_MAX_SIZE;
+
+ if (!(jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR))) {
+ /* Unit size: instruction. */
+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr - 2;
+ if (jump->u.label->size > jump->addr) {
+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);
+ diff -= (sljit_sw)size_reduce;
+ }
+
+ if (jump->flags & IS_COND) {
+ diff++;
+
+ if (diff <= (0xff / SSIZE_OF(u16)) && diff >= (-0x100 / SSIZE_OF(u16)))
+ total_size = 0;
+ else if (diff <= (0xfffff / SSIZE_OF(u16)) && diff >= (-0x100000 / SSIZE_OF(u16)))
+ total_size = 1;
+ diff--;
+ } else if (!(jump->flags & IS_BL) && diff <= (0x7ff / SSIZE_OF(u16)) && diff >= (-0x800 / SSIZE_OF(u16)))
+ total_size = 1;
+
+ if (total_size == JUMP_MAX_SIZE && diff <= (0xffffff / SSIZE_OF(u16)) && diff >= (-0x1000000 / SSIZE_OF(u16)))
+ total_size = 2;
+ }
+
+ size_reduce += JUMP_MAX_SIZE - total_size;
+ } else {
+ /* Real size minus 1. Unit size: instruction. */
+ total_size = 3;
+
+ if (!(jump->flags & JUMP_ADDR)) {
+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
+ if (jump->u.label->size > jump->addr) {
+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);
+ diff -= (sljit_sw)size_reduce;
+ }
+
+ if (diff <= (0xffd / SSIZE_OF(u16)) && diff >= (-0xfff / SSIZE_OF(u16)))
+ total_size = 1;
+ }
+
+ size_reduce += 3 - total_size;
+ }
+
+ jump->flags |= total_size << JUMP_SIZE_SHIFT;
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ }
+
+ compiler->size -= size_reduce;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
+{
+ struct sljit_memory_fragment *buf;
+ sljit_u16 *code;
+ sljit_u16 *code_ptr;
+ sljit_u16 *buf_ptr;
+ sljit_u16 *buf_end;
+ sljit_uw half_count;
+ SLJIT_NEXT_DEFINE_TYPES;
+ sljit_sw addr;
+ sljit_sw executable_offset;
+
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
+
+ reduce_code_size(compiler);
+
+ code = (sljit_u16*)allocate_executable_memory(compiler->size * sizeof(sljit_u16), options, exec_allocator_data, &executable_offset);
+ PTR_FAIL_WITH_EXEC_IF(code);
+
+ reverse_buf(compiler);
+ buf = compiler->buf;
+
+ code_ptr = code;
+ half_count = 0;
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ SLJIT_NEXT_INIT_TYPES();
+ SLJIT_GET_NEXT_MIN();
+
+ do {
+ buf_ptr = (sljit_u16*)buf->memory;
+ buf_end = buf_ptr + (buf->used_size >> 1);
+ do {
+ *code_ptr = *buf_ptr++;
+ if (next_min_addr == half_count) {
+ SLJIT_ASSERT(!label || label->size >= half_count);
+ SLJIT_ASSERT(!jump || jump->addr >= half_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= half_count);
+
+ /* These structures are ordered by their address. */
+ if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+ *code_ptr = buf_ptr[-1];
+ }
+
+ label->u.addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ if (next_min_addr == next_jump_addr) {
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+ half_count = half_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT);
+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
+ SLJIT_ASSERT((sljit_uw)code_ptr - jump->addr <
+ ((jump->flags >> JUMP_SIZE_SHIFT) + ((jump->flags & 0xf0) <= PATCH_TYPE2)) * sizeof(sljit_u16));
+ } else {
+ half_count += jump->flags >> JUMP_SIZE_SHIFT;
+ addr = (sljit_sw)code_ptr;
+ code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);
+ jump->addr = (sljit_uw)addr;
+ }
+
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ } else if (next_min_addr == next_const_addr) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+ }
+
+ SLJIT_GET_NEXT_MIN();
+ }
+ code_ptr++;
+ half_count++;
+ } while (buf_ptr < buf_end);
+
+ buf = buf->next;
+ } while (buf);
+
+ if (label && label->size == half_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
+ label->u.addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ }
+
+ SLJIT_ASSERT(!label);
+ SLJIT_ASSERT(!jump);
+ SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
+
+ jump = compiler->jumps;
+ while (jump) {
+ generate_jump_or_mov_addr(jump, executable_offset);
+ jump = jump->next;
+ }
+
+ compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_u16);
+
+ code = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+ code_ptr = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
+ SLJIT_CACHE_FLUSH(code, code_ptr);
+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
+
+ /* Set thumb mode flag. */
+ return (void*)((sljit_uw)code | 0x1);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type) {
+ case SLJIT_HAS_FPU:
+ case SLJIT_HAS_F64_AS_F32_PAIR:
+ case SLJIT_HAS_SIMD:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return (SLJIT_IS_FPU_AVAILABLE) != 0;
+#else
+ /* Available by default. */
+ return 1;
+#endif
+
+ case SLJIT_SIMD_REGS_ARE_PAIRS:
+ case SLJIT_HAS_CLZ:
+ case SLJIT_HAS_CTZ:
+ case SLJIT_HAS_REV:
+ case SLJIT_HAS_ROT:
+ case SLJIT_HAS_CMOV:
+ case SLJIT_HAS_PREFETCH:
+ case SLJIT_HAS_COPY_F32:
+ case SLJIT_HAS_COPY_F64:
+ case SLJIT_HAS_ATOMIC:
+ case SLJIT_HAS_MEMORY_BARRIER:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/* --------------------------------------------------------------------- */
+/* Core code generator functions. */
+/* --------------------------------------------------------------------- */
+
+#define INVALID_IMM 0x80000000
+static sljit_uw get_imm(sljit_uw imm)
+{
+ /* Thumb immediate form. */
+ sljit_s32 counter;
+
+ if (imm <= 0xff)
+ return imm;
+
+ if ((imm & 0xffff) == (imm >> 16)) {
+ /* Some special cases. */
+ if (!(imm & 0xff00))
+ return (1 << 12) | (imm & 0xff);
+ if (!(imm & 0xff))
+ return (2 << 12) | ((imm >> 8) & 0xff);
+ if ((imm & 0xff00) == ((imm & 0xff) << 8))
+ return (3 << 12) | (imm & 0xff);
+ }
+
+ /* Assembly optimization: count leading zeroes? */
+ counter = 8;
+ if (!(imm & 0xffff0000)) {
+ counter += 16;
+ imm <<= 16;
+ }
+ if (!(imm & 0xff000000)) {
+ counter += 8;
+ imm <<= 8;
+ }
+ if (!(imm & 0xf0000000)) {
+ counter += 4;
+ imm <<= 4;
+ }
+ if (!(imm & 0xc0000000)) {
+ counter += 2;
+ imm <<= 2;
+ }
+ if (!(imm & 0x80000000)) {
+ counter += 1;
+ imm <<= 1;
+ }
+ /* Since imm >= 128, this must be true. */
+ SLJIT_ASSERT(counter <= 31);
+
+ if (imm & 0x00ffffff)
+ return INVALID_IMM; /* Cannot be encoded. */
+
+ return ((imm >> 24) & 0x7f) | COPY_BITS(counter, 4, 26, 1) | COPY_BITS(counter, 1, 12, 3) | COPY_BITS(counter, 0, 7, 1);
+}
+
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm)
+{
+ sljit_uw tmp;
+
+ /* MOVS cannot be used since it destroy flags. */
+
+ if (imm >= 0x10000) {
+ tmp = get_imm(imm);
+ if (tmp != INVALID_IMM)
+ return push_inst32(compiler, MOV_WI | RD4(dst) | tmp);
+ tmp = get_imm(~imm);
+ if (tmp != INVALID_IMM)
+ return push_inst32(compiler, MVN_WI | RD4(dst) | tmp);
+ }
+
+ /* set low 16 bits, set hi 16 bits to 0. */
+ FAIL_IF(push_inst32(compiler, MOVW | RD4(dst)
+ | COPY_BITS(imm, 12, 16, 4) | COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff)));
+
+ /* set hi 16 bit if needed. */
+ if (imm >= 0x10000)
+ return push_inst32(compiler, MOVT | RD4(dst)
+ | COPY_BITS(imm, 12 + 16, 16, 4) | COPY_BITS(imm, 11 + 16, 26, 1) | COPY_BITS(imm, 8 + 16, 12, 3) | ((imm & 0xff0000) >> 16));
+ return SLJIT_SUCCESS;
+}
+
+#define ARG1_IMM 0x0010000
+#define ARG2_IMM 0x0020000
+/* SET_FLAGS must be 0x100000 as it is also the value of S bit (can be used for optimization). */
+#define SET_FLAGS 0x0100000
+#define UNUSED_RETURN 0x0200000
+#define REGISTER_OP 0x0400000
+
+static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 dst, sljit_uw arg1, sljit_uw arg2)
+{
+ /* dst must be register
+ arg1 must be register, imm
+ arg2 must be register, imm */
+ sljit_s32 reg;
+ sljit_uw imm, imm2;
+
+ if (SLJIT_UNLIKELY((flags & (ARG1_IMM | ARG2_IMM)) == (ARG1_IMM | ARG2_IMM))) {
+ /* Both are immediates, no temporaries are used. */
+ flags &= ~ARG1_IMM;
+ FAIL_IF(load_immediate(compiler, TMP_REG1, arg1));
+ arg1 = TMP_REG1;
+ }
+
+ if (flags & (ARG1_IMM | ARG2_IMM)) {
+ reg = (sljit_s32)((flags & ARG2_IMM) ? arg1 : arg2);
+ imm = (flags & ARG2_IMM) ? arg2 : arg1;
+
+ switch (flags & 0xffff) {
+ case SLJIT_CLZ:
+ case SLJIT_CTZ:
+ case SLJIT_REV:
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+ case SLJIT_MUL:
+ case SLJIT_MULADD:
+ /* No form with immediate operand. */
+ break;
+ case SLJIT_MOV:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && (flags & ARG2_IMM) && arg1 == TMP_REG2);
+ return load_immediate(compiler, dst, imm);
+ case SLJIT_ADD:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ imm2 = NEGATE(imm);
+ if (IS_2_LO_REGS(reg, dst)) {
+ if (imm <= 0x7)
+ return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
+ if (imm2 <= 0x7)
+ return push_inst16(compiler, SUBSI3 | IMM3(imm2) | RD3(dst) | RN3(reg));
+ if (reg == dst) {
+ if (imm <= 0xff)
+ return push_inst16(compiler, ADDSI8 | IMM8(imm) | RDN3(dst));
+ if (imm2 <= 0xff)
+ return push_inst16(compiler, SUBSI8 | IMM8(imm2) | RDN3(dst));
+ }
+ }
+ if (!(flags & SET_FLAGS)) {
+ if (imm <= 0xfff)
+ return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm));
+ if (imm2 <= 0xfff)
+ return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm2));
+ }
+ imm2 = get_imm(imm);
+ if (imm2 != INVALID_IMM)
+ return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2);
+ imm = get_imm(NEGATE(imm));
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+ break;
+ case SLJIT_ADDC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ imm2 = get_imm(imm);
+ if (imm2 != INVALID_IMM)
+ return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2);
+ if (flags & ARG2_IMM) {
+ imm = get_imm(~imm);
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+ }
+ break;
+ case SLJIT_SUB:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ if (flags & ARG1_IMM) {
+ if (imm == 0 && IS_2_LO_REGS(reg, dst))
+ return push_inst16(compiler, RSBSI | RD3(dst) | RN3(reg));
+ imm = get_imm(imm);
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, RSB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+ break;
+ }
+ if (flags & UNUSED_RETURN) {
+ if (imm <= 0xff && reg_map[reg] <= 7)
+ return push_inst16(compiler, CMPI | IMM8(imm) | RDN3(reg));
+ imm2 = get_imm(imm);
+ if (imm2 != INVALID_IMM)
+ return push_inst32(compiler, CMPI_W | RN4(reg) | imm2);
+ imm = get_imm(NEGATE(imm));
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, CMNI_W | RN4(reg) | imm);
+ break;
+ }
+ imm2 = NEGATE(imm);
+ if (IS_2_LO_REGS(reg, dst)) {
+ if (imm <= 0x7)
+ return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
+ if (imm2 <= 0x7)
+ return push_inst16(compiler, ADDSI3 | IMM3(imm2) | RD3(dst) | RN3(reg));
+ if (reg == dst) {
+ if (imm <= 0xff)
+ return push_inst16(compiler, SUBSI8 | IMM8(imm) | RDN3(dst));
+ if (imm2 <= 0xff)
+ return push_inst16(compiler, ADDSI8 | IMM8(imm2) | RDN3(dst));
+ }
+ }
+ if (!(flags & SET_FLAGS)) {
+ if (imm <= 0xfff)
+ return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(imm));
+ if (imm2 <= 0xfff)
+ return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(imm2));
+ }
+ imm2 = get_imm(imm);
+ if (imm2 != INVALID_IMM)
+ return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2);
+ imm = get_imm(NEGATE(imm));
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+ break;
+ case SLJIT_SUBC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ if (flags & ARG1_IMM)
+ break;
+ imm2 = get_imm(imm);
+ if (imm2 != INVALID_IMM)
+ return push_inst32(compiler, SBCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2);
+ imm = get_imm(~imm);
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+ break;
+ case SLJIT_AND:
+ imm2 = get_imm(imm);
+ if (imm2 != INVALID_IMM)
+ return push_inst32(compiler, ((flags & UNUSED_RETURN) ? TSTI : ANDI) | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2);
+ imm = get_imm(~imm);
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, BICI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+ break;
+ case SLJIT_OR:
+ imm2 = get_imm(imm);
+ if (imm2 != INVALID_IMM)
+ return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm2);
+ imm = get_imm(~imm);
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, ORNI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+ break;
+ case SLJIT_XOR:
+ if (imm == (sljit_uw)-1) {
+ if (IS_2_LO_REGS(dst, reg))
+ return push_inst16(compiler, MVNS | RD3(dst) | RN3(reg));
+ return push_inst32(compiler, MVN_W | (flags & SET_FLAGS) | RD4(dst) | RM4(reg));
+ }
+ imm = get_imm(imm);
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, EORI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
+ break;
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ case SLJIT_ROTL:
+ case SLJIT_ROTR:
+ if (flags & ARG1_IMM)
+ break;
+ imm &= 0x1f;
+
+ if (imm == 0) {
+ if (!(flags & SET_FLAGS))
+ return push_inst16(compiler, MOV | SET_REGS44(dst, reg));
+ if (IS_2_LO_REGS(dst, reg))
+ return push_inst16(compiler, MOVS | RD3(dst) | RN3(reg));
+ return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(dst) | RM4(reg));
+ }
+
+ switch (flags & 0xffff) {
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ if (IS_2_LO_REGS(dst, reg))
+ return push_inst16(compiler, LSLSI | RD3(dst) | RN3(reg) | (imm << 6));
+ return push_inst32(compiler, LSL_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ if (IS_2_LO_REGS(dst, reg))
+ return push_inst16(compiler, LSRSI | RD3(dst) | RN3(reg) | (imm << 6));
+ return push_inst32(compiler, LSR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ if (IS_2_LO_REGS(dst, reg))
+ return push_inst16(compiler, ASRSI | RD3(dst) | RN3(reg) | (imm << 6));
+ return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
+ case SLJIT_ROTL:
+ imm = (imm ^ 0x1f) + 1;
+ SLJIT_FALLTHROUGH
+ default: /* SLJIT_ROTR */
+ return push_inst32(compiler, ROR_WI | RD4(dst) | RM4(reg) | IMM5(imm));
+ }
+ default:
+ SLJIT_UNREACHABLE();
+ break;
+ }
+
+ if (flags & ARG2_IMM) {
+ imm = arg2;
+ arg2 = (arg1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(load_immediate(compiler, (sljit_s32)arg2, imm));
+ } else {
+ imm = arg1;
+ arg1 = (arg2 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(load_immediate(compiler, (sljit_s32)arg1, imm));
+ }
+
+ SLJIT_ASSERT(arg1 != arg2);
+ }
+
+ /* Both arguments are registers. */
+ switch (flags & 0xffff) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ case SLJIT_MOV_P:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
+ if (dst == (sljit_s32)arg2)
+ return SLJIT_SUCCESS;
+ return push_inst16(compiler, MOV | SET_REGS44(dst, arg2));
+ case SLJIT_MOV_U8:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
+ if (IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, UXTB | RD3(dst) | RN3(arg2));
+ return push_inst32(compiler, UXTB_W | RD4(dst) | RM4(arg2));
+ case SLJIT_MOV_S8:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
+ if (IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, SXTB | RD3(dst) | RN3(arg2));
+ return push_inst32(compiler, SXTB_W | RD4(dst) | RM4(arg2));
+ case SLJIT_MOV_U16:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
+ if (IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, UXTH | RD3(dst) | RN3(arg2));
+ return push_inst32(compiler, UXTH_W | RD4(dst) | RM4(arg2));
+ case SLJIT_MOV_S16:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
+ if (IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, SXTH | RD3(dst) | RN3(arg2));
+ return push_inst32(compiler, SXTH_W | RD4(dst) | RM4(arg2));
+ case SLJIT_CLZ:
+ SLJIT_ASSERT(arg1 == TMP_REG2);
+ return push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2));
+ case SLJIT_CTZ:
+ SLJIT_ASSERT(arg1 == TMP_REG2);
+ FAIL_IF(push_inst32(compiler, RBIT | RN4(arg2) | RD4(dst) | RM4(arg2)));
+ return push_inst32(compiler, CLZ | RN4(dst) | RD4(dst) | RM4(dst));
+ case SLJIT_REV:
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+ SLJIT_ASSERT(arg1 == TMP_REG2);
+ if (IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, REV | RD3(dst) | RN3(arg2));
+ return push_inst32(compiler, REV_W | RN4(arg2) | RD4(dst) | RM4(arg2));
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+ SLJIT_ASSERT(arg1 == TMP_REG2);
+
+ if (IS_2_LO_REGS(dst, arg2))
+ FAIL_IF(push_inst16(compiler, REV16 | RD3(dst) | RN3(arg2)));
+ else
+ FAIL_IF(push_inst32(compiler, REV16_W | RN4(arg2) | RD4(dst) | RM4(arg2)));
+
+ if (!(flags & REGISTER_OP))
+ return SLJIT_SUCCESS;
+
+ flags &= 0xffff;
+ if (reg_map[dst] <= 7)
+ return push_inst16(compiler, (flags == SLJIT_REV_U16 ? UXTH : SXTH) | RD3(dst) | RN3(dst));
+ return push_inst32(compiler, (flags == SLJIT_REV_U16 ? UXTH_W : SXTH_W) | RD4(dst) | RM4(dst));
+ case SLJIT_ADD:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ if (IS_3_LO_REGS(dst, arg1, arg2))
+ return push_inst16(compiler, ADDS | RD3(dst) | RN3(arg1) | RM3(arg2));
+ if (dst == (sljit_s32)arg1 && !(flags & SET_FLAGS))
+ return push_inst16(compiler, ADD | SET_REGS44(dst, arg2));
+ return push_inst32(compiler, ADD_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+ case SLJIT_ADDC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, ADCS | RD3(dst) | RN3(arg2));
+ return push_inst32(compiler, ADC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+ case SLJIT_SUB:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ if (flags & UNUSED_RETURN) {
+ if (IS_2_LO_REGS(arg1, arg2))
+ return push_inst16(compiler, CMP | RD3(arg1) | RN3(arg2));
+ return push_inst16(compiler, CMP_X | SET_REGS44(arg1, arg2));
+ }
+ if (IS_3_LO_REGS(dst, arg1, arg2))
+ return push_inst16(compiler, SUBS | RD3(dst) | RN3(arg1) | RM3(arg2));
+ return push_inst32(compiler, SUB_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+ case SLJIT_SUBC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, SBCS | RD3(dst) | RN3(arg2));
+ return push_inst32(compiler, SBC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+ case SLJIT_MUL:
+ compiler->status_flags_state = 0;
+ if (!(flags & SET_FLAGS))
+ return push_inst32(compiler, MUL | RD4(dst) | RN4(arg1) | RM4(arg2));
+ reg = (dst == TMP_REG2) ? TMP_REG1 : TMP_REG2;
+ FAIL_IF(push_inst32(compiler, SMULL | RT4(dst) | RD4(reg) | RN4(arg1) | RM4(arg2)));
+ /* cmp TMP_REG2, dst asr #31. */
+ return push_inst32(compiler, CMP_W | RN4(reg) | 0x70e0 | RM4(dst));
+ case SLJIT_AND:
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, ANDS | RD3(dst) | RN3(arg2));
+ if ((flags & UNUSED_RETURN) && IS_2_LO_REGS(arg1, arg2))
+ return push_inst16(compiler, TST | RD3(arg1) | RN3(arg2));
+ return push_inst32(compiler, ((flags & UNUSED_RETURN) ? TST_W : AND_W) | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+ case SLJIT_OR:
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, ORRS | RD3(dst) | RN3(arg2));
+ return push_inst32(compiler, ORR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+ case SLJIT_XOR:
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, EORS | RD3(dst) | RN3(arg2));
+ return push_inst32(compiler, EOR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+ case SLJIT_MSHL:
+ reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2;
+ FAIL_IF(push_inst32(compiler, ANDI | RD4(reg) | RN4(arg2) | 0x1f));
+ arg2 = (sljit_uw)reg;
+ SLJIT_FALLTHROUGH
+ case SLJIT_SHL:
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, LSLS | RD3(dst) | RN3(arg2));
+ return push_inst32(compiler, LSL_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+ case SLJIT_MLSHR:
+ reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2;
+ FAIL_IF(push_inst32(compiler, ANDI | RD4(reg) | RN4(arg2) | 0x1f));
+ arg2 = (sljit_uw)reg;
+ SLJIT_FALLTHROUGH
+ case SLJIT_LSHR:
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, LSRS | RD3(dst) | RN3(arg2));
+ return push_inst32(compiler, LSR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+ case SLJIT_MASHR:
+ reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2;
+ FAIL_IF(push_inst32(compiler, ANDI | RD4(reg) | RN4(arg2) | 0x1f));
+ arg2 = (sljit_uw)reg;
+ SLJIT_FALLTHROUGH
+ case SLJIT_ASHR:
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, ASRS | RD3(dst) | RN3(arg2));
+ return push_inst32(compiler, ASR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+ case SLJIT_ROTL:
+ reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2;
+ FAIL_IF(push_inst32(compiler, RSB_WI | RD4(reg) | RN4(arg2) | 0));
+ arg2 = (sljit_uw)reg;
+ SLJIT_FALLTHROUGH
+ case SLJIT_ROTR:
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
+ return push_inst16(compiler, RORS | RD3(dst) | RN3(arg2));
+ return push_inst32(compiler, ROR_W | RD4(dst) | RN4(arg1) | RM4(arg2));
+ case SLJIT_MULADD:
+ compiler->status_flags_state = 0;
+ return push_inst32(compiler, MLA | RD4(dst) | RN4(arg1) | RM4(arg2) | RT4(dst));
+ }
+
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
+}
+
+#define STORE 0x01
+#define SIGNED 0x02
+
+#define WORD_SIZE 0x00
+#define BYTE_SIZE 0x04
+#define HALF_SIZE 0x08
+#define PRELOAD 0x0c
+
+#define IS_WORD_SIZE(flags) (!((flags) & (BYTE_SIZE | HALF_SIZE)))
+#define ALIGN_CHECK(argw, imm, shift) (!((argw) & ~((imm) << (shift))))
+
+/*
+ 1st letter:
+ w = word
+ b = byte
+ h = half
+
+ 2nd letter:
+ s = signed
+ u = unsigned
+
+ 3rd letter:
+ l = load
+ s = store
+*/
+
+static const sljit_ins sljit_mem16[12] = {
+/* w u l */ 0x5800 /* ldr */,
+/* w u s */ 0x5000 /* str */,
+/* w s l */ 0x5800 /* ldr */,
+/* w s s */ 0x5000 /* str */,
+
+/* b u l */ 0x5c00 /* ldrb */,
+/* b u s */ 0x5400 /* strb */,
+/* b s l */ 0x5600 /* ldrsb */,
+/* b s s */ 0x5400 /* strb */,
+
+/* h u l */ 0x5a00 /* ldrh */,
+/* h u s */ 0x5200 /* strh */,
+/* h s l */ 0x5e00 /* ldrsh */,
+/* h s s */ 0x5200 /* strh */,
+};
+
+static const sljit_ins sljit_mem16_imm5[12] = {
+/* w u l */ 0x6800 /* ldr imm5 */,
+/* w u s */ 0x6000 /* str imm5 */,
+/* w s l */ 0x6800 /* ldr imm5 */,
+/* w s s */ 0x6000 /* str imm5 */,
+
+/* b u l */ 0x7800 /* ldrb imm5 */,
+/* b u s */ 0x7000 /* strb imm5 */,
+/* b s l */ 0x0000 /* not allowed */,
+/* b s s */ 0x7000 /* strb imm5 */,
+
+/* h u l */ 0x8800 /* ldrh imm5 */,
+/* h u s */ 0x8000 /* strh imm5 */,
+/* h s l */ 0x0000 /* not allowed */,
+/* h s s */ 0x8000 /* strh imm5 */,
+};
+
+#define MEM_IMM8 0xc00
+#define MEM_IMM12 0x800000
+static const sljit_ins sljit_mem32[13] = {
+/* w u l */ 0xf8500000 /* ldr.w */,
+/* w u s */ 0xf8400000 /* str.w */,
+/* w s l */ 0xf8500000 /* ldr.w */,
+/* w s s */ 0xf8400000 /* str.w */,
+
+/* b u l */ 0xf8100000 /* ldrb.w */,
+/* b u s */ 0xf8000000 /* strb.w */,
+/* b s l */ 0xf9100000 /* ldrsb.w */,
+/* b s s */ 0xf8000000 /* strb.w */,
+
+/* h u l */ 0xf8300000 /* ldrh.w */,
+/* h u s */ 0xf8200000 /* strsh.w */,
+/* h s l */ 0xf9300000 /* ldrsh.w */,
+/* h s s */ 0xf8200000 /* strsh.w */,
+
+/* p u l */ 0xf8100000 /* pld */,
+};
+
+/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */
+static sljit_s32 emit_set_delta(struct sljit_compiler *compiler, sljit_s32 dst, sljit_s32 reg, sljit_sw value)
+{
+ sljit_uw imm;
+
+ if (value >= 0) {
+ if (value <= 0xfff)
+ return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(value));
+ imm = get_imm((sljit_uw)value);
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, ADD_WI | RD4(dst) | RN4(reg) | imm);
+ }
+ else {
+ value = -value;
+ if (value <= 0xfff)
+ return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(value));
+ imm = get_imm((sljit_uw)value);
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, SUB_WI | RD4(dst) | RN4(reg) | imm);
+ }
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,
+ sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
+{
+ sljit_s32 other_r;
+ sljit_uw imm, tmp;
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+ SLJIT_ASSERT((arg & REG_MASK) != tmp_reg || (arg == SLJIT_MEM1(tmp_reg) && argw >= -0xff && argw <= 0xfff));
+
+ if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
+ imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);
+ if (imm != INVALID_IMM) {
+ FAIL_IF(push_inst32(compiler, MOV_WI | RD4(tmp_reg) | imm));
+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg) | (argw & 0xfff));
+ }
+
+ FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw));
+ if (IS_2_LO_REGS(reg, tmp_reg) && sljit_mem16_imm5[flags])
+ return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(tmp_reg));
+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg));
+ }
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ argw &= 0x3;
+ other_r = OFFS_REG(arg);
+ arg &= REG_MASK;
+
+ if (!argw && IS_3_LO_REGS(reg, arg, other_r))
+ return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r));
+ return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | ((sljit_ins)argw << 4));
+ }
+
+ arg &= REG_MASK;
+
+ if (argw > 0xfff) {
+ imm = get_imm((sljit_uw)(argw & ~0xfff));
+ if (imm != INVALID_IMM) {
+ push_inst32(compiler, ADD_WI | RD4(tmp_reg) | RN4(arg) | imm);
+ arg = tmp_reg;
+ argw = argw & 0xfff;
+ }
+ }
+ else if (argw < -0xff) {
+ tmp = (sljit_uw)((-argw + 0xfff) & ~0xfff);
+ SLJIT_ASSERT(tmp >= (sljit_uw)-argw);
+ imm = get_imm(tmp);
+
+ if (imm != INVALID_IMM) {
+ push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | imm);
+ arg = tmp_reg;
+ argw += (sljit_sw)tmp;
+
+ SLJIT_ASSERT(argw >= 0 && argw <= 0xfff);
+ }
+ }
+
+ /* 16 bit instruction forms. */
+ if (IS_2_LO_REGS(reg, arg) && sljit_mem16_imm5[flags]) {
+ tmp = 3;
+ if (IS_WORD_SIZE(flags)) {
+ if (ALIGN_CHECK(argw, 0x1f, 2))
+ tmp = 2;
+ }
+ else if (flags & BYTE_SIZE)
+ {
+ if (ALIGN_CHECK(argw, 0x1f, 0))
+ tmp = 0;
+ }
+ else {
+ SLJIT_ASSERT(flags & HALF_SIZE);
+ if (ALIGN_CHECK(argw, 0x1f, 1))
+ tmp = 1;
+ }
+
+ if (tmp < 3)
+ return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | ((sljit_ins)argw << (6 - tmp)));
+ }
+ else if (SLJIT_UNLIKELY(arg == SLJIT_SP) && IS_WORD_SIZE(flags) && ALIGN_CHECK(argw, 0xff, 2) && reg_map[reg] <= 7) {
+ /* SP based immediate. */
+ return push_inst16(compiler, STR_SP | (sljit_ins)((flags & STORE) ? 0 : 0x800) | RDN3(reg) | ((sljit_ins)argw >> 2));
+ }
+
+ if (argw >= 0 && argw <= 0xfff)
+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | (sljit_ins)argw);
+ else if (argw < 0 && argw >= -0xff)
+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | (sljit_ins)-argw);
+
+ SLJIT_ASSERT(arg != tmp_reg);
+
+ FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw));
+ if (IS_3_LO_REGS(reg, arg, tmp_reg))
+ return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp_reg));
+ return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg));
+}
+
+#undef ALIGN_CHECK
+#undef IS_WORD_SIZE
+
+/* --------------------------------------------------------------------- */
+/* Entry, exit */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches;
+ sljit_s32 fsaveds;
+ sljit_s32 size, i, tmp, word_arg_count;
+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
+ sljit_uw offset;
+ sljit_uw imm = 0;
+#ifdef __SOFTFP__
+ sljit_u32 float_arg_count;
+#else
+ sljit_u32 old_offset, f32_offset;
+ sljit_u32 remap[3];
+ sljit_u32 *remap_ptr = remap;
+#endif
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--)
+ imm |= (sljit_uw)1 << reg_map[i];
+
+ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
+ imm |= (sljit_uw)1 << reg_map[i];
+
+ /* At least two registers must be set for PUSH_W and one for PUSH instruction. */
+ FAIL_IF((imm & 0xff00)
+ ? push_inst32(compiler, PUSH_W | (1 << 14) | imm)
+ : push_inst16(compiler, PUSH | (1 << 8) | imm));
+
+ /* Stack must be aligned to 8 bytes: (LR, R4) */
+ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);
+
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if ((size & SSIZE_OF(sw)) != 0) {
+ FAIL_IF(push_inst16(compiler, SUB_SP_I | (sizeof(sljit_sw) >> 2)));
+ size += SSIZE_OF(sw);
+ }
+
+ if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {
+ FAIL_IF(push_inst32(compiler, VPUSH | VD4(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));
+ } else {
+ if (fsaveds > 0)
+ FAIL_IF(push_inst32(compiler, VPUSH | VD4(SLJIT_FS0) | ((sljit_uw)fsaveds << 1)));
+ if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)
+ FAIL_IF(push_inst32(compiler, VPUSH | VD4(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));
+ }
+ }
+
+ local_size = ((size + local_size + 0x7) & ~0x7) - size;
+ compiler->local_size = local_size;
+
+ if (options & SLJIT_ENTER_REG_ARG)
+ arg_types = 0;
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ word_arg_count = 0;
+ saved_arg_count = 0;
+#ifdef __SOFTFP__
+ SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
+
+ offset = 0;
+ float_arg_count = 0;
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset & 0x7)
+ offset += sizeof(sljit_sw);
+
+ if (offset < 4 * sizeof(sljit_sw))
+ FAIL_IF(push_inst32(compiler, VMOV2 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));
+ else
+ FAIL_IF(push_inst32(compiler, VLDR_F32 | 0x800100 | RN4(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));
+ float_arg_count++;
+ offset += sizeof(sljit_f64) - sizeof(sljit_sw);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (offset < 4 * sizeof(sljit_sw))
+ FAIL_IF(push_inst32(compiler, VMOV | (float_arg_count << 16) | (offset << 10)));
+ else
+ FAIL_IF(push_inst32(compiler, VLDR_F32 | 0x800000 | RN4(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));
+ float_arg_count++;
+ break;
+ default:
+ word_arg_count++;
+
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ tmp = SLJIT_S0 - saved_arg_count;
+ saved_arg_count++;
+ } else if (word_arg_count - 1 != (sljit_s32)(offset >> 2))
+ tmp = word_arg_count;
+ else
+ break;
+
+ if (offset < 4 * sizeof(sljit_sw))
+ FAIL_IF(push_inst16(compiler, MOV | ((sljit_ins)reg_map[tmp] & 0x7) | (((sljit_ins)reg_map[tmp] & 0x8) << 4) | (offset << 1)));
+ else if (reg_map[tmp] <= 7)
+ FAIL_IF(push_inst16(compiler, LDR_SP | RDN3(tmp)
+ | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));
+ else
+ FAIL_IF(push_inst32(compiler, LDR | RT4(tmp) | RN4(SLJIT_SP)
+ | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)))));
+ break;
+ }
+
+ offset += sizeof(sljit_sw);
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ compiler->args_size = offset;
+#else
+ offset = SLJIT_FR0;
+ old_offset = SLJIT_FR0;
+ f32_offset = 0;
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset != old_offset)
+ *remap_ptr++ = VMOV_F32 | SLJIT_32 | VD4(offset) | VM4(old_offset);
+ old_offset++;
+ offset++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (f32_offset != 0) {
+ *remap_ptr++ = VMOV_F32 | 0x20 | VD4(offset) | VM4(f32_offset);
+ f32_offset = 0;
+ } else {
+ if (offset != old_offset)
+ *remap_ptr++ = VMOV_F32 | VD4(offset) | VM4(old_offset);
+ f32_offset = old_offset;
+ old_offset++;
+ }
+ offset++;
+ break;
+ default:
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S0 - saved_arg_count, SLJIT_R0 + word_arg_count)));
+ saved_arg_count++;
+ }
+
+ word_arg_count++;
+ break;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ SLJIT_ASSERT((sljit_uw)(remap_ptr - remap) <= sizeof(remap));
+
+ while (remap_ptr > remap)
+ FAIL_IF(push_inst32(compiler, *(--remap_ptr)));
+#endif
+
+#ifdef _WIN32
+ if (local_size >= 4096) {
+ imm = get_imm(4096);
+ SLJIT_ASSERT(imm != INVALID_IMM);
+
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));
+
+ if (local_size < 4 * 4096) {
+ if (local_size > 2 * 4096) {
+ if (local_size > 3 * 4096) {
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));
+ }
+
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));
+ }
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, ((sljit_uw)local_size >> 12) - 1));
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));
+ FAIL_IF(push_inst32(compiler, SUB_WI | SET_FLAGS | RD4(TMP_REG2) | RN4(TMP_REG2) | 1));
+ FAIL_IF(push_inst16(compiler, BCC | (0x1 << 8) /* not-equal */ | (-8 & 0xff)));
+ }
+
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));
+ local_size &= 0xfff;
+ }
+
+ if (local_size >= 256) {
+ SLJIT_ASSERT(local_size < 4096);
+
+ if (local_size <= (127 << 2))
+ FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_uw)local_size >> 2)));
+ else
+ FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, (sljit_uw)local_size));
+
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));
+ } else if (local_size > 0)
+ FAIL_IF(push_inst32(compiler, LDRI | 0x500 | RT4(TMP_REG1) | RN4(SLJIT_SP) | (sljit_uw)local_size));
+#else /* !_WIN32 */
+ if (local_size > 0) {
+ if (local_size <= (127 << 2))
+ FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_uw)local_size >> 2)));
+ else
+ FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, (sljit_uw)local_size));
+ }
+#endif /* _WIN32 */
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches;
+ sljit_s32 fsaveds;
+ sljit_s32 size;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+ size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);
+
+ /* Doubles are saved, so alignment is unaffected. */
+ if ((size & SSIZE_OF(sw)) != 0 && (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG))
+ size += SSIZE_OF(sw);
+
+ compiler->local_size = ((size + local_size + 0x7) & ~0x7) - size;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm)
+{
+ sljit_uw imm2;
+
+ /* The TMP_REG1 register must keep its value. */
+ if (imm <= (127u << 2))
+ return push_inst16(compiler, ADD_SP_I | (imm >> 2));
+
+ if (imm <= 0xfff)
+ return push_inst32(compiler, ADDWI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | IMM12(imm));
+
+ imm2 = get_imm(imm);
+
+ if (imm2 != INVALID_IMM)
+ return push_inst32(compiler, ADD_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm2);
+
+ FAIL_IF(load_immediate(compiler, TMP_REG2, imm));
+ return push_inst16(compiler, ADD_SP | RN3(TMP_REG2));
+}
+
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size)
+{
+ sljit_s32 local_size, fscratches, fsaveds, i, tmp;
+ sljit_s32 restored_reg = 0;
+ sljit_s32 lr_dst = TMP_PC;
+ sljit_uw reg_list = 0;
+
+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14 && frame_size <= 128);
+
+ local_size = compiler->local_size;
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if (local_size > 0)
+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));
+
+ if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {
+ FAIL_IF(push_inst32(compiler, VPOP | VD4(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));
+ } else {
+ if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)
+ FAIL_IF(push_inst32(compiler, VPOP | VD4(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));
+ if (fsaveds > 0)
+ FAIL_IF(push_inst32(compiler, VPOP | VD4(SLJIT_FS0) | ((sljit_uw)fsaveds << 1)));
+ }
+
+ local_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1) & 0x7;
+ }
+
+ if (frame_size < 0) {
+ lr_dst = TMP_REG2;
+ frame_size = 0;
+ } else if (frame_size > 0) {
+ SLJIT_ASSERT(frame_size == 1 || (frame_size & 0x7) == 0);
+ lr_dst = 0;
+ frame_size &= ~0x7;
+ }
+
+ tmp = SLJIT_S0 - compiler->saveds;
+ i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options);
+ if (tmp < i) {
+ restored_reg = i;
+ do {
+ reg_list |= (sljit_uw)1 << reg_map[i];
+ } while (--i > tmp);
+ }
+
+ i = compiler->scratches;
+ if (i >= SLJIT_FIRST_SAVED_REG) {
+ restored_reg = i;
+ do {
+ reg_list |= (sljit_uw)1 << reg_map[i];
+ } while (--i >= SLJIT_FIRST_SAVED_REG);
+ }
+
+ if (lr_dst == TMP_REG2 && reg_list == 0) {
+ reg_list |= (sljit_uw)1 << reg_map[TMP_REG2];
+ restored_reg = TMP_REG2;
+ lr_dst = 0;
+ }
+
+ if (lr_dst == 0 && (reg_list & (reg_list - 1)) == 0) {
+ /* The local_size does not include the saved registers. */
+ tmp = 0;
+ if (reg_list != 0) {
+ tmp = 2;
+ if (local_size <= 0xfff) {
+ if (local_size == 0) {
+ SLJIT_ASSERT(restored_reg != TMP_REG2);
+ if (frame_size == 0)
+ return push_inst32(compiler, LDRI | RT4(restored_reg) | RN4(SLJIT_SP) | 0x308);
+ if (frame_size > 2 * SSIZE_OF(sw))
+ return push_inst32(compiler, LDRI | RT4(restored_reg) | RN4(SLJIT_SP) | 0x100 | (sljit_ins)(frame_size - (2 * SSIZE_OF(sw))));
+ }
+
+ if (reg_map[restored_reg] <= 7 && local_size <= 0x3fc)
+ FAIL_IF(push_inst16(compiler, STR_SP | 0x800 | RDN3(restored_reg) | (sljit_ins)(local_size >> 2)));
+ else
+ FAIL_IF(push_inst32(compiler, LDR | RT4(restored_reg) | RN4(SLJIT_SP) | (sljit_ins)local_size));
+ tmp = 1;
+ } else if (frame_size == 0) {
+ frame_size = (restored_reg == TMP_REG2) ? SSIZE_OF(sw) : 2 * SSIZE_OF(sw);
+ tmp = 3;
+ }
+
+ /* Place for the saved register. */
+ if (restored_reg != TMP_REG2)
+ local_size += SSIZE_OF(sw);
+ }
+
+ /* Place for the lr register. */
+ local_size += SSIZE_OF(sw);
+
+ if (frame_size > local_size)
+ FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_ins)(frame_size - local_size) >> 2)));
+ else if (frame_size < local_size)
+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size)));
+
+ if (tmp <= 1)
+ return SLJIT_SUCCESS;
+
+ if (tmp == 2) {
+ frame_size -= SSIZE_OF(sw);
+ if (restored_reg != TMP_REG2)
+ frame_size -= SSIZE_OF(sw);
+
+ if (reg_map[restored_reg] <= 7)
+ return push_inst16(compiler, STR_SP | 0x800 | RDN3(restored_reg) | (sljit_ins)(frame_size >> 2));
+
+ return push_inst32(compiler, LDR | RT4(restored_reg) | RN4(SLJIT_SP) | (sljit_ins)frame_size);
+ }
+
+ tmp = (restored_reg == TMP_REG2) ? 0x304 : 0x308;
+ return push_inst32(compiler, LDRI | RT4(restored_reg) | RN4(SLJIT_SP) | (sljit_ins)tmp);
+ }
+
+ if (local_size > 0)
+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));
+
+ if (!(reg_list & 0xff00) && lr_dst != TMP_REG2) {
+ if (lr_dst == TMP_PC)
+ reg_list |= 1u << 8;
+
+ /* At least one register must be set for POP instruction. */
+ SLJIT_ASSERT(reg_list != 0);
+
+ FAIL_IF(push_inst16(compiler, POP | reg_list));
+ } else {
+ if (lr_dst != 0)
+ reg_list |= (sljit_uw)1 << reg_map[lr_dst];
+
+ /* At least two registers must be set for POP_W instruction. */
+ SLJIT_ASSERT((reg_list & (reg_list - 1)) != 0);
+
+ FAIL_IF(push_inst32(compiler, POP_W | reg_list));
+ }
+
+ if (frame_size > 0)
+ return push_inst16(compiler, SUB_SP_I | (((sljit_ins)frame_size - sizeof(sljit_sw)) >> 2));
+
+ if (lr_dst != 0)
+ return SLJIT_SUCCESS;
+
+ return push_inst16(compiler, ADD_SP_I | 1);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ return emit_stack_frame_release(compiler, 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));
+ src = TMP_REG1;
+ srcw = 0;
+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, src)));
+ src = TMP_REG1;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 1));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
+}
+
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
+#if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _WIN32
+extern unsigned long long __rt_udiv(unsigned int denominator, unsigned int numerator);
+extern long long __rt_sdiv(int denominator, int numerator);
+#elif defined(__GNUC__)
+extern unsigned int __aeabi_uidivmod(unsigned int numerator, int unsigned denominator);
+extern int __aeabi_idivmod(int numerator, int denominator);
+#else
+#error "Software divmod functions are needed"
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
+{
+#if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)
+ sljit_uw saved_reg_list[3];
+ sljit_uw saved_reg_count;
+#endif
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op0(compiler, op));
+
+ op = GET_OPCODE(op);
+ switch (op) {
+ case SLJIT_BREAKPOINT:
+ return push_inst16(compiler, BKPT);
+ case SLJIT_NOP:
+ return push_inst16(compiler, NOP);
+ case SLJIT_LMUL_UW:
+ case SLJIT_LMUL_SW:
+ return push_inst32(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)
+ | RD4(SLJIT_R1) | RT4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1));
+#if (defined __ARM_FEATURE_IDIV) || (defined __ARM_ARCH_EXT_IDIV__)
+ case SLJIT_DIVMOD_UW:
+ case SLJIT_DIVMOD_SW:
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, SLJIT_R0)));
+ FAIL_IF(push_inst32(compiler, (op == SLJIT_DIVMOD_UW ? UDIV : SDIV) | RD4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1)));
+ FAIL_IF(push_inst32(compiler, MUL | RD4(SLJIT_R1) | RN4(SLJIT_R0) | RM4(SLJIT_R1)));
+ return push_inst32(compiler, SUB_W | RD4(SLJIT_R1) | RN4(TMP_REG1) | RM4(SLJIT_R1));
+ case SLJIT_DIV_UW:
+ case SLJIT_DIV_SW:
+ return push_inst32(compiler, (op == SLJIT_DIV_UW ? UDIV : SDIV) | RD4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1));
+#else /* !__ARM_FEATURE_IDIV && !__ARM_ARCH_EXT_IDIV__ */
+ case SLJIT_DIVMOD_UW:
+ case SLJIT_DIVMOD_SW:
+ case SLJIT_DIV_UW:
+ case SLJIT_DIV_SW:
+ SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
+ SLJIT_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 3);
+
+ saved_reg_count = 0;
+ if (compiler->scratches >= 4)
+ saved_reg_list[saved_reg_count++] = 3;
+ if (compiler->scratches >= 3)
+ saved_reg_list[saved_reg_count++] = 2;
+ if (op >= SLJIT_DIV_UW)
+ saved_reg_list[saved_reg_count++] = 1;
+
+ if (saved_reg_count > 0) {
+ FAIL_IF(push_inst32(compiler, 0xf84d0d00 | (saved_reg_count >= 3 ? 16 : 8)
+ | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */));
+ if (saved_reg_count >= 2) {
+ SLJIT_ASSERT(saved_reg_list[1] < 8);
+ FAIL_IF(push_inst16(compiler, 0x9001 | (saved_reg_list[1] << 8) /* str rX, [sp, #4] */));
+ }
+ if (saved_reg_count >= 3) {
+ SLJIT_ASSERT(saved_reg_list[2] < 8);
+ FAIL_IF(push_inst16(compiler, 0x9002 | (saved_reg_list[2] << 8) /* str rX, [sp, #8] */));
+ }
+ }
+
+#ifdef _WIN32
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, SLJIT_R0)));
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_R0, SLJIT_R1)));
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_R1, TMP_REG1)));
+ FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
+ ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_ADDR(__rt_udiv) : SLJIT_FUNC_ADDR(__rt_sdiv))));
+#elif defined(__GNUC__)
+ FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
+ ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_ADDR(__aeabi_uidivmod) : SLJIT_FUNC_ADDR(__aeabi_idivmod))));
+#else
+#error "Software divmod functions are needed"
+#endif
+
+ if (saved_reg_count > 0) {
+ if (saved_reg_count >= 3) {
+ SLJIT_ASSERT(saved_reg_list[2] < 8);
+ FAIL_IF(push_inst16(compiler, 0x9802 | (saved_reg_list[2] << 8) /* ldr rX, [sp, #8] */));
+ }
+ if (saved_reg_count >= 2) {
+ SLJIT_ASSERT(saved_reg_list[1] < 8);
+ FAIL_IF(push_inst16(compiler, 0x9801 | (saved_reg_list[1] << 8) /* ldr rX, [sp, #4] */));
+ }
+ return push_inst32(compiler, 0xf85d0b00 | (saved_reg_count >= 3 ? 16 : 8)
+ | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
+ }
+ return SLJIT_SUCCESS;
+#endif /* __ARM_FEATURE_IDIV || __ARM_ARCH_EXT_IDIV__ */
+ case SLJIT_MEMORY_BARRIER:
+ return push_inst32(compiler, DMB_SY);
+ case SLJIT_ENDBR:
+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
+ return SLJIT_SUCCESS;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r, flags;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ op = GET_OPCODE(op);
+ if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {
+ switch (op) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ case SLJIT_MOV_P:
+ flags = WORD_SIZE;
+ break;
+ case SLJIT_MOV_U8:
+ flags = BYTE_SIZE;
+ if (src == SLJIT_IMM)
+ srcw = (sljit_u8)srcw;
+ break;
+ case SLJIT_MOV_S8:
+ flags = BYTE_SIZE | SIGNED;
+ if (src == SLJIT_IMM)
+ srcw = (sljit_s8)srcw;
+ break;
+ case SLJIT_MOV_U16:
+ flags = HALF_SIZE;
+ if (src == SLJIT_IMM)
+ srcw = (sljit_u16)srcw;
+ break;
+ case SLJIT_MOV_S16:
+ flags = HALF_SIZE | SIGNED;
+ if (src == SLJIT_IMM)
+ srcw = (sljit_s16)srcw;
+ break;
+ default:
+ SLJIT_UNREACHABLE();
+ flags = 0;
+ break;
+ }
+
+ if (src == SLJIT_IMM)
+ FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG2, (sljit_uw)srcw));
+ else if (src & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, flags, dst_r, src, srcw, TMP_REG1));
+ else if (FAST_IS_REG(dst))
+ return emit_op_imm(compiler, op, dst_r, TMP_REG2, (sljit_uw)src);
+ else
+ dst_r = src;
+
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+
+ return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG1);
+ }
+
+ SLJIT_COMPILE_ASSERT(WORD_SIZE == 0, word_size_must_be_0);
+ flags = WORD_SIZE;
+
+ if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {
+ if (!(dst & SLJIT_MEM) && (!(src & SLJIT_MEM) || op == SLJIT_REV_S16))
+ op |= REGISTER_OP;
+ flags |= HALF_SIZE;
+ }
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, flags, TMP_REG1, src, srcw, TMP_REG1));
+ src = TMP_REG1;
+ }
+
+ emit_op_imm(compiler, op, dst_r, TMP_REG2, (sljit_uw)src);
+
+ if (SLJIT_UNLIKELY(dst & SLJIT_MEM))
+ return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG1);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 dst_reg, src2_tmp_reg, flags;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
+
+ if (dst == TMP_REG1)
+ flags |= UNUSED_RETURN;
+
+ if (src2 == SLJIT_IMM)
+ flags |= ARG2_IMM;
+ else if (src2 & SLJIT_MEM) {
+ src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;
+ emit_op_mem(compiler, WORD_SIZE, src2_tmp_reg, src2, src2w, TMP_REG1);
+ src2w = src2_tmp_reg;
+ } else
+ src2w = src2;
+
+ if (src1 == SLJIT_IMM)
+ flags |= ARG1_IMM;
+ else if (src1 & SLJIT_MEM) {
+ emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src1, src1w, TMP_REG1);
+ src1w = TMP_REG1;
+ } else
+ src1w = src1;
+
+ emit_op_imm(compiler, flags | GET_OPCODE(op), dst_reg, (sljit_uw)src1w, (sljit_uw)src2w);
+
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG1);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MULADD:
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, op, dst_reg, 0, src1, src1w, src2, src2w);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1_reg,
+ sljit_s32 src2_reg,
+ sljit_s32 src3, sljit_sw src3w)
+{
+ sljit_s32 is_left;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
+
+ op = GET_OPCODE(op);
+ is_left = (op == SLJIT_SHL || op == SLJIT_MSHL);
+
+ if (src1_reg == src2_reg) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, is_left ? SLJIT_ROTL : SLJIT_ROTR, dst_reg, 0, src1_reg, 0, src3, src3w);
+ }
+
+ ADJUST_LOCAL_OFFSET(src3, src3w);
+
+ if (src3 == SLJIT_IMM) {
+ src3w &= 0x1f;
+
+ if (src3w == 0)
+ return SLJIT_SUCCESS;
+
+ if (IS_2_LO_REGS(dst_reg, src1_reg))
+ FAIL_IF(push_inst16(compiler, (is_left ? LSLSI : LSRSI) | RD3(dst_reg) | RN3(src1_reg) | ((sljit_ins)src3w << 6)));
+ else
+ FAIL_IF(push_inst32(compiler, (is_left ? LSL_WI : LSR_WI) | RD4(dst_reg) | RM4(src1_reg) | IMM5(src3w)));
+
+ src3w = (src3w ^ 0x1f) + 1;
+ return push_inst32(compiler, ORR_W | RD4(dst_reg) | RN4(dst_reg) | RM4(src2_reg) | (is_left ? 0x10 : 0x0) | IMM5(src3w));
+ }
+
+ if (src3 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src3, src3w, TMP_REG2));
+ src3 = TMP_REG2;
+ }
+
+ if (op == SLJIT_MSHL || op == SLJIT_MLSHR || dst_reg == src3) {
+ FAIL_IF(push_inst32(compiler, ANDI | RD4(TMP_REG2) | RN4(src3) | 0x1f));
+ src3 = TMP_REG2;
+ }
+
+ if (dst_reg == src1_reg && IS_2_LO_REGS(dst_reg, src3))
+ FAIL_IF(push_inst16(compiler, (is_left ? LSLS : LSRS) | RD3(dst_reg) | RN3(src3)));
+ else
+ FAIL_IF(push_inst32(compiler, (is_left ? LSL_W : LSR_W) | RD4(dst_reg) | RN4(src1_reg) | RM4(src3)));
+
+ FAIL_IF(push_inst32(compiler, (is_left ? LSR_WI : LSL_WI) | RD4(TMP_REG1) | RM4(src2_reg) | (1 << 6)));
+ FAIL_IF(push_inst32(compiler, EORI | RD4(TMP_REG2) | RN4(src3) | 0x1f));
+ FAIL_IF(push_inst32(compiler, (is_left ? LSR_W : LSL_W) | RD4(TMP_REG1) | RN4(TMP_REG1) | RM4(TMP_REG2)));
+ return push_inst32(compiler, ORR_W | RD4(dst_reg) | RN4(dst_reg) | RM4(TMP_REG1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r, tmp_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= 0x1f;
+
+ if (src2 == SLJIT_IMM) {
+ src2w = (sljit_sw)((sljit_uw)src2w << shift_arg);
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
+ src1 = TMP_REG1;
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src1, src1w, TMP_REG1));
+ src1 = TMP_REG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, tmp_r, src2, src2w, tmp_r));
+ src2 = tmp_r;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ FAIL_IF(push_inst32(compiler, ADD_W | RD4(dst_r) | RN4(src1) | RM4(src2) | ((sljit_ins)(shift_arg & 0x3) << 6) | ((sljit_ins)(shift_arg & 0x1c) << 10)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG1);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ switch (op) {
+ case SLJIT_FAST_RETURN:
+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
+
+ if (FAST_IS_REG(src)) {
+ if (src != TMP_REG2)
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src)));
+ } else
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2));
+
+ return push_inst16(compiler, BX | RN3(TMP_REG2));
+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
+ return SLJIT_SUCCESS;
+ case SLJIT_PREFETCH_L1:
+ case SLJIT_PREFETCH_L2:
+ case SLJIT_PREFETCH_L3:
+ case SLJIT_PREFETCH_ONCE:
+ return emit_op_mem(compiler, PRELOAD, TMP_PC, src, srcw, TMP_REG1);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 size, dst_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ switch (op) {
+ case SLJIT_FAST_ENTER:
+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
+
+ if (FAST_IS_REG(dst)) {
+ if (dst == TMP_REG2)
+ return SLJIT_SUCCESS;
+ return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2));
+ }
+ break;
+ case SLJIT_GET_RETURN_ADDRESS:
+ size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 0);
+
+ if (compiler->fsaveds > 0 || compiler->fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ /* The size of pc is not added above. */
+ if ((size & SSIZE_OF(sw)) == 0)
+ size += SSIZE_OF(sw);
+
+ size += GET_SAVED_FLOAT_REGISTERS_SIZE(compiler->fscratches, compiler->fsaveds, f64);
+ }
+
+ SLJIT_ASSERT(((compiler->local_size + size + SSIZE_OF(sw)) & 0x7) == 0);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + size, TMP_REG1));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, TMP_REG1);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
+{
+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
+
+ if (type == SLJIT_GP_REGISTER)
+ return reg_map[reg];
+
+ if (type == SLJIT_FLOAT_REGISTER || type == SLJIT_SIMD_REG_64)
+ return freg_map[reg];
+
+ if (type == SLJIT_SIMD_REG_128)
+ return freg_map[reg] & ~0x1;
+
+ return -1;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_u32 size)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
+
+ if (size == 2)
+ return push_inst16(compiler, *(sljit_u16*)instruction);
+ return push_inst32(compiler, *(sljit_ins*)instruction);
+}
+
+/* --------------------------------------------------------------------- */
+/* Floating point operators */
+/* --------------------------------------------------------------------- */
+
+#define FPU_LOAD (1 << 20)
+
+static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
+{
+ sljit_uw imm;
+ sljit_ins inst = VSTR_F32 | (flags & (SLJIT_32 | FPU_LOAD));
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+
+ /* Fast loads and stores. */
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | (((sljit_uw)argw & 0x3) << 6)));
+ arg = SLJIT_MEM | TMP_REG1;
+ argw = 0;
+ }
+
+ if ((arg & REG_MASK) && (argw & 0x3) == 0) {
+ if (!(argw & ~0x3fc))
+ return push_inst32(compiler, inst | 0x800000 | RN4(arg & REG_MASK) | VD4(reg) | ((sljit_uw)argw >> 2));
+ if (!(-argw & ~0x3fc))
+ return push_inst32(compiler, inst | RN4(arg & REG_MASK) | VD4(reg) | ((sljit_uw)-argw >> 2));
+ }
+
+ if (arg & REG_MASK) {
+ if (emit_set_delta(compiler, TMP_REG1, arg & REG_MASK, argw) != SLJIT_ERR_UNSUPPORTED) {
+ FAIL_IF(compiler->error);
+ return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | VD4(reg));
+ }
+
+ imm = get_imm((sljit_uw)argw & ~(sljit_uw)0x3fc);
+ if (imm != INVALID_IMM) {
+ FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm));
+ return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | VD4(reg) | (((sljit_uw)argw & 0x3fc) >> 2));
+ }
+
+ imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0x3fc);
+ if (imm != INVALID_IMM) {
+ argw = -argw;
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm));
+ return push_inst32(compiler, inst | RN4(TMP_REG1) | VD4(reg) | (((sljit_uw)argw & 0x3fc) >> 2));
+ }
+ }
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)argw));
+ if (arg & REG_MASK)
+ FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, (arg & REG_MASK))));
+ return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | VD4(reg));
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ op ^= SLJIT_32;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src, srcw));
+ src = TMP_FREG1;
+ }
+
+ FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_32) | VD4(TMP_FREG1) | VM4(src)));
+
+ if (FAST_IS_REG(dst))
+ return push_inst32(compiler, VMOV | (1 << 20) | RT4(dst) | VN4(TMP_FREG1));
+
+ /* Store the integer value from a VFP register. */
+ return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);
+}
+
+static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (FAST_IS_REG(src))
+ FAIL_IF(push_inst32(compiler, VMOV | RT4(src) | VN4(TMP_FREG1)));
+ else if (src & SLJIT_MEM) {
+ /* Load the integer value into a VFP register. */
+ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));
+ }
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));
+ FAIL_IF(push_inst32(compiler, VMOV | RT4(TMP_REG1) | VN4(TMP_FREG1)));
+ }
+
+ FAIL_IF(push_inst32(compiler, ins | VD4(dst_r) | VM4(TMP_FREG1)));
+
+ if (dst & SLJIT_MEM)
+ return emit_fop_mem(compiler, (ins & SLJIT_32), TMP_FREG1, dst, dstw);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ return sljit_emit_fop1_conv_f64_from_w(compiler, VCVT_F32_S32 | (~op & SLJIT_32), dst, dstw, src, srcw);
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ return sljit_emit_fop1_conv_f64_from_w(compiler, VCVT_F32_U32 | (~op & SLJIT_32), dst, dstw, src, srcw);
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ op ^= SLJIT_32;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));
+ src1 = TMP_FREG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));
+ src2 = TMP_FREG2;
+ }
+
+ FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_32) | VD4(src1) | VM4(src2)));
+ FAIL_IF(push_inst32(compiler, VMRS));
+
+ if (GET_FLAG_TYPE(op) != SLJIT_UNORDERED_OR_EQUAL)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst16(compiler, IT | (0x6 << 4) | 0x8));
+ return push_inst16(compiler, CMP /* Rm, Rn = r0 */);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+
+ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100), float_transfer_bit_error);
+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32)
+ op ^= SLJIT_32;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, dst_r, src, srcw));
+ src = dst_r;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_F64:
+ if (src != dst_r) {
+ if (!(dst & SLJIT_MEM))
+ FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src)));
+ else
+ dst_r = src;
+ }
+ break;
+ case SLJIT_NEG_F64:
+ FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src)));
+ break;
+ case SLJIT_ABS_F64:
+ FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src)));
+ break;
+ case SLJIT_CONV_F64_FROM_F32:
+ FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src)));
+ op ^= SLJIT_32;
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_fop_mem(compiler, (op & SLJIT_32), dst_r, dst, dstw);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ op ^= SLJIT_32;
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));
+ src1 = TMP_FREG1;
+ }
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));
+ src2 = TMP_FREG2;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD_F64:
+ FAIL_IF(push_inst32(compiler, VADD_F32 | (op & SLJIT_32) | VD4(dst_r) | VN4(src1) | VM4(src2)));
+ break;
+ case SLJIT_SUB_F64:
+ FAIL_IF(push_inst32(compiler, VSUB_F32 | (op & SLJIT_32) | VD4(dst_r) | VN4(src1) | VM4(src2)));
+ break;
+ case SLJIT_MUL_F64:
+ FAIL_IF(push_inst32(compiler, VMUL_F32 | (op & SLJIT_32) | VD4(dst_r) | VN4(src1) | VM4(src2)));
+ break;
+ case SLJIT_DIV_F64:
+ FAIL_IF(push_inst32(compiler, VDIV_F32 | (op & SLJIT_32) | VD4(dst_r) | VN4(src1) | VM4(src2)));
+ break;
+ case SLJIT_COPYSIGN_F64:
+ FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | VN4(src2) | RT4(TMP_REG1) | ((op & SLJIT_32) ? (1 << 7) : 0)));
+ FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(src1)));
+ FAIL_IF(push_inst32(compiler, CMPI_W | RN4(TMP_REG1) | 0));
+ FAIL_IF(push_inst16(compiler, IT | (0xb << 4) | 0x8));
+ return push_inst32(compiler, VNEG_F32 | (op & SLJIT_32) | VD4(dst_r) | VM4(dst_r));
+ }
+
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f32 value)
+{
+#if defined(__ARM_NEON) && __ARM_NEON
+ sljit_u32 exp;
+ sljit_ins ins;
+#endif /* NEON */
+ union {
+ sljit_u32 imm;
+ sljit_f32 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset32(compiler, freg, value));
+
+ u.value = value;
+
+#if defined(__ARM_NEON) && __ARM_NEON
+ if ((u.imm << (32 - 19)) == 0) {
+ exp = (u.imm >> (23 + 2)) & 0x3f;
+
+ if (exp == 0x20 || exp == 0x1f) {
+ ins = ((u.imm >> 24) & 0x80) | ((u.imm >> 19) & 0x7f);
+ return push_inst32(compiler, (VMOV_F32 ^ (1 << 6)) | ((ins & 0xf0) << 12) | VD4(freg) | (ins & 0xf));
+ }
+ }
+#endif /* NEON */
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));
+ return push_inst32(compiler, VMOV | VN4(freg) | RT4(TMP_REG1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value)
+{
+#if defined(__ARM_NEON) && __ARM_NEON
+ sljit_u32 exp;
+ sljit_ins ins;
+#endif /* NEON */
+ union {
+ sljit_u32 imm[2];
+ sljit_f64 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset64(compiler, freg, value));
+
+ u.value = value;
+
+#if defined(__ARM_NEON) && __ARM_NEON
+ if (u.imm[0] == 0 && (u.imm[1] << (64 - 48)) == 0) {
+ exp = (u.imm[1] >> ((52 - 32) + 2)) & 0x1ff;
+
+ if (exp == 0x100 || exp == 0xff) {
+ ins = ((u.imm[1] >> (56 - 32)) & 0x80) | ((u.imm[1] >> (48 - 32)) & 0x7f);
+ return push_inst32(compiler, (VMOV_F32 ^ (1 << 6)) | (1 << 8) | ((ins & 0xf0) << 12) | VD4(freg) | (ins & 0xf));
+ }
+ }
+#endif /* NEON */
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0]));
+ if (u.imm[0] == u.imm[1])
+ return push_inst32(compiler, VMOV2 | RN4(TMP_REG1) | RT4(TMP_REG1) | VM4(freg));
+
+ FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1]));
+ return push_inst32(compiler, VMOV2 | RN4(TMP_REG2) | RT4(TMP_REG1) | VM4(freg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg)
+{
+ sljit_s32 reg2;
+ sljit_ins inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
+
+ if (reg & REG_PAIR_MASK) {
+ reg2 = REG_PAIR_SECOND(reg);
+ reg = REG_PAIR_FIRST(reg);
+
+ inst = VMOV2 | RN4(reg) | RT4(reg2) | VM4(freg);
+ } else {
+ inst = VMOV | VN4(freg) | RT4(reg);
+
+ if (!(op & SLJIT_32))
+ inst |= 1 << 7;
+ }
+
+ if (GET_OPCODE(op) == SLJIT_COPY_FROM_F64)
+ inst |= 1 << 20;
+
+ return push_inst32(compiler, inst);
+}
+
+/* --------------------------------------------------------------------- */
+/* Conditional instructions */
+/* --------------------------------------------------------------------- */
+
+static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
+{
+ switch (type) {
+ case SLJIT_EQUAL:
+ case SLJIT_ATOMIC_STORED:
+ case SLJIT_F_EQUAL:
+ case SLJIT_ORDERED_EQUAL:
+ case SLJIT_UNORDERED_OR_EQUAL:
+ return 0x0;
+
+ case SLJIT_NOT_EQUAL:
+ case SLJIT_ATOMIC_NOT_STORED:
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_NOT_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ return 0x1;
+
+ case SLJIT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
+ return 0x2;
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_LESS:
+ return 0x3;
+
+ case SLJIT_NOT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
+ return 0x3;
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_GREATER_EQUAL:
+ return 0x2;
+
+ case SLJIT_GREATER:
+ case SLJIT_UNORDERED_OR_GREATER:
+ return 0x8;
+
+ case SLJIT_LESS_EQUAL:
+ case SLJIT_F_LESS_EQUAL:
+ case SLJIT_ORDERED_LESS_EQUAL:
+ return 0x9;
+
+ case SLJIT_SIG_LESS:
+ case SLJIT_UNORDERED_OR_LESS:
+ return 0xb;
+
+ case SLJIT_SIG_GREATER_EQUAL:
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_ORDERED_GREATER_EQUAL:
+ return 0xa;
+
+ case SLJIT_SIG_GREATER:
+ case SLJIT_F_GREATER:
+ case SLJIT_ORDERED_GREATER:
+ return 0xc;
+
+ case SLJIT_SIG_LESS_EQUAL:
+ case SLJIT_UNORDERED_OR_LESS_EQUAL:
+ return 0xd;
+
+ case SLJIT_OVERFLOW:
+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
+ return 0x1;
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_UNORDERED:
+ return 0x6;
+
+ case SLJIT_NOT_OVERFLOW:
+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
+ return 0x0;
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_ORDERED:
+ return 0x7;
+
+ case SLJIT_F_LESS:
+ case SLJIT_ORDERED_LESS:
+ return 0x4;
+
+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:
+ return 0x5;
+
+ default: /* SLJIT_JUMP */
+ SLJIT_UNREACHABLE();
+ return 0xe;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_label(compiler));
+
+ if (compiler->last_label && compiler->last_label->size == compiler->size)
+ return compiler->last_label;
+
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+ PTR_FAIL_IF(!label);
+ set_label(label, compiler);
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, i;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (alignment <= SLJIT_LABEL_ALIGN_2) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_u16);
+
+ for (i = (mask >> 1); i != 0; i--)
+ PTR_FAIL_IF(push_inst16(compiler, NOP));
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ for (i = (buffers->size + 1) >> 1; i > 0; i--)
+ PTR_FAIL_IF(push_inst16(compiler, NOP));
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
+{
+ struct sljit_jump *jump;
+ sljit_ins cc;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_jump(compiler, type));
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ type &= 0xff;
+
+ if (type < SLJIT_JUMP) {
+ jump->flags |= IS_COND;
+ cc = get_cc(compiler, type);
+ jump->flags |= cc << 8;
+ PTR_FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ }
+
+ jump->addr = compiler->size;
+ if (type <= SLJIT_JUMP)
+ PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG1)));
+ else {
+ jump->flags |= IS_BL;
+ PTR_FAIL_IF(push_inst16(compiler, BLX | RN3(TMP_REG1)));
+ }
+
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += JUMP_MAX_SIZE - 1;
+ return jump;
+}
+
+#ifdef __SOFTFP__
+
+static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src, sljit_u32 *extra_space)
+{
+ sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;
+ sljit_u32 offset = 0;
+ sljit_u32 word_arg_offset = 0;
+ sljit_u32 float_arg_count = 0;
+ sljit_s32 types = 0;
+ sljit_u32 src_offset = 4 * sizeof(sljit_sw);
+ sljit_u8 offsets[4];
+ sljit_u8 *offset_ptr = offsets;
+
+ if (src && FAST_IS_REG(*src))
+ src_offset = (sljit_u32)reg_map[*src] * sizeof(sljit_sw);
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ while (arg_types) {
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
+
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset & 0x7)
+ offset += sizeof(sljit_sw);
+ *offset_ptr++ = (sljit_u8)offset;
+ offset += sizeof(sljit_f64);
+ float_arg_count++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ *offset_ptr++ = (sljit_u8)offset;
+ offset += sizeof(sljit_f32);
+ float_arg_count++;
+ break;
+ default:
+ *offset_ptr++ = (sljit_u8)offset;
+ offset += sizeof(sljit_sw);
+ word_arg_offset += sizeof(sljit_sw);
+ break;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {
+ /* Keep lr register on the stack. */
+ if (is_tail_call)
+ offset += sizeof(sljit_sw);
+
+ offset = ((offset - 4 * sizeof(sljit_sw)) + 0x7) & ~(sljit_uw)0x7;
+
+ *extra_space = offset;
+
+ if (is_tail_call)
+ FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset));
+ else
+ FAIL_IF(push_inst16(compiler, SUB_SP_I | (offset >> 2)));
+ } else {
+ if (is_tail_call)
+ FAIL_IF(emit_stack_frame_release(compiler, -1));
+ *extra_space = 0;
+ }
+
+ SLJIT_ASSERT(reg_map[TMP_REG1] == 12);
+
+ /* Process arguments in reversed direction. */
+ while (types) {
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ float_arg_count--;
+ offset = *(--offset_ptr);
+
+ SLJIT_ASSERT((offset & 0x7) == 0);
+
+ if (offset < 4 * sizeof(sljit_sw)) {
+ if (src_offset == offset || src_offset == offset + sizeof(sljit_sw)) {
+ FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));
+ *src = TMP_REG1;
+ }
+ FAIL_IF(push_inst32(compiler, VMOV2 | 0x100000 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));
+ } else
+ FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800100 | RN4(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ float_arg_count--;
+ offset = *(--offset_ptr);
+
+ if (offset < 4 * sizeof(sljit_sw)) {
+ if (src_offset == offset) {
+ FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));
+ *src = TMP_REG1;
+ }
+ FAIL_IF(push_inst32(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (offset << 10)));
+ } else
+ FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800000 | RN4(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));
+ break;
+ default:
+ word_arg_offset -= sizeof(sljit_sw);
+ offset = *(--offset_ptr);
+
+ SLJIT_ASSERT(offset >= word_arg_offset);
+
+ if (offset != word_arg_offset) {
+ if (offset < 4 * sizeof(sljit_sw)) {
+ if (src_offset == offset) {
+ FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));
+ *src = TMP_REG1;
+ }
+ else if (src_offset == word_arg_offset) {
+ *src = (sljit_s32)(1 + (offset >> 2));
+ src_offset = offset;
+ }
+ FAIL_IF(push_inst16(compiler, MOV | (offset >> 2) | (word_arg_offset << 1)));
+ } else
+ FAIL_IF(push_inst16(compiler, STR_SP | (word_arg_offset << 6) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));
+ }
+ break;
+ }
+
+ types >>= SLJIT_ARG_SHIFT;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
+{
+ if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64)
+ FAIL_IF(push_inst32(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0));
+ if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32)
+ FAIL_IF(push_inst32(compiler, VMOV | (0 << 16) | (0 << 12)));
+
+ return SLJIT_SUCCESS;
+}
+
+#else
+
+static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
+{
+ sljit_u32 offset = SLJIT_FR0;
+ sljit_u32 new_offset = SLJIT_FR0;
+ sljit_u32 f32_offset = 0;
+
+ /* Remove return value. */
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset != new_offset)
+ FAIL_IF(push_inst32(compiler, VMOV_F32 | SLJIT_32 | VD4(new_offset) | VM4(offset)));
+
+ new_offset++;
+ offset++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (f32_offset != 0) {
+ FAIL_IF(push_inst32(compiler, VMOV_F32 | 0x400000 | VD4(f32_offset) | VM4(offset)));
+ f32_offset = 0;
+ } else {
+ if (offset != new_offset)
+ FAIL_IF(push_inst32(compiler, VMOV_F32 | 0x400000 | VD4(new_offset) | VM4(offset)));
+ f32_offset = new_offset;
+ new_offset++;
+ }
+ offset++;
+ break;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types)
+{
+#ifdef __SOFTFP__
+ struct sljit_jump *jump;
+ sljit_u32 extra_space = (sljit_u32)type;
+#endif
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
+
+#ifdef __SOFTFP__
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
+ PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
+ SLJIT_ASSERT((extra_space & 0x7) == 0);
+
+ if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+
+ SLJIT_SKIP_CHECKS(compiler);
+ jump = sljit_emit_jump(compiler, type);
+ PTR_FAIL_IF(jump == NULL);
+
+ if (extra_space > 0) {
+ if (type & SLJIT_CALL_RETURN)
+ PTR_FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)
+ | RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));
+
+ PTR_FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));
+
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG2)));
+ return jump;
+ }
+ }
+
+ SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
+ PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
+ return jump;
+ }
+#endif /* __SOFTFP__ */
+
+ if (type & SLJIT_CALL_RETURN) {
+ /* ldmia sp!, {..., lr} */
+ PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ }
+
+#ifndef __SOFTFP__
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)
+ PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
+#endif /* !__SOFTFP__ */
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_jump(compiler, type);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
+{
+ struct sljit_jump *jump;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ SLJIT_ASSERT(reg_map[TMP_REG1] != 14);
+
+ if (src != SLJIT_IMM) {
+ if (FAST_IS_REG(src)) {
+ SLJIT_ASSERT(reg_map[src] != 14);
+ return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(src));
+ }
+
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, type <= SLJIT_JUMP ? TMP_PC : TMP_REG1, src, srcw, TMP_REG1));
+ if (type >= SLJIT_FAST_CALL)
+ return push_inst16(compiler, BLX | RN3(TMP_REG1));
+ }
+
+ /* These jumps are converted to jump/call instructions when possible. */
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF(!jump);
+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
+ jump->u.target = (sljit_uw)srcw;
+
+ jump->addr = compiler->size;
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += JUMP_MAX_SIZE - 1;
+ return push_inst16(compiler, (type <= SLJIT_JUMP ? BX : BLX) | RN3(TMP_REG1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types,
+ sljit_s32 src, sljit_sw srcw)
+{
+#ifdef __SOFTFP__
+ sljit_u32 extra_space = (sljit_u32)type;
+#endif
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));
+ src = TMP_REG1;
+ }
+
+ if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) {
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, src)));
+ src = TMP_REG1;
+ }
+
+#ifdef __SOFTFP__
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
+ FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
+ SLJIT_ASSERT((extra_space & 0x7) == 0);
+
+ if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
+ type = SLJIT_JUMP;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
+
+ if (extra_space > 0) {
+ if (type & SLJIT_CALL_RETURN)
+ FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)
+ | RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));
+
+ FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));
+
+ if (type & SLJIT_CALL_RETURN)
+ return push_inst16(compiler, BX | RN3(TMP_REG2));
+ }
+
+ SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
+ return softfloat_post_call_with_args(compiler, arg_types);
+ }
+#endif /* __SOFTFP__ */
+
+ if (type & SLJIT_CALL_RETURN) {
+ /* ldmia sp!, {..., lr} */
+ FAIL_IF(emit_stack_frame_release(compiler, -1));
+ type = SLJIT_JUMP;
+ }
+
+#ifndef __SOFTFP__
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)
+ FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
+#endif /* !__SOFTFP__ */
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, type, src, srcw);
+}
+
+#ifdef __SOFTFP__
+
+static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
+{
+ if (compiler->options & SLJIT_ENTER_REG_ARG) {
+ if (src == SLJIT_FR0)
+ return SLJIT_SUCCESS;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw);
+ }
+
+ if (FAST_IS_REG(src)) {
+ if (op & SLJIT_32)
+ return push_inst32(compiler, VMOV | (1 << 20) | VN4(src) | RT4(SLJIT_R0));
+ return push_inst32(compiler, VMOV2 | (1 << 20) | VM4(src) | RT4(SLJIT_R0) | RN4(SLJIT_R1));
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+
+ if (op & SLJIT_32)
+ return sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, src, srcw);
+ return sljit_emit_mem(compiler, SLJIT_MOV, SLJIT_REG_PAIR(SLJIT_R0, SLJIT_R1), src, srcw);
+}
+
+#endif /* __SOFTFP__ */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 type)
+{
+ sljit_s32 dst_r, flags = GET_ALL_FLAGS(op);
+ sljit_ins cc;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ op = GET_OPCODE(op);
+ cc = get_cc(compiler, type);
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (op < SLJIT_ADD) {
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
+ if (reg_map[dst_r] > 7) {
+ FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 1));
+ FAIL_IF(push_inst32(compiler, MOV_WI | RD4(dst_r) | 0));
+ } else {
+ /* The movsi (immediate) instruction does not set flags in IT block. */
+ FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 1));
+ FAIL_IF(push_inst16(compiler, MOVSI | RDN3(dst_r) | 0));
+ }
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, TMP_REG2);
+ }
+
+ if (dst & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2));
+
+ if (op == SLJIT_AND) {
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | (((cc & 0x1) ^ 0x1) << 3) | 0x4));
+ FAIL_IF(push_inst32(compiler, ANDI | RN4(dst_r) | RD4(dst_r) | 1));
+ FAIL_IF(push_inst32(compiler, ANDI | RN4(dst_r) | RD4(dst_r) | 0));
+ }
+ else {
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ FAIL_IF(push_inst32(compiler, ((op == SLJIT_OR) ? ORRI : EORI) | RN4(dst_r) | RD4(dst_r) | 1));
+ }
+
+ if (dst & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG1, dst, dstw, TMP_REG2));
+
+ if (!(flags & SLJIT_SET_Z))
+ return SLJIT_SUCCESS;
+
+ /* The condition must always be set, even if the ORR/EORI is not executed above. */
+ return push_inst32(compiler, MOV_W | SET_FLAGS | RD4(TMP_REG1) | RM4(dst_r));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_reg)
+{
+ sljit_uw cc, tmp, tmp2;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ if (src2_reg != dst_reg && src1 == dst_reg) {
+ src1 = src2_reg;
+ src1w = 0;
+ src2_reg = dst_reg;
+ if (!(type & SLJIT_COMPARE_SELECT))
+ type ^= 0x1;
+ }
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, (src2_reg != dst_reg) ? dst_reg : TMP_REG1, src1, src1w, TMP_REG1));
+
+ if (src2_reg != dst_reg) {
+ src1 = src2_reg;
+ src1w = 0;
+ if (!(type & SLJIT_COMPARE_SELECT))
+ type ^= 0x1;
+ } else {
+ src1 = TMP_REG1;
+ src1w = 0;
+ }
+ } else if (dst_reg != src2_reg)
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(dst_reg, src2_reg)));
+
+ if ((type & SLJIT_COMPARE_SELECT))
+ type ^= 0x1;
+ cc = get_cc(compiler, type & ~(SLJIT_32 | SLJIT_COMPARE_SELECT));
+
+ if (src1 == SLJIT_IMM && (type & SLJIT_COMPARE_SELECT)) {
+ tmp = (sljit_uw)src1w;
+ if (tmp <= 0xff && reg_map[dst_reg] <= 7) {
+ if (type & SLJIT_COMPARE_SELECT)
+ FAIL_IF(push_inst16(compiler, CMPI | IMM8(tmp) | RDN3(dst_reg)));
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ return push_inst16(compiler, MOVI | IMM8(tmp) | RDN3(dst_reg));
+ }
+
+ tmp = get_imm((sljit_uw)src1w);
+ if (tmp != INVALID_IMM) {
+ if (type & SLJIT_COMPARE_SELECT)
+ FAIL_IF(push_inst32(compiler, CMPI_W | RN4(dst_reg) | tmp));
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ return push_inst32(compiler, MOV_WI | RD4(dst_reg) | tmp);
+ }
+
+ tmp = get_imm(~(sljit_uw)src1w);
+ if (tmp != INVALID_IMM && (type & SLJIT_COMPARE_SELECT)) {
+ tmp2 = get_imm(NEGATE(src1w));
+ if (tmp2 != INVALID_IMM)
+ FAIL_IF(push_inst32(compiler, CMNI_W | RN4(dst_reg) | tmp2));
+ else
+ tmp = INVALID_IMM;
+ }
+
+ if (tmp != INVALID_IMM) {
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ return push_inst32(compiler, MVN_WI | RD4(dst_reg) | tmp);
+ }
+
+ if (type & SLJIT_COMPARE_SELECT) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
+ src1 = TMP_REG1;
+ }
+ }
+
+ if (src1 != SLJIT_IMM) {
+ if (type & SLJIT_COMPARE_SELECT) {
+ if (IS_2_LO_REGS(dst_reg, src1))
+ FAIL_IF(push_inst16(compiler, CMP | RD3(dst_reg) | RN3(src1)));
+ else
+ FAIL_IF(push_inst16(compiler, CMP_X | SET_REGS44(dst_reg, src1)));
+ }
+
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ return push_inst16(compiler, MOV | SET_REGS44(dst_reg, src1));
+ }
+
+ tmp = (sljit_uw)src1w;
+
+ if (tmp < 0x10000) {
+ /* set low 16 bits, set hi 16 bits to 0. */
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ return push_inst32(compiler, MOVW | RD4(dst_reg)
+ | COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff));
+ }
+
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | ((cc & 0x1) << 3) | 0x4));
+
+ tmp = (sljit_uw)src1w;
+ FAIL_IF(push_inst32(compiler, MOVW | RD4(dst_reg)
+ | COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff)));
+ return push_inst32(compiler, MOVT | RD4(dst_reg)
+ | COPY_BITS(tmp, 12 + 16, 16, 4) | COPY_BITS(tmp, 11 + 16, 26, 1) | COPY_BITS(tmp, 8 + 16, 12, 3) | ((tmp & 0xff0000) >> 16));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_freg)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ type ^= SLJIT_32;
+
+ if (dst_freg != src2_freg) {
+ if (dst_freg == src1) {
+ src1 = src2_freg;
+ src1w = 0;
+ type ^= 0x1;
+ } else
+ FAIL_IF(push_inst32(compiler, VMOV_F32 | (type & SLJIT_32) | VD4(dst_freg) | VM4(src2_freg)));
+ }
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, (type & SLJIT_32) | FPU_LOAD, TMP_FREG2, src1, src1w));
+ src1 = TMP_FREG2;
+ }
+
+ FAIL_IF(push_inst16(compiler, IT | (get_cc(compiler, type & ~SLJIT_32) << 4) | 0x8));
+ return push_inst32(compiler, VMOV_F32 | (type & SLJIT_32) | VD4(dst_freg) | VM4(src1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_s32 flags;
+ sljit_uw imm, tmp;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
+
+ if (!(reg & REG_PAIR_MASK))
+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
+
+ if (type & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32)) {
+ if ((mem & REG_MASK) == 0) {
+ if ((memw & 0xfff) >= (0x1000 - SSIZE_OF(sw))) {
+ imm = get_imm((sljit_uw)((memw + 0x1000) & ~0xfff));
+
+ if (imm != INVALID_IMM)
+ memw = (memw & 0xfff) - 0x1000;
+ } else {
+ imm = get_imm((sljit_uw)(memw & ~0xfff));
+
+ if (imm != INVALID_IMM)
+ memw &= 0xfff;
+ }
+
+ if (imm == INVALID_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));
+ memw = 0;
+ } else
+ FAIL_IF(push_inst32(compiler, MOV_WI | RD4(TMP_REG1) | imm));
+
+ mem = SLJIT_MEM1(TMP_REG1);
+ } else if (mem & OFFS_REG_MASK) {
+ FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(mem & REG_MASK) | RM4(OFFS_REG(mem)) | ((sljit_uw)(memw & 0x3) << 6)));
+ memw = 0;
+ mem = SLJIT_MEM1(TMP_REG1);
+ } else if (memw < -0xff) {
+ /* Zero value can be included in the first case. */
+ if ((-memw & 0xfff) <= SSIZE_OF(sw))
+ tmp = (sljit_uw)((-memw + 0x7ff) & ~0x7ff);
+ else
+ tmp = (sljit_uw)((-memw + 0xfff) & ~0xfff);
+
+ SLJIT_ASSERT(tmp >= (sljit_uw)-memw);
+ imm = get_imm(tmp);
+
+ if (imm != INVALID_IMM) {
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(mem & REG_MASK) | imm));
+ memw += (sljit_sw)tmp;
+ SLJIT_ASSERT(memw >= 0 && memw <= 0xfff - SSIZE_OF(sw));
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));
+ FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem & REG_MASK)));
+ memw = 0;
+ }
+
+ mem = SLJIT_MEM1(TMP_REG1);
+ } else if (memw >= (0x1000 - SSIZE_OF(sw))) {
+ if ((memw & 0xfff) >= (0x1000 - SSIZE_OF(sw))) {
+ imm = get_imm((sljit_uw)((memw + 0x1000) & ~0xfff));
+
+ if (imm != INVALID_IMM)
+ memw = (memw & 0xfff) - 0x1000;
+ } else {
+ imm = get_imm((sljit_uw)(memw & ~0xfff));
+
+ if (imm != INVALID_IMM)
+ memw &= 0xfff;
+ }
+
+ if (imm != INVALID_IMM) {
+ SLJIT_ASSERT(memw >= -0xff && memw <= 0xfff);
+ FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(mem & REG_MASK) | imm));
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));
+ FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem & REG_MASK)));
+ memw = 0;
+ }
+
+ mem = SLJIT_MEM1(TMP_REG1);
+ }
+
+ flags = WORD_SIZE;
+
+ SLJIT_ASSERT(memw <= 0xfff - SSIZE_OF(sw) && memw >= -0xff);
+
+ if (type & SLJIT_MEM_STORE) {
+ flags |= STORE;
+ } else if (REG_PAIR_FIRST(reg) == (mem & REG_MASK)) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, REG_PAIR_SECOND(reg), mem, memw + SSIZE_OF(sw), TMP_REG2));
+ return emit_op_mem(compiler, WORD_SIZE, REG_PAIR_FIRST(reg), mem, memw, TMP_REG2);
+ }
+
+ FAIL_IF(emit_op_mem(compiler, flags, REG_PAIR_FIRST(reg), mem, memw, TMP_REG2));
+ return emit_op_mem(compiler, flags, REG_PAIR_SECOND(reg), mem, memw + SSIZE_OF(sw), TMP_REG2);
+ }
+
+ flags = 1 << 23;
+
+ if ((mem & REG_MASK) == 0) {
+ tmp = (sljit_uw)(memw & 0x7fc);
+ imm = get_imm((sljit_uw)((memw + (tmp <= 0x400 ? 0 : 0x400)) & ~0x3fc));
+
+ if (imm == INVALID_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));
+ memw = 0;
+ } else {
+ FAIL_IF(push_inst32(compiler, MOV_WI | RD4(TMP_REG1) | imm));
+ memw = (memw & 0x3fc) >> 2;
+
+ if (tmp > 0x400) {
+ memw = 0x100 - memw;
+ flags = 0;
+ }
+
+ SLJIT_ASSERT(memw >= 0 && memw <= 0xff);
+ }
+
+ mem = SLJIT_MEM1(TMP_REG1);
+ } else if (mem & OFFS_REG_MASK) {
+ FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(mem & REG_MASK) | RM4(OFFS_REG(mem)) | ((sljit_uw)(memw & 0x3) << 6)));
+ memw = 0;
+ mem = SLJIT_MEM1(TMP_REG1);
+ } else if (memw < 0) {
+ if ((-memw & ~0x3fc) == 0) {
+ flags = 0;
+ memw = -memw >> 2;
+ } else {
+ tmp = (sljit_uw)(-memw & 0x7fc);
+ imm = get_imm((sljit_uw)((-memw + (tmp <= 0x400 ? 0 : 0x400)) & ~0x3fc));
+
+ if (imm != INVALID_IMM) {
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(mem & REG_MASK) | imm));
+ memw = (-memw & 0x3fc) >> 2;
+
+ if (tmp <= 0x400)
+ flags = 0;
+ else
+ memw = 0x100 - memw;
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));
+ FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem & REG_MASK)));
+ memw = 0;
+ }
+
+ mem = SLJIT_MEM1(TMP_REG1);
+ }
+ } else if ((memw & ~0x3fc) != 0) {
+ tmp = (sljit_uw)(memw & 0x7fc);
+ imm = get_imm((sljit_uw)((memw + (tmp <= 0x400 ? 0 : 0x400)) & ~0x3fc));
+
+ if (imm != INVALID_IMM) {
+ FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(mem & REG_MASK) | imm));
+ memw = (memw & 0x3fc) >> 2;
+
+ if (tmp > 0x400) {
+ memw = 0x100 - memw;
+ flags = 0;
+ }
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));
+ FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem & REG_MASK)));
+ memw = 0;
+ }
+
+ mem = SLJIT_MEM1(TMP_REG1);
+ } else
+ memw >>= 2;
+
+ SLJIT_ASSERT(memw >= 0 && memw <= 0xff);
+ return push_inst32(compiler, ((type & SLJIT_MEM_STORE) ? STRD : LDRD) | (sljit_ins)flags | RN4(mem & REG_MASK) | RT4(REG_PAIR_FIRST(reg)) | RD4(REG_PAIR_SECOND(reg)) | (sljit_ins)memw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_s32 flags;
+ sljit_ins inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));
+
+ if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -255))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_MEM_SUPP)
+ return SLJIT_SUCCESS;
+
+ switch (type & 0xff) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ case SLJIT_MOV_P:
+ flags = WORD_SIZE;
+ break;
+ case SLJIT_MOV_U8:
+ flags = BYTE_SIZE;
+ break;
+ case SLJIT_MOV_S8:
+ flags = BYTE_SIZE | SIGNED;
+ break;
+ case SLJIT_MOV_U16:
+ flags = HALF_SIZE;
+ break;
+ case SLJIT_MOV_S16:
+ flags = HALF_SIZE | SIGNED;
+ break;
+ default:
+ SLJIT_UNREACHABLE();
+ flags = WORD_SIZE;
+ break;
+ }
+
+ if (type & SLJIT_MEM_STORE)
+ flags |= STORE;
+
+ inst = sljit_mem32[flags] | 0x900;
+
+ if (!(type & SLJIT_MEM_POST))
+ inst |= 0x400;
+
+ if (memw >= 0)
+ inst |= 0x200;
+ else
+ memw = -memw;
+
+ return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | (sljit_ins)memw);
+}
+
+static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s32 max_offset)
+{
+ sljit_s32 arg = *mem;
+ sljit_sw argw = *memw;
+ sljit_uw imm;
+
+ *mem = TMP_REG1;
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ *memw = 0;
+ return push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((sljit_uw)(argw & 0x3) << 6));
+ }
+
+ arg &= REG_MASK;
+
+ if (arg) {
+ if (argw <= max_offset && argw >= -0xff) {
+ *mem = arg;
+ return SLJIT_SUCCESS;
+ }
+
+ if (argw < 0) {
+ imm = get_imm((sljit_uw)(-argw & ~0xff));
+
+ if (imm) {
+ *memw = -(-argw & 0xff);
+ return push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg) | imm);
+ }
+ } else if ((argw & 0xfff) <= max_offset) {
+ imm = get_imm((sljit_uw)(argw & ~0xfff));
+
+ if (imm) {
+ *memw = argw & 0xfff;
+ return push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg) | imm);
+ }
+ } else {
+ imm = get_imm((sljit_uw)((argw | 0xfff) + 1));
+
+ if (imm) {
+ *memw = (argw & 0xfff) - 0x1000;
+ return push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg) | imm);
+ }
+ }
+ }
+
+ imm = (sljit_uw)(argw & ~0xfff);
+
+ if ((argw & 0xfff) > max_offset) {
+ imm += 0x1000;
+ *memw = (argw & 0xfff) - 0x1000;
+ } else
+ *memw = argw & 0xfff;
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, imm));
+
+ if (arg == 0)
+ return SLJIT_SUCCESS;
+
+ return push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, arg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 freg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
+
+ if (type & SLJIT_MEM_ALIGNED_32)
+ return emit_fop_mem(compiler, ((type ^ SLJIT_32) & SLJIT_32) | ((type & SLJIT_MEM_STORE) ? 0 : FPU_LOAD), freg, mem, memw);
+
+ if (type & SLJIT_MEM_STORE) {
+ FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | VN4(freg) | RT4(TMP_REG2)));
+
+ if (type & SLJIT_32)
+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw, TMP_REG1);
+
+ FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
+ mem |= SLJIT_MEM;
+
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw, TMP_REG1));
+ FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | VN4(freg) | 0x80 | RT4(TMP_REG2)));
+ return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, mem, memw + 4, TMP_REG1);
+ }
+
+ if (type & SLJIT_32) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1));
+ return push_inst32(compiler, VMOV | VN4(freg) | RT4(TMP_REG2));
+ }
+
+ FAIL_IF(update_mem_addr(compiler, &mem, &memw, 0xfff - 4));
+ mem |= SLJIT_MEM;
+
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, mem, memw, TMP_REG1));
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, mem, memw + 4, TMP_REG1));
+ return push_inst32(compiler, VMOV2 | VM4(freg) | RT4(TMP_REG2) | RN4(TMP_REG1));
+}
+
+static sljit_s32 sljit_emit_simd_mem_offset(struct sljit_compiler *compiler, sljit_s32 *mem_ptr, sljit_sw memw)
+{
+ sljit_uw imm;
+ sljit_s32 mem = *mem_ptr;
+
+ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
+ *mem_ptr = TMP_REG1;
+ return push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(mem & REG_MASK) | RM4(OFFS_REG(mem)) | ((sljit_uw)(memw & 0x3) << 6));
+ }
+
+ if (SLJIT_UNLIKELY(!(mem & REG_MASK))) {
+ *mem_ptr = TMP_REG1;
+ return load_immediate(compiler, TMP_REG1, (sljit_uw)memw);
+ }
+
+ mem &= REG_MASK;
+
+ if (memw == 0) {
+ *mem_ptr = mem;
+ return SLJIT_SUCCESS;
+ }
+
+ *mem_ptr = TMP_REG1;
+ imm = get_imm((sljit_uw)(memw < 0 ? -memw : memw));
+
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, ((memw < 0) ? SUB_WI : ADD_WI) | RD4(TMP_REG1) | RN4(mem) | imm);
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)memw));
+ return push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, mem));
+}
+
+static SLJIT_INLINE sljit_s32 simd_get_quad_reg_index(sljit_s32 freg)
+{
+ freg += freg & 0x1;
+
+ SLJIT_ASSERT((freg_map[freg] & 0x1) == (freg <= SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS));
+
+ if (freg <= SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS)
+ freg--;
+
+ return freg;
+}
+
+#define SLJIT_QUAD_OTHER_HALF(freg) ((((freg) & 0x1) << 1) - 1)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw));
+
+ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (reg_size == 4)
+ vreg = simd_get_quad_reg_index(vreg);
+
+ if (!(srcdst & SLJIT_MEM)) {
+ if (reg_size == 4)
+ srcdst = simd_get_quad_reg_index(srcdst);
+
+ if (type & SLJIT_SIMD_STORE)
+ ins = VD4(srcdst) | VN4(vreg) | VM4(vreg);
+ else
+ ins = VD4(vreg) | VN4(srcdst) | VM4(srcdst);
+
+ if (reg_size == 4)
+ ins |= (sljit_ins)1 << 6;
+
+ return push_inst32(compiler, VORR | ins);
+ }
+
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));
+
+ if (elem_size > 3)
+ elem_size = 3;
+
+ ins = ((type & SLJIT_SIMD_STORE) ? VST1 : VLD1) | VD4(vreg)
+ | (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8));
+
+ SLJIT_ASSERT(reg_size >= alignment);
+
+ if (alignment == 3)
+ ins |= 0x10;
+ else if (alignment >= 4)
+ ins |= 0x20;
+
+ return push_inst32(compiler, ins | RN4(srcdst) | ((sljit_ins)elem_size) << 6 | 0xf);
+}
+
+static sljit_ins simd_get_imm(sljit_s32 elem_size, sljit_uw value)
+{
+ sljit_ins result;
+
+ if (elem_size > 1 && (sljit_u16)value == (value >> 16)) {
+ elem_size = 1;
+ value = (sljit_u16)value;
+ }
+
+ if (elem_size == 1 && (sljit_u8)value == (value >> 8)) {
+ elem_size = 0;
+ value = (sljit_u8)value;
+ }
+
+ switch (elem_size) {
+ case 0:
+ SLJIT_ASSERT(value <= 0xff);
+ result = 0xe00;
+ break;
+ case 1:
+ SLJIT_ASSERT(value <= 0xffff);
+ result = 0;
+
+ while (1) {
+ if (value <= 0xff) {
+ result |= 0x800;
+ break;
+ }
+
+ if ((value & 0xff) == 0) {
+ value >>= 8;
+ result |= 0xa00;
+ break;
+ }
+
+ if (result != 0)
+ return ~(sljit_ins)0;
+
+ value ^= (sljit_uw)0xffff;
+ result = (1 << 5);
+ }
+ break;
+ default:
+ SLJIT_ASSERT(value <= 0xffffffff);
+ result = 0;
+
+ while (1) {
+ if (value <= 0xff) {
+ result |= 0x000;
+ break;
+ }
+
+ if ((value & ~(sljit_uw)0xff00) == 0) {
+ value >>= 8;
+ result |= 0x200;
+ break;
+ }
+
+ if ((value & ~(sljit_uw)0xff0000) == 0) {
+ value >>= 16;
+ result |= 0x400;
+ break;
+ }
+
+ if ((value & ~(sljit_uw)0xff000000) == 0) {
+ value >>= 24;
+ result |= 0x600;
+ break;
+ }
+
+ if ((value & (sljit_uw)0xff) == 0xff && (value >> 16) == 0) {
+ value >>= 8;
+ result |= 0xc00;
+ break;
+ }
+
+ if ((value & (sljit_uw)0xffff) == 0xffff && (value >> 24) == 0) {
+ value >>= 16;
+ result |= 0xd00;
+ break;
+ }
+
+ if (result != 0)
+ return ~(sljit_ins)0;
+
+ value = ~value;
+ result = (1 << 5);
+ }
+ break;
+ }
+
+ return ((sljit_ins)value & 0xf) | (((sljit_ins)value & 0x70) << 12) | (((sljit_ins)value & 0x80) << 21) | result;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins, imm;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw));
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (reg_size == 4)
+ vreg = simd_get_quad_reg_index(vreg);
+
+ if (src == SLJIT_IMM && srcw == 0)
+ return push_inst32(compiler, VMOV_i | ((reg_size == 4) ? (1 << 6) : 0) | VD4(vreg));
+
+ if (SLJIT_UNLIKELY(elem_size == 3)) {
+ SLJIT_ASSERT(type & SLJIT_SIMD_FLOAT);
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_fop_mem(compiler, FPU_LOAD | SLJIT_32, vreg, src, srcw));
+ src = vreg;
+ } else if (vreg != src)
+ FAIL_IF(push_inst32(compiler, VORR | VD4(vreg) | VN4(src) | VM4(src)));
+
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+
+ if (vreg != src)
+ return push_inst32(compiler, VORR | VD4(vreg) | VN4(src) | VM4(src));
+ return SLJIT_SUCCESS;
+ }
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));
+
+ ins = (sljit_ins)(elem_size << 6);
+
+ if (reg_size == 4)
+ ins |= 1 << 5;
+
+ return push_inst32(compiler, VLD1_r | ins | VD4(vreg) | RN4(src) | 0xf);
+ }
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ SLJIT_ASSERT(elem_size == 2);
+ ins = ((sljit_ins)freg_ebit_map[src] << (16 + 2 + 1)) | ((sljit_ins)1 << (16 + 2));
+
+ if (reg_size == 4)
+ ins |= (sljit_ins)1 << 6;
+
+ return push_inst32(compiler, VDUP_s | ins | VD4(vreg) | (sljit_ins)freg_map[src]);
+ }
+
+ if (src == SLJIT_IMM) {
+ if (elem_size < 2)
+ srcw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1;
+
+ imm = simd_get_imm(elem_size, (sljit_uw)srcw);
+
+ if (imm != ~(sljit_ins)0) {
+ if (reg_size == 4)
+ imm |= (sljit_ins)1 << 6;
+
+ return push_inst32(compiler, VMOV_i | imm | VD4(vreg));
+ }
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));
+ src = TMP_REG1;
+ }
+
+ switch (elem_size) {
+ case 0:
+ ins = 1 << 22;
+ break;
+ case 1:
+ ins = 1 << 5;
+ break;
+ default:
+ ins = 0;
+ break;
+ }
+
+ if (reg_size == 4)
+ ins |= (sljit_ins)1 << 21;
+
+ return push_inst32(compiler, VDUP | ins | VN4(vreg) | RT4(src));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg, sljit_s32 lane_index,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw));
+
+ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (reg_size == 4)
+ vreg = simd_get_quad_reg_index(vreg);
+
+ if (type & SLJIT_SIMD_LANE_ZERO) {
+ ins = (reg_size == 3) ? 0 : ((sljit_ins)1 << 6);
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (elem_size == 3 && !(srcdst & SLJIT_MEM)) {
+ if (lane_index == 1)
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+
+ if (srcdst != vreg)
+ FAIL_IF(push_inst32(compiler, VORR | VD4(vreg) | VN4(srcdst) | VM4(srcdst)));
+
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+ return push_inst32(compiler, VMOV_i | VD4(vreg));
+ }
+
+ if (srcdst == vreg || (elem_size == 3 && srcdst == (vreg + SLJIT_QUAD_OTHER_HALF(vreg)))) {
+ FAIL_IF(push_inst32(compiler, VORR | ins | VD4(TMP_FREG2) | VN4(vreg) | VM4(vreg)));
+ srcdst = TMP_FREG2;
+ srcdstw = 0;
+ }
+ }
+
+ FAIL_IF(push_inst32(compiler, VMOV_i | ins | VD4(vreg)));
+ }
+
+ if (reg_size == 4 && lane_index >= (0x8 >> elem_size)) {
+ lane_index -= (0x8 >> elem_size);
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+ }
+
+ if (srcdst & SLJIT_MEM) {
+ if (elem_size == 3)
+ return emit_fop_mem(compiler, ((type & SLJIT_SIMD_STORE) ? 0 : FPU_LOAD) | SLJIT_32, vreg, srcdst, srcdstw);
+
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));
+
+ lane_index = lane_index << elem_size;
+ ins = (sljit_ins)((elem_size << 10) | (lane_index << 5));
+ return push_inst32(compiler, ((type & SLJIT_SIMD_STORE) ? VST1_s : VLD1_s) | ins | VD4(vreg) | RN4(srcdst) | 0xf);
+ }
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (elem_size == 3) {
+ if (type & SLJIT_SIMD_STORE)
+ return push_inst32(compiler, VORR | VD4(srcdst) | VN4(vreg) | VM4(vreg));
+ return push_inst32(compiler, VMOV_F32 | SLJIT_32 | VD4(vreg) | VM4(srcdst));
+ }
+
+ if (type & SLJIT_SIMD_STORE) {
+ if (freg_ebit_map[vreg] == 0) {
+ if (lane_index == 1)
+ vreg = SLJIT_F64_SECOND(vreg);
+
+ return push_inst32(compiler, VMOV_F32 | VD4(srcdst) | VM4(vreg));
+ }
+
+ FAIL_IF(push_inst32(compiler, VMOV_s | (1 << 20) | ((sljit_ins)lane_index << 21) | VN4(vreg) | RT4(TMP_REG1)));
+ return push_inst32(compiler, VMOV | VN4(srcdst) | RT4(TMP_REG1));
+ }
+
+ FAIL_IF(push_inst32(compiler, VMOV | (1 << 20) | VN4(srcdst) | RT4(TMP_REG1)));
+ return push_inst32(compiler, VMOV_s | ((sljit_ins)lane_index << 21) | VN4(vreg) | RT4(TMP_REG1));
+ }
+
+ if (srcdst == SLJIT_IMM) {
+ if (elem_size < 2)
+ srcdstw &= ((sljit_sw)1 << (((sljit_sw)1 << elem_size) << 3)) - 1;
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcdstw));
+ srcdst = TMP_REG1;
+ }
+
+ if (elem_size == 0)
+ ins = 0x400000;
+ else if (elem_size == 1)
+ ins = 0x20;
+ else
+ ins = 0;
+
+ lane_index = lane_index << elem_size;
+ ins |= (sljit_ins)(((lane_index & 0x4) << 19) | ((lane_index & 0x3) << 5));
+
+ if (type & SLJIT_SIMD_STORE) {
+ ins |= (1 << 20);
+
+ if (elem_size < 2 && !(type & SLJIT_SIMD_LANE_SIGNED))
+ ins |= (1 << 23);
+ }
+
+ return push_inst32(compiler, VMOV_s | ins | VN4(vreg) | RT4(srcdst));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_s32 src_lane_index)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index));
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (reg_size == 4) {
+ vreg = simd_get_quad_reg_index(vreg);
+ src = simd_get_quad_reg_index(src);
+
+ if (src_lane_index >= (0x8 >> elem_size)) {
+ src_lane_index -= (0x8 >> elem_size);
+ src += SLJIT_QUAD_OTHER_HALF(src);
+ }
+ }
+
+ if (elem_size == 3) {
+ if (vreg != src)
+ FAIL_IF(push_inst32(compiler, VORR | VD4(vreg) | VN4(src) | VM4(src)));
+
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+
+ if (vreg != src)
+ return push_inst32(compiler, VORR | VD4(vreg) | VN4(src) | VM4(src));
+ return SLJIT_SUCCESS;
+ }
+
+ ins = ((((sljit_ins)src_lane_index << 1) | 1) << (16 + elem_size));
+
+ if (reg_size == 4)
+ ins |= (sljit_ins)1 << 6;
+
+ return push_inst32(compiler, VDUP_s | ins | VD4(vreg) | VM4(src));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);
+ sljit_s32 dst_reg;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw));
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size != 2 || elem2_size != 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (reg_size == 4)
+ vreg = simd_get_quad_reg_index(vreg);
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));
+ if (reg_size == 4 && elem2_size - elem_size == 1)
+ FAIL_IF(push_inst32(compiler, VLD1 | (0x7 << 8) | VD4(vreg) | RN4(src) | 0xf));
+ else
+ FAIL_IF(push_inst32(compiler, VLD1_s | (sljit_ins)((reg_size - elem2_size + elem_size) << 10) | VD4(vreg) | RN4(src) | 0xf));
+ src = vreg;
+ } else if (reg_size == 4)
+ src = simd_get_quad_reg_index(src);
+
+ if (!(type & SLJIT_SIMD_FLOAT)) {
+ dst_reg = (reg_size == 4) ? vreg : TMP_FREG2;
+
+ do {
+ FAIL_IF(push_inst32(compiler, VSHLL | ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0 : (1 << 28))
+ | ((sljit_ins)1 << (19 + elem_size)) | VD4(dst_reg) | VM4(src)));
+ src = dst_reg;
+ } while (++elem_size < elem2_size);
+
+ if (dst_reg == TMP_FREG2)
+ return push_inst32(compiler, VORR | VD4(vreg) | VN4(TMP_FREG2) | VM4(TMP_FREG2));
+ return SLJIT_SUCCESS;
+ }
+
+ /* No SIMD variant, must use VFP instead. */
+ SLJIT_ASSERT(reg_size == 4);
+
+ if (vreg == src) {
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+ FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | VD4(vreg) | VM4(src) | 0x20));
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+ return push_inst32(compiler, VCVT_F64_F32 | VD4(vreg) | VM4(src));
+ }
+
+ FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | VD4(vreg) | VM4(src)));
+ vreg += SLJIT_QUAD_OTHER_HALF(vreg);
+ return push_inst32(compiler, VCVT_F64_F32 | VD4(vreg) | VM4(src) | 0x20);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins, imms;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw));
+
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ switch (elem_size) {
+ case 0:
+ imms = 0x243219;
+ ins = VSHR | (1 << 28) | (0x9 << 16);
+ break;
+ case 1:
+ imms = (reg_size == 4) ? 0x243219 : 0x2231;
+ ins = VSHR | (1 << 28) | (0x11 << 16);
+ break;
+ case 2:
+ imms = (reg_size == 4) ? 0x2231 : 0x21;
+ ins = VSHR | (1 << 28) | (0x21 << 16);
+ break;
+ default:
+ imms = 0x21;
+ ins = VSHR | (1 << 28) | (0x1 << 16) | (1 << 7);
+ break;
+ }
+
+ if (reg_size == 4) {
+ vreg = simd_get_quad_reg_index(vreg);
+ ins |= (sljit_ins)1 << 6;
+ }
+
+ SLJIT_ASSERT((freg_map[TMP_FREG2] & 0x1) == 0);
+ FAIL_IF(push_inst32(compiler, ins | VD4(TMP_FREG2) | VM4(vreg)));
+
+ if (reg_size == 4 && elem_size > 0)
+ FAIL_IF(push_inst32(compiler, VMOVN | ((sljit_ins)(elem_size - 1) << 18) | VD4(TMP_FREG2) | VM4(TMP_FREG2)));
+
+ ins = (reg_size == 4 && elem_size == 0) ? (1 << 6) : 0;
+
+ while (imms >= 0x100) {
+ FAIL_IF(push_inst32(compiler, VSRA | (1 << 28) | ins | ((imms & 0xff) << 16) | VD4(TMP_FREG2) | VM4(TMP_FREG2)));
+ imms >>= 8;
+ }
+
+ FAIL_IF(push_inst32(compiler, VSRA | (1 << 28) | ins | (1 << 7) | (imms << 16) | VD4(TMP_FREG2) | VM4(TMP_FREG2)));
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ FAIL_IF(push_inst32(compiler, VMOV_s | (1 << 20) | (1 << 23) | (0x2 << 21) | RT4(dst_r) | VN4(TMP_FREG2)));
+
+ if (reg_size == 4 && elem_size == 0) {
+ SLJIT_ASSERT(freg_map[TMP_FREG2] + 1 == freg_map[TMP_FREG1]);
+ FAIL_IF(push_inst32(compiler, VMOV_s | (1 << 20) | (1 << 23) | (0x2 << 21) | RT4(TMP_REG2)| VN4(TMP_FREG1)));
+ FAIL_IF(push_inst32(compiler, ORR_W | RD4(dst_r) | RN4(dst_r) | RM4(TMP_REG2) | (0x2 << 12)));
+ }
+
+ if (dst_r == TMP_REG1)
+ return emit_op_mem(compiler, STORE | WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 alignment;
+ sljit_ins ins = 0, load_ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ if (reg_size != 3 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ switch (SLJIT_SIMD_GET_OPCODE(type)) {
+ case SLJIT_SIMD_OP2_AND:
+ ins = VAND;
+ break;
+ case SLJIT_SIMD_OP2_OR:
+ ins = VORR;
+ break;
+ case SLJIT_SIMD_OP2_XOR:
+ ins = VEOR;
+ break;
+ case SLJIT_SIMD_OP2_SHUFFLE:
+ ins = VTBL;
+ break;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ if (elem_size > 3)
+ elem_size = 3;
+
+ load_ins = VLD1 | (sljit_ins)((reg_size == 3) ? (0x7 << 8) : (0xa << 8));
+ alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);
+
+ SLJIT_ASSERT(reg_size >= alignment);
+
+ if (alignment == 3)
+ load_ins |= 0x10;
+ else if (alignment >= 4)
+ load_ins |= 0x20;
+
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src2, src2w));
+ FAIL_IF(push_inst32(compiler, load_ins | VD4(TMP_FREG2) | RN4(src2) | ((sljit_ins)elem_size) << 6 | 0xf));
+ src2 = TMP_FREG2;
+ }
+
+ if (reg_size == 4) {
+ dst_vreg = simd_get_quad_reg_index(dst_vreg);
+ src1_vreg = simd_get_quad_reg_index(src1_vreg);
+ src2 = simd_get_quad_reg_index(src2);
+
+ if (SLJIT_SIMD_GET_OPCODE(type) == SLJIT_SIMD_OP2_SHUFFLE) {
+ ins |= (sljit_ins)1 << 8;
+
+ FAIL_IF(push_inst32(compiler, ins | VD4(dst_vreg != src1_vreg ? dst_vreg : TMP_FREG2) | VN4(src1_vreg) | VM4(src2)));
+ src2 += SLJIT_QUAD_OTHER_HALF(src2);
+ FAIL_IF(push_inst32(compiler, ins | VD4(dst_vreg + SLJIT_QUAD_OTHER_HALF(dst_vreg)) | VN4(src1_vreg) | VM4(src2)));
+
+ if (dst_vreg == src1_vreg)
+ return push_inst32(compiler, VORR | VD4(dst_vreg) | VN4(TMP_FREG2) | VM4(TMP_FREG2));
+ return SLJIT_SUCCESS;
+ }
+
+ ins |= (sljit_ins)1 << 6;
+ }
+
+ return push_inst32(compiler, ins | VD4(dst_vreg) | VN4(src1_vreg) | VM4(src2));
+}
+
+#undef FPU_LOAD
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 mem_reg)
+{
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));
+
+ if (op & SLJIT_ATOMIC_USE_CAS)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_S8:
+ case SLJIT_MOV_S16:
+ case SLJIT_MOV_S32:
+ return SLJIT_ERR_UNSUPPORTED;
+
+ case SLJIT_MOV_U8:
+ ins = LDREXB;
+ break;
+ case SLJIT_MOV_U16:
+ ins = LDREXH;
+ break;
+ default:
+ ins = LDREX;
+ break;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ return push_inst32(compiler, ins | RN4(mem_reg) | RT4(dst_reg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src_reg,
+ sljit_s32 mem_reg,
+ sljit_s32 temp_reg)
+{
+ sljit_ins ins;
+
+ /* temp_reg == mem_reg is undefined so use another temp register */
+ SLJIT_UNUSED_ARG(temp_reg);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));
+
+ if (op & SLJIT_ATOMIC_USE_CAS)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_S8:
+ case SLJIT_MOV_S16:
+ case SLJIT_MOV_S32:
+ return SLJIT_ERR_UNSUPPORTED;
+
+ case SLJIT_MOV_U8:
+ ins = STREXB | RM4(TMP_REG1);
+ break;
+ case SLJIT_MOV_U16:
+ ins = STREXH | RM4(TMP_REG1);
+ break;
+ default:
+ ins = STREX | RD4(TMP_REG1);
+ break;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst32(compiler, ins | RN4(mem_reg) | RT4(src_reg)));
+ if (op & SLJIT_SET_ATOMIC_STORED)
+ return push_inst32(compiler, CMPI_W | RN4(TMP_REG1));
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
+{
+ struct sljit_const *const_;
+ sljit_s32 dst_r;
+ sljit_s32 mem_flags = WORD_SIZE | STORE;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+ PTR_FAIL_IF(!const_);
+ set_const(const_, compiler);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (GET_OPCODE(op) == SLJIT_MOV_U8) {
+ PTR_FAIL_IF(push_inst32(compiler,
+ ((init_value & 0x100) != 0 ? (MVN_WI | (~init_value & 0xff)) : (MOV_WI | (init_value & 0xff))) | RD4(dst_r)));
+ mem_flags = BYTE_SIZE | STORE;
+ } else
+ PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, (sljit_uw)init_value));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, dst, dstw, TMP_REG2));
+ return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_jump *jump;
+ sljit_s32 dst_r, target_r;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = TMP_REG1;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, dst_r, dst, dstw, TMP_REG1));
+ }
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_mov_addr(jump, compiler, 0);
+
+ if (op != SLJIT_MOV_ADDR)
+ jump->flags |= IS_ABS;
+
+ PTR_FAIL_IF(push_inst16(compiler, RDN3(target_r)));
+ compiler->size += 3;
+
+ if (op == SLJIT_ADD_ABS_ADDR)
+ PTR_FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(dst_r, TMP_REG1)));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG1));
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
+{
+ sljit_u16 *inst = (sljit_u16*)addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);
+ modify_imm32_const(inst, new_target);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);
+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 4);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
+{
+ sljit_u16 *inst;
+
+ if (GET_OPCODE(op) != SLJIT_MOV_U8) {
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ return;
+ }
+
+ inst = (sljit_u16*)addr;
+ SLJIT_ASSERT(inst[0] == (MOV_WI >> 16) || inst[0] == (MVN_WI >> 16));
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+
+ if ((new_constant & 0x100) != 0) {
+ inst[0] = (sljit_u16)(MVN_WI >> 16);
+ new_constant = ~new_constant;
+ } else
+ inst[0] = (sljit_u16)(MOV_WI >> 16);
+
+ inst[1] = (sljit_u16)((new_constant & 0xff) | (inst[1] & 0xf00));
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst + 1, inst + 2);
+}
diff --git a/deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c b/deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c
new file mode 100644
index 0000000..83e6e29
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c
@@ -0,0 +1,4123 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
+{
+ return "LOONGARCH" SLJIT_CPUINFO;
+}
+
+typedef sljit_u32 sljit_ins;
+
+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
+#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
+#define TMP_ZERO 0
+
+/* Flags are kept in volatile registers. */
+#define EQUAL_FLAG (SLJIT_NUMBER_OF_REGISTERS + 5)
+#define RETURN_ADDR_REG TMP_REG2
+#define OTHER_FLAG (SLJIT_NUMBER_OF_REGISTERS + 6)
+
+#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
+
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
+ 0, 4, 5, 6, 7, 8, 9, 10, 11, 16, 17, 18, 19, 20, 22, 31, 30, 29, 28, 27, 26, 25, 24, 23, 3, 13, 1, 14, 12, 15
+};
+
+static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 31, 30, 29, 28, 27, 26, 25, 24, 8, 9
+};
+
+/* --------------------------------------------------------------------- */
+/* Instruction forms */
+/* --------------------------------------------------------------------- */
+
+/*
+LoongArch instructions are 32 bits wide, belonging to 9 basic instruction formats (and variants of them):
+
+| Format name | Composition |
+| 2R | Opcode + Rj + Rd |
+| 3R | Opcode + Rk + Rj + Rd |
+| 4R | Opcode + Ra + Rk + Rj + Rd |
+| 2RI8 | Opcode + I8 + Rj + Rd |
+| 2RI12 | Opcode + I12 + Rj + Rd |
+| 2RI14 | Opcode + I14 + Rj + Rd |
+| 2RI16 | Opcode + I16 + Rj + Rd |
+| 1RI21 | Opcode + I21L + Rj + I21H |
+| I26 | Opcode + I26L + I26H |
+
+Rd is the destination register operand, while Rj, Rk and Ra ("a" stands for "additional") are the source register operands.
+I8/I12/I14/I16/I21/I26 are immediate operands of respective width. The longer I21 and I26 are stored in separate higher and
+lower parts in the instruction word, denoted by the "L" and "H" suffixes. */
+
+#define RD(rd) ((sljit_ins)reg_map[rd])
+#define RJ(rj) ((sljit_ins)reg_map[rj] << 5)
+#define RK(rk) ((sljit_ins)reg_map[rk] << 10)
+#define RA(ra) ((sljit_ins)reg_map[ra] << 15)
+
+#define FD(fd) ((sljit_ins)reg_map[fd])
+#define FRD(fd) ((sljit_ins)freg_map[fd])
+#define FRJ(fj) ((sljit_ins)freg_map[fj] << 5)
+#define FRK(fk) ((sljit_ins)freg_map[fk] << 10)
+#define FRA(fa) ((sljit_ins)freg_map[fa] << 15)
+
+#define IMM_V(imm) ((sljit_ins)(imm) << 10)
+#define IMM_I8(imm) (((sljit_ins)(imm)&0xff) << 10)
+#define IMM_I12(imm) (((sljit_ins)(imm)&0xfff) << 10)
+#define IMM_I14(imm) (((sljit_ins)(imm)&0xfff3) << 10)
+#define IMM_I16(imm) (((sljit_ins)(imm)&0xffff) << 10)
+#define IMM_I20(imm) (((sljit_ins)(imm)&0xffffffff) >> 12 << 5)
+#define IMM_I21(imm) ((((sljit_ins)(imm)&0xffff) << 10) | (((sljit_ins)(imm) >> 16) & 0x1f))
+#define IMM_I26(imm) ((((sljit_ins)(imm)&0xffff) << 10) | (((sljit_ins)(imm) >> 16) & 0x3ff))
+
+#define OPC_I26(opc) ((sljit_ins)(opc) << 26)
+#define OPC_1RI21(opc) ((sljit_ins)(opc) << 26)
+#define OPC_2RI16(opc) ((sljit_ins)(opc) << 26)
+#define OPC_2RI14(opc) ((sljit_ins)(opc) << 24)
+#define OPC_2RI12(opc) ((sljit_ins)(opc) << 22)
+#define OPC_2RI8(opc) ((sljit_ins)(opc) << 18)
+#define OPC_4R(opc) ((sljit_ins)(opc) << 20)
+#define OPC_3R(opc) ((sljit_ins)(opc) << 15)
+#define OPC_2R(opc) ((sljit_ins)(opc) << 10)
+#define OPC_1RI20(opc) ((sljit_ins)(opc) << 25)
+
+/* Arithmetic operation instructions */
+#define ADD_W OPC_3R(0x20)
+#define ADD_D OPC_3R(0x21)
+#define SUB_W OPC_3R(0x22)
+#define SUB_D OPC_3R(0x23)
+#define ADDI_W OPC_2RI12(0xa)
+#define ADDI_D OPC_2RI12(0xb)
+#define ANDI OPC_2RI12(0xd)
+#define ORI OPC_2RI12(0xe)
+#define XORI OPC_2RI12(0xf)
+#define ADDU16I_D OPC_2RI16(0x4)
+#define LU12I_W OPC_1RI20(0xa)
+#define LU32I_D OPC_1RI20(0xb)
+#define LU52I_D OPC_2RI12(0xc)
+#define SLT OPC_3R(0x24)
+#define SLTU OPC_3R(0x25)
+#define SLTI OPC_2RI12(0x8)
+#define SLTUI OPC_2RI12(0x9)
+#define PCADDI OPC_1RI20(0xc)
+#define PCALAU12I OPC_1RI20(0xd)
+#define PCADDU12I OPC_1RI20(0xe)
+#define PCADDU18I OPC_1RI20(0xf)
+#define NOR OPC_3R(0x28)
+#define AND OPC_3R(0x29)
+#define OR OPC_3R(0x2a)
+#define XOR OPC_3R(0x2b)
+#define ORN OPC_3R(0x2c)
+#define ANDN OPC_3R(0x2d)
+#define MUL_W OPC_3R(0x38)
+#define MULH_W OPC_3R(0x39)
+#define MULH_WU OPC_3R(0x3a)
+#define MUL_D OPC_3R(0x3b)
+#define MULH_D OPC_3R(0x3c)
+#define MULH_DU OPC_3R(0x3d)
+#define MULW_D_W OPC_3R(0x3e)
+#define MULW_D_WU OPC_3R(0x3f)
+#define DIV_W OPC_3R(0x40)
+#define MOD_W OPC_3R(0x41)
+#define DIV_WU OPC_3R(0x42)
+#define MOD_WU OPC_3R(0x43)
+#define DIV_D OPC_3R(0x44)
+#define MOD_D OPC_3R(0x45)
+#define DIV_DU OPC_3R(0x46)
+#define MOD_DU OPC_3R(0x47)
+
+/* Bit-shift instructions */
+#define SLL_W OPC_3R(0x2e)
+#define SRL_W OPC_3R(0x2f)
+#define SRA_W OPC_3R(0x30)
+#define SLL_D OPC_3R(0x31)
+#define SRL_D OPC_3R(0x32)
+#define SRA_D OPC_3R(0x33)
+#define ROTR_W OPC_3R(0x36)
+#define ROTR_D OPC_3R(0x37)
+#define SLLI_W OPC_3R(0x81)
+#define SLLI_D ((sljit_ins)(0x41) << 16)
+#define SRLI_W OPC_3R(0x89)
+#define SRLI_D ((sljit_ins)(0x45) << 16)
+#define SRAI_W OPC_3R(0x91)
+#define SRAI_D ((sljit_ins)(0x49) << 16)
+#define ROTRI_W OPC_3R(0x99)
+#define ROTRI_D ((sljit_ins)(0x4d) << 16)
+
+/* Bit-manipulation instructions */
+#define CLO_W OPC_2R(0x4)
+#define CLZ_W OPC_2R(0x5)
+#define CTO_W OPC_2R(0x6)
+#define CTZ_W OPC_2R(0x7)
+#define CLO_D OPC_2R(0x8)
+#define CLZ_D OPC_2R(0x9)
+#define CTO_D OPC_2R(0xa)
+#define CTZ_D OPC_2R(0xb)
+#define REVB_2H OPC_2R(0xc)
+#define REVB_4H OPC_2R(0xd)
+#define REVB_2W OPC_2R(0xe)
+#define REVB_D OPC_2R(0xf)
+#define REVH_2W OPC_2R(0x10)
+#define REVH_D OPC_2R(0x11)
+#define BITREV_4B OPC_2R(0x12)
+#define BITREV_8B OPC_2R(0x13)
+#define BITREV_W OPC_2R(0x14)
+#define BITREV_D OPC_2R(0x15)
+#define EXT_W_H OPC_2R(0x16)
+#define EXT_W_B OPC_2R(0x17)
+#define BSTRINS_W (0x1 << 22 | 1 << 21)
+#define BSTRPICK_W (0x1 << 22 | 1 << 21 | 1 << 15)
+#define BSTRINS_D (0x2 << 22)
+#define BSTRPICK_D (0x3 << 22)
+
+/* Branch instructions */
+#define BEQZ OPC_1RI21(0x10)
+#define BNEZ OPC_1RI21(0x11)
+#define JIRL OPC_2RI16(0x13)
+#define B OPC_I26(0x14)
+#define BL OPC_I26(0x15)
+#define BEQ OPC_2RI16(0x16)
+#define BNE OPC_2RI16(0x17)
+#define BLT OPC_2RI16(0x18)
+#define BGE OPC_2RI16(0x19)
+#define BLTU OPC_2RI16(0x1a)
+#define BGEU OPC_2RI16(0x1b)
+
+/* Memory access instructions */
+#define LD_B OPC_2RI12(0xa0)
+#define LD_H OPC_2RI12(0xa1)
+#define LD_W OPC_2RI12(0xa2)
+#define LD_D OPC_2RI12(0xa3)
+
+#define ST_B OPC_2RI12(0xa4)
+#define ST_H OPC_2RI12(0xa5)
+#define ST_W OPC_2RI12(0xa6)
+#define ST_D OPC_2RI12(0xa7)
+
+#define LD_BU OPC_2RI12(0xa8)
+#define LD_HU OPC_2RI12(0xa9)
+#define LD_WU OPC_2RI12(0xaa)
+
+#define LDX_B OPC_3R(0x7000)
+#define LDX_H OPC_3R(0x7008)
+#define LDX_W OPC_3R(0x7010)
+#define LDX_D OPC_3R(0x7018)
+
+#define STX_B OPC_3R(0x7020)
+#define STX_H OPC_3R(0x7028)
+#define STX_W OPC_3R(0x7030)
+#define STX_D OPC_3R(0x7038)
+
+#define LDX_BU OPC_3R(0x7040)
+#define LDX_HU OPC_3R(0x7048)
+#define LDX_WU OPC_3R(0x7050)
+
+#define PRELD OPC_2RI12(0xab)
+
+/* Atomic memory access instructions */
+#define LL_W OPC_2RI14(0x20)
+#define SC_W OPC_2RI14(0x21)
+#define LL_D OPC_2RI14(0x22)
+#define SC_D OPC_2RI14(0x23)
+
+/* LoongArch V1.10 Instructions */
+#define AMCAS_B OPC_3R(0x70B0)
+#define AMCAS_H OPC_3R(0x70B1)
+#define AMCAS_W OPC_3R(0x70B2)
+#define AMCAS_D OPC_3R(0x70B3)
+
+/* Memory barrier instructions */
+#define DBAR OPC_3R(0x70e4)
+
+/* Other instructions */
+#define BREAK OPC_3R(0x54)
+#define DBGCALL OPC_3R(0x55)
+#define NOP ANDI
+#define SYSCALL OPC_3R(0x56)
+
+/* Basic Floating-Point Instructions */
+/* Floating-Point Arithmetic Operation Instructions */
+#define FADD_S OPC_3R(0x201)
+#define FADD_D OPC_3R(0x202)
+#define FSUB_S OPC_3R(0x205)
+#define FSUB_D OPC_3R(0x206)
+#define FMUL_S OPC_3R(0x209)
+#define FMUL_D OPC_3R(0x20a)
+#define FDIV_S OPC_3R(0x20d)
+#define FDIV_D OPC_3R(0x20e)
+#define FCMP_COND_S OPC_4R(0xc1)
+#define FCMP_COND_D OPC_4R(0xc2)
+#define FCOPYSIGN_S OPC_3R(0x225)
+#define FCOPYSIGN_D OPC_3R(0x226)
+#define FSEL OPC_4R(0xd0)
+#define FABS_S OPC_2R(0x4501)
+#define FABS_D OPC_2R(0x4502)
+#define FNEG_S OPC_2R(0x4505)
+#define FNEG_D OPC_2R(0x4506)
+#define FMOV_S OPC_2R(0x4525)
+#define FMOV_D OPC_2R(0x4526)
+
+/* Floating-Point Conversion Instructions */
+#define FCVT_S_D OPC_2R(0x4646)
+#define FCVT_D_S OPC_2R(0x4649)
+#define FTINTRZ_W_S OPC_2R(0x46a1)
+#define FTINTRZ_W_D OPC_2R(0x46a2)
+#define FTINTRZ_L_S OPC_2R(0x46a9)
+#define FTINTRZ_L_D OPC_2R(0x46aa)
+#define FFINT_S_W OPC_2R(0x4744)
+#define FFINT_S_L OPC_2R(0x4746)
+#define FFINT_D_W OPC_2R(0x4748)
+#define FFINT_D_L OPC_2R(0x474a)
+
+/* Floating-Point Move Instructions */
+#define FMOV_S OPC_2R(0x4525)
+#define FMOV_D OPC_2R(0x4526)
+#define MOVGR2FR_W OPC_2R(0x4529)
+#define MOVGR2FR_D OPC_2R(0x452a)
+#define MOVGR2FRH_W OPC_2R(0x452b)
+#define MOVFR2GR_S OPC_2R(0x452d)
+#define MOVFR2GR_D OPC_2R(0x452e)
+#define MOVFRH2GR_S OPC_2R(0x452f)
+#define MOVGR2FCSR OPC_2R(0x4530)
+#define MOVFCSR2GR OPC_2R(0x4532)
+#define MOVFR2CF OPC_2R(0x4534)
+#define MOVCF2FR OPC_2R(0x4535)
+#define MOVGR2CF OPC_2R(0x4536)
+#define MOVCF2GR OPC_2R(0x4537)
+
+/* Floating-Point Branch Instructions */
+#define BCEQZ OPC_I26(0x12)
+#define BCNEZ OPC_I26(0x12)
+
+/* Floating-Point Common Memory Access Instructions */
+#define FLD_S OPC_2RI12(0xac)
+#define FLD_D OPC_2RI12(0xae)
+#define FST_S OPC_2RI12(0xad)
+#define FST_D OPC_2RI12(0xaf)
+
+#define FLDX_S OPC_3R(0x7060)
+#define FLDX_D OPC_3R(0x7068)
+#define FSTX_S OPC_3R(0x7070)
+#define FSTX_D OPC_3R(0x7078)
+
+/* Vector Instructions */
+
+/* Vector Arithmetic Instructions */
+#define VOR_V OPC_3R(0xe24d)
+#define VXOR_V OPC_3R(0xe24e)
+#define VAND_V OPC_3R(0xe24c)
+#define VMSKLTZ OPC_2R(0x1ca710)
+
+/* Vector Memory Access Instructions */
+#define VLD OPC_2RI12(0xb0)
+#define VST OPC_2RI12(0xb1)
+#define XVLD OPC_2RI12(0xb2)
+#define XVST OPC_2RI12(0xb3)
+#define VSTELM OPC_2RI8(0xc40)
+
+/* Vector Float Conversion Instructions */
+#define VFCVTL_D_S OPC_2R(0x1ca77c)
+
+/* Vector Bit Manipulate Instructions */
+#define VSLLWIL OPC_2R(0x1cc200)
+
+/* Vector Move And Shuffle Instructions */
+#define VLDREPL OPC_2R(0xc0000)
+#define VINSGR2VR OPC_2R(0x1cbac0)
+#define VPICKVE2GR_U OPC_2R(0x1cbce0)
+#define VREPLGR2VR OPC_2R(0x1ca7c0)
+#define VREPLVE OPC_3R(0xe244)
+#define VREPLVEI OPC_2R(0x1cbde0)
+#define VSHUF_B OPC_4R(0xd5)
+#define XVPERMI OPC_2RI8(0x1dfa)
+
+#define I12_MAX (0x7ff)
+#define I12_MIN (-0x800)
+#define BRANCH16_MAX (0x7fff << 2)
+#define BRANCH16_MIN (-(0x8000 << 2))
+#define BRANCH21_MAX (0xfffff << 2)
+#define BRANCH21_MIN (-(0x100000 << 2))
+#define JUMP_MAX (0x1ffffff << 2)
+#define JUMP_MIN (-(0x2000000 << 2))
+#define JIRL_MAX (0x7fff << 2)
+#define JIRL_MIN (-(0x8000 << 2))
+
+#define S32_MAX (0x7fffffffl)
+#define S32_MIN (-0x80000000l)
+#define S52_MAX (0x7ffffffffffffl)
+
+#define INST(inst, type) ((sljit_ins)((type & SLJIT_32) ? inst##_W : inst##_D))
+
+/* LoongArch CPUCFG register for feature detection */
+#define LOONGARCH_CFG2 0x02
+#define LOONGARCH_CFG2_LAMCAS (1 << 28)
+
+static sljit_u32 cfg2_feature_list = 0;
+
+/* According to Software Development and Build Convention for LoongArch Architectures,
++ the status of LSX and LASX extension must be checked through HWCAP */
+#include
+
+#define LOONGARCH_HWCAP_LSX (1 << 4)
+#define LOONGARCH_HWCAP_LASX (1 << 5)
+
+static sljit_u32 hwcap_feature_list = 0;
+
+/* Feature type */
+#define GET_CFG2 0
+#define GET_HWCAP 1
+
+#define LOONGARCH_SUPPORT_AMCAS (LOONGARCH_CFG2_LAMCAS & get_cpu_features(GET_CFG2))
+
+static SLJIT_INLINE sljit_u32 get_cpu_features(sljit_u32 feature_type)
+ {
+ if (cfg2_feature_list == 0)
+ __asm__ ("cpucfg %0, %1" : "+&r"(cfg2_feature_list) : "r"(LOONGARCH_CFG2));
+ if (hwcap_feature_list == 0)
+ hwcap_feature_list = (sljit_u32)getauxval(AT_HWCAP);
+
+ return feature_type ? hwcap_feature_list : cfg2_feature_list;
+ }
+
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
+{
+ sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ *ptr = ins;
+ compiler->size++;
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
+{
+ sljit_sw diff;
+ sljit_uw target_addr;
+ sljit_uw jump_addr = (sljit_uw)code_ptr;
+ sljit_uw orig_addr = jump->addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ jump->addr = jump_addr;
+ if (jump->flags & SLJIT_REWRITABLE_JUMP)
+ goto exit;
+
+ if (jump->flags & JUMP_ADDR)
+ target_addr = jump->u.target;
+ else {
+ SLJIT_ASSERT(jump->u.label != NULL);
+ target_addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
+
+ if (jump->u.label->size > orig_addr)
+ jump_addr = (sljit_uw)(code + orig_addr);
+ }
+
+ diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);
+
+ if (jump->flags & IS_COND) {
+ diff += SSIZE_OF(ins);
+
+ if (diff >= BRANCH16_MIN && diff <= BRANCH16_MAX) {
+ code_ptr--;
+ code_ptr[0] = (code_ptr[0] & 0xfc0003ff) ^ 0x4000000;
+ jump->flags |= PATCH_B;
+ jump->addr = (sljit_uw)code_ptr;
+ return code_ptr;
+ }
+
+ diff -= SSIZE_OF(ins);
+ }
+
+ if (diff >= JUMP_MIN && diff <= JUMP_MAX) {
+ if (jump->flags & IS_COND) {
+ code_ptr[-1] |= (sljit_ins)IMM_I16(2);
+ }
+
+ jump->flags |= PATCH_J;
+ return code_ptr;
+ }
+
+ if (diff >= S32_MIN && diff <= S32_MAX) {
+ if (jump->flags & IS_COND)
+ code_ptr[-1] |= (sljit_ins)IMM_I16(3);
+
+ jump->flags |= PATCH_REL32;
+ code_ptr[1] = code_ptr[0];
+ return code_ptr + 1;
+ }
+
+ if (target_addr <= (sljit_uw)S32_MAX) {
+ if (jump->flags & IS_COND)
+ code_ptr[-1] |= (sljit_ins)IMM_I16(3);
+
+ jump->flags |= PATCH_ABS32;
+ code_ptr[1] = code_ptr[0];
+ return code_ptr + 1;
+ }
+
+ if (target_addr <= S52_MAX) {
+ if (jump->flags & IS_COND)
+ code_ptr[-1] |= (sljit_ins)IMM_I16(4);
+
+ jump->flags |= PATCH_ABS52;
+ code_ptr[2] = code_ptr[0];
+ return code_ptr + 2;
+ }
+
+exit:
+ if (jump->flags & IS_COND)
+ code_ptr[-1] |= (sljit_ins)IMM_I16(5);
+ code_ptr[3] = code_ptr[0];
+ return code_ptr + 3;
+}
+
+static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
+{
+ sljit_uw addr;
+ sljit_uw jump_addr = (sljit_uw)code_ptr;
+ sljit_sw diff;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_ASSERT(jump->flags < ((sljit_uw)6 << JUMP_SIZE_SHIFT));
+ if (jump->flags & JUMP_ADDR)
+ addr = jump->u.target;
+ else {
+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
+
+ if (jump->u.label->size > jump->addr)
+ jump_addr = (sljit_uw)(code + jump->addr);
+ }
+
+ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);
+
+ if (diff >= S32_MIN && diff <= S32_MAX) {
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
+ jump->flags |= PATCH_REL32;
+ return 1;
+ }
+
+ if (addr <= S32_MAX) {
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
+ jump->flags |= PATCH_ABS32;
+ return 1;
+ }
+
+ if (addr <= S52_MAX) {
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)2 << JUMP_SIZE_SHIFT));
+ jump->flags |= PATCH_ABS52;
+ return 2;
+ }
+
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));
+ return 3;
+}
+
+static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw executable_offset)
+{
+ sljit_uw flags = jump->flags;
+ sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
+ sljit_ins *ins = (sljit_ins*)jump->addr;
+ sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : TMP_REG1;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ if (flags & PATCH_REL32) {
+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);
+
+ SLJIT_ASSERT((sljit_sw)addr >= S32_MIN && (sljit_sw)addr <= S32_MAX);
+
+ if ((addr & 0x800) != 0)
+ addr += 0x1000;
+
+ ins[0] = PCADDU12I | RD(reg) | IMM_I20(addr);
+
+ if (!(flags & JUMP_MOV_ADDR)) {
+ SLJIT_ASSERT((ins[1] & OPC_2RI16(0x3f)) == JIRL);
+ ins[1] = (ins[1] & (OPC_2RI16(0x3f) | 0x3ff)) | IMM_I16((addr & 0xfff) >> 2);
+ } else
+ ins[1] = ADDI_D | RD(reg) | RJ(reg) | IMM_I12(addr);
+ return;
+ }
+
+ if (flags & PATCH_ABS32) {
+ SLJIT_ASSERT(addr <= S32_MAX);
+ ins[0] = LU12I_W | RD(reg) | (sljit_ins)(((addr & 0xffffffff) >> 12) << 5);
+ } else if (flags & PATCH_ABS52) {
+ ins[0] = LU12I_W | RD(reg) | (sljit_ins)(((addr & 0xffffffff) >> 12) << 5);
+ ins[1] = LU32I_D | RD(reg) | (sljit_ins)(((addr >> 32) & 0xfffff) << 5);
+ ins += 1;
+ } else {
+ ins[0] = LU12I_W | RD(reg) | (sljit_ins)(((addr & 0xffffffff) >> 12) << 5);
+ ins[1] = LU32I_D | RD(reg) | (sljit_ins)(((addr >> 32) & 0xfffff) << 5);
+ ins[2] = LU52I_D | RD(reg) | RJ(reg) | IMM_I12(addr >> 52);
+ ins += 2;
+ }
+
+ if (!(flags & JUMP_MOV_ADDR)) {
+ SLJIT_ASSERT((ins[1] & OPC_2RI16(0x3f)) == JIRL);
+ ins[1] = (ins[1] & (OPC_2RI16(0x3f) | 0x3ff)) | IMM_I16((addr & 0xfff) >> 2);
+ } else
+ ins[1] = ORI | RD(reg) | RJ(reg) | IMM_I12(addr);
+}
+
+static SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
+static void reduce_code_size(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+ SLJIT_NEXT_DEFINE_TYPES;
+ sljit_uw total_size;
+ sljit_uw size_reduce = 0;
+ sljit_sw diff;
+
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+
+ SLJIT_NEXT_INIT_TYPES();
+
+ while (1) {
+ SLJIT_GET_NEXT_MIN();
+
+ if (next_min_addr == SLJIT_MAX_ADDRESS)
+ break;
+
+ if (next_min_addr == next_label_size) {
+ label->size -= size_reduce;
+
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ if (next_min_addr == next_const_addr) {
+ const_->addr -= size_reduce;
+ const_ = const_->next;
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+ continue;
+ }
+
+ if (next_min_addr != next_jump_addr)
+ continue;
+
+ jump->addr -= size_reduce;
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+ total_size = JUMP_MAX_SIZE;
+
+ if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {
+ if (jump->flags & JUMP_ADDR) {
+ if (jump->u.target <= S32_MAX)
+ total_size = 2;
+ else if (jump->u.target <= S52_MAX)
+ total_size = 3;
+ } else {
+ /* Unit size: instruction. */
+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
+ if (jump->u.label->size > jump->addr) {
+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);
+ diff -= (sljit_sw)size_reduce;
+ }
+
+ if ((jump->flags & IS_COND) && (diff + 1) <= (BRANCH16_MAX / SSIZE_OF(ins)) && (diff + 1) >= (BRANCH16_MIN / SSIZE_OF(ins)))
+ total_size = 0;
+ else if (diff >= (JUMP_MIN / SSIZE_OF(ins)) && diff <= (JUMP_MAX / SSIZE_OF(ins)))
+ total_size = 1;
+ else if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins)))
+ total_size = 2;
+ }
+ }
+
+ size_reduce += JUMP_MAX_SIZE - total_size;
+ jump->flags |= total_size << JUMP_SIZE_SHIFT;
+ } else {
+ total_size = 3;
+
+ if (!(jump->flags & JUMP_ADDR)) {
+ /* Real size minus 1. Unit size: instruction. */
+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
+ if (jump->u.label->size > jump->addr) {
+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);
+ diff -= (sljit_sw)size_reduce;
+ }
+
+ if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins)))
+ total_size = 1;
+ } else if (jump->u.target < S32_MAX)
+ total_size = 1;
+ else if (jump->u.target <= S52_MAX)
+ total_size = 2;
+
+ size_reduce += 3 - total_size;
+ jump->flags |= total_size << JUMP_SIZE_SHIFT;
+ }
+
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ }
+
+ compiler->size -= size_reduce;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
+{
+ struct sljit_memory_fragment *buf;
+ sljit_ins *code;
+ sljit_ins *code_ptr;
+ sljit_ins *buf_ptr;
+ sljit_ins *buf_end;
+ sljit_uw word_count;
+ SLJIT_NEXT_DEFINE_TYPES;
+ sljit_sw executable_offset;
+ sljit_uw addr;
+
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
+
+ reduce_code_size(compiler);
+
+ code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
+ PTR_FAIL_WITH_EXEC_IF(code);
+
+ reverse_buf(compiler);
+ buf = compiler->buf;
+
+ code_ptr = code;
+ word_count = 0;
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ SLJIT_NEXT_INIT_TYPES();
+ SLJIT_GET_NEXT_MIN();
+
+ do {
+ buf_ptr = (sljit_ins*)buf->memory;
+ buf_end = buf_ptr + (buf->used_size >> 2);
+ do {
+ *code_ptr = *buf_ptr++;
+ if (next_min_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+
+ /* These structures are ordered by their address. */
+ if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+ *code_ptr = buf_ptr[-1];
+ }
+
+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ if (next_min_addr == next_jump_addr) {
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+ word_count = word_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT);
+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
+ SLJIT_ASSERT((jump->flags & PATCH_B) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));
+ } else {
+ word_count += jump->flags >> JUMP_SIZE_SHIFT;
+ addr = (sljit_uw)code_ptr;
+ code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);
+ jump->addr = addr;
+ }
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ } else if (next_min_addr == next_const_addr) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+ }
+
+ SLJIT_GET_NEXT_MIN();
+ }
+ code_ptr++;
+ word_count++;
+ } while (buf_ptr < buf_end);
+
+ buf = buf->next;
+ } while (buf);
+
+ if (label && label->size == word_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
+ label->u.addr = (sljit_uw)code_ptr;
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ }
+
+ SLJIT_ASSERT(!label);
+ SLJIT_ASSERT(!jump);
+ SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
+
+ jump = compiler->jumps;
+ while (jump) {
+ do {
+ if (!(jump->flags & (PATCH_B | PATCH_J)) || (jump->flags & JUMP_MOV_ADDR)) {
+ load_addr_to_reg(jump, executable_offset);
+ break;
+ }
+
+ addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
+ buf_ptr = (sljit_ins *)jump->addr;
+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
+
+ if (jump->flags & PATCH_B) {
+ SLJIT_ASSERT((sljit_sw)addr >= BRANCH16_MIN && (sljit_sw)addr <= BRANCH16_MAX);
+ buf_ptr[0] |= (sljit_ins)IMM_I16(addr >> 2);
+ break;
+ }
+
+ SLJIT_ASSERT((sljit_sw)addr >= JUMP_MIN && (sljit_sw)addr <= JUMP_MAX);
+ if (jump->flags & IS_CALL)
+ buf_ptr[0] = BL | (sljit_ins)IMM_I26(addr >> 2);
+ else
+ buf_ptr[0] = B | (sljit_ins)IMM_I26(addr >> 2);
+ } while (0);
+ jump = jump->next;
+ }
+
+ compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
+
+ code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+ code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
+ SLJIT_CACHE_FLUSH(code, code_ptr);
+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
+ return code;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type)
+ {
+ case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return (SLJIT_IS_FPU_AVAILABLE) != 0;
+#else
+ /* Available by default. */
+ return 1;
+#endif
+
+ case SLJIT_HAS_LASX:
+ return (LOONGARCH_HWCAP_LASX & get_cpu_features(GET_HWCAP));
+
+ case SLJIT_HAS_SIMD:
+ return (LOONGARCH_HWCAP_LSX & get_cpu_features(GET_HWCAP));
+
+ case SLJIT_HAS_CLZ:
+ case SLJIT_HAS_CTZ:
+ case SLJIT_HAS_REV:
+ case SLJIT_HAS_ROT:
+ case SLJIT_HAS_PREFETCH:
+ case SLJIT_HAS_COPY_F32:
+ case SLJIT_HAS_COPY_F64:
+ case SLJIT_HAS_ATOMIC:
+ case SLJIT_HAS_MEMORY_BARRIER:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
+{
+ SLJIT_UNUSED_ARG(type);
+
+ return 0;
+}
+
+/* --------------------------------------------------------------------- */
+/* Entry, exit */
+/* --------------------------------------------------------------------- */
+
+/* Creates an index in data_transfer_insts array. */
+#define LOAD_DATA 0x01
+#define WORD_DATA 0x00
+#define BYTE_DATA 0x02
+#define HALF_DATA 0x04
+#define INT_DATA 0x06
+#define SIGNED_DATA 0x08
+/* Separates integer and floating point registers */
+#define GPR_REG 0x0f
+#define DOUBLE_DATA 0x10
+#define SINGLE_DATA 0x12
+
+#define MEM_MASK 0x1f
+
+#define ARG_TEST 0x00020
+#define ALT_KEEP_CACHE 0x00040
+#define CUMULATIVE_OP 0x00080
+#define IMM_OP 0x00100
+#define MOVE_OP 0x00200
+#define SRC2_IMM 0x00400
+
+#define UNUSED_DEST 0x00800
+#define REG_DEST 0x01000
+#define REG1_SOURCE 0x02000
+#define REG2_SOURCE 0x04000
+#define SLOW_SRC1 0x08000
+#define SLOW_SRC2 0x10000
+#define SLOW_DEST 0x20000
+#define MEM_USE_TMP2 0x40000
+
+#define STACK_STORE ST_D
+#define STACK_LOAD LD_D
+
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm)
+{
+ if (imm <= I12_MAX && imm >= I12_MIN)
+ return push_inst(compiler, ADDI_D | RD(dst_r) | RJ(TMP_ZERO) | IMM_I12(imm));
+
+ if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
+ FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)(((imm & 0xffffffff) >> 12) << 5)));
+ if (IMM_I12(imm) != 0)
+ return push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm));
+ return SLJIT_SUCCESS;
+ } else if (imm <= 0x7ffffffffffffl && imm >= -0x8000000000000l) {
+ FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)(((imm & 0xffffffff) >> 12) << 5)));
+ if (IMM_I12(imm) != 0)
+ FAIL_IF(push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm)));
+ return push_inst(compiler, LU32I_D | RD(dst_r) | (sljit_ins)(((imm >> 32) & 0xfffff) << 5));
+ }
+ FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)(((imm & 0xffffffff) >> 12) << 5)));
+ if (IMM_I12(imm) != 0)
+ FAIL_IF(push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm)));
+ FAIL_IF(push_inst(compiler, LU32I_D | RD(dst_r) | (sljit_ins)(((imm >> 32) & 0xfffff) << 5)));
+ return push_inst(compiler, LU52I_D | RD(dst_r) | RJ(dst_r) | IMM_I12(imm >> 52));
+}
+
+#define STACK_MAX_DISTANCE (-I12_MIN)
+
+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw);
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches;
+ sljit_s32 fsaveds;
+ sljit_s32 i, tmp, offset;
+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);
+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+
+ local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
+ compiler->local_size = local_size;
+
+ if (local_size <= STACK_MAX_DISTANCE) {
+ /* Frequent case. */
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(-local_size)));
+ offset = local_size - SSIZE_OF(sw);
+ local_size = 0;
+ } else {
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(STACK_MAX_DISTANCE)));
+ local_size -= STACK_MAX_DISTANCE;
+
+ if (local_size > STACK_MAX_DISTANCE)
+ FAIL_IF(load_immediate(compiler, TMP_REG1, local_size));
+ offset = STACK_MAX_DISTANCE - SSIZE_OF(sw);
+ }
+
+ FAIL_IF(push_inst(compiler, STACK_STORE | RD(RETURN_ADDR_REG) | RJ(SLJIT_SP) | IMM_I12(offset)));
+
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_STORE | RD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));
+ }
+
+ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_STORE | RD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));
+ }
+
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, FST_D | FRD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));
+ }
+
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, FST_D | FRD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));
+ }
+
+ if (local_size > STACK_MAX_DISTANCE)
+ FAIL_IF(push_inst(compiler, SUB_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | RK(TMP_REG1)));
+ else if (local_size > 0)
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(-local_size)));
+
+ if (options & SLJIT_ENTER_REG_ARG)
+ return SLJIT_SUCCESS;
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ saved_arg_count = 0;
+ tmp = SLJIT_R0;
+
+ while (arg_types > 0) {
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_S0 - saved_arg_count) | RJ(tmp) | IMM_I12(0)));
+ saved_arg_count++;
+ }
+ tmp++;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+#undef STACK_MAX_DISTANCE
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches;
+ sljit_s32 fsaveds;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);
+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+
+ compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
+
+ return SLJIT_SUCCESS;
+}
+
+#define STACK_MAX_DISTANCE (-I12_MIN - 16)
+
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)
+{
+ sljit_s32 i, tmp, offset;
+ sljit_s32 local_size = compiler->local_size;
+
+ if (local_size > STACK_MAX_DISTANCE) {
+ local_size -= STACK_MAX_DISTANCE;
+
+ if (local_size > STACK_MAX_DISTANCE) {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, local_size));
+ FAIL_IF(push_inst(compiler, ADD_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | RK(TMP_REG2)));
+ } else
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(local_size)));
+
+ local_size = STACK_MAX_DISTANCE;
+ }
+
+ SLJIT_ASSERT(local_size > 0);
+
+ offset = local_size - SSIZE_OF(sw);
+ if (!is_return_to)
+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RJ(SLJIT_SP) | IMM_I12(offset)));
+
+ tmp = SLJIT_S0 - compiler->saveds;
+ for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));
+ }
+
+ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));
+ }
+
+ tmp = SLJIT_FS0 - compiler->fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, FLD_D | FRD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));
+ }
+
+ for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, FLD_D | FRD(i) | RJ(SLJIT_SP) | IMM_I12(offset)));
+ }
+
+ return push_inst(compiler, ADDI_D | RD(SLJIT_SP) | RJ(SLJIT_SP) | IMM_I12(local_size));
+}
+
+#undef STACK_MAX_DISTANCE
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ FAIL_IF(emit_stack_frame_release(compiler, 0));
+ return push_inst(compiler, JIRL | RD(TMP_ZERO) | RJ(RETURN_ADDR_REG) | IMM_I12(0));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
+ src = TMP_REG1;
+ srcw = 0;
+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(src) | IMM_I12(0)));
+ src = TMP_REG1;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 1));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
+}
+
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
+static const sljit_ins data_transfer_insts[16 + 4] = {
+/* u w s */ ST_D /* st.d */,
+/* u w l */ LD_D /* ld.d */,
+/* u b s */ ST_B /* st.b */,
+/* u b l */ LD_BU /* ld.bu */,
+/* u h s */ ST_H /* st.h */,
+/* u h l */ LD_HU /* ld.hu */,
+/* u i s */ ST_W /* st.w */,
+/* u i l */ LD_WU /* ld.wu */,
+
+/* s w s */ ST_D /* st.d */,
+/* s w l */ LD_D /* ld.d */,
+/* s b s */ ST_B /* st.b */,
+/* s b l */ LD_B /* ld.b */,
+/* s h s */ ST_H /* st.h */,
+/* s h l */ LD_H /* ld.h */,
+/* s i s */ ST_W /* st.w */,
+/* s i l */ LD_W /* ld.w */,
+
+/* d s */ FST_D /* fst.d */,
+/* d l */ FLD_D /* fld.d */,
+/* s s */ FST_S /* fst.s */,
+/* s l */ FLD_S /* fld.s */,
+};
+
+static const sljit_ins data_transfer_insts_x[16 + 4] = {
+/* u w s */ STX_D /* stx.d */,
+/* u w l */ LDX_D /* ldx.d */,
+/* u b s */ STX_B /* stx.b */,
+/* u b l */ LDX_BU /* ldx.bu */,
+/* u h s */ STX_H /* stx.h */,
+/* u h l */ LDX_HU /* ldx.hu */,
+/* u i s */ STX_W /* stx.w */,
+/* u i l */ LDX_WU /* ldx.wu */,
+
+/* s w s */ STX_D /* stx.d */,
+/* s w l */ LDX_D /* ldx.d */,
+/* s b s */ STX_B /* stx.b */,
+/* s b l */ LDX_B /* ldx.b */,
+/* s h s */ STX_H /* stx.h */,
+/* s h l */ LDX_H /* ldx.h */,
+/* s i s */ STX_W /* stx.w */,
+/* s i l */ LDX_W /* ldx.w */,
+
+/* d s */ FSTX_D /* fstx.d */,
+/* d l */ FLDX_D /* fldx.d */,
+/* s s */ FSTX_S /* fstx.s */,
+/* s l */ FLDX_S /* fldx.s */,
+};
+
+static sljit_s32 push_mem_inst(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
+{
+ sljit_ins ins;
+ sljit_s32 base = arg & REG_MASK;
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+
+ if (arg & OFFS_REG_MASK) {
+ sljit_s32 offs = OFFS_REG(arg);
+
+ SLJIT_ASSERT(!argw);
+ ins = data_transfer_insts_x[flags & MEM_MASK] |
+ ((flags & MEM_MASK) <= GPR_REG ? RD(reg) : FRD(reg)) |
+ RJ(base) | RK(offs);
+ } else {
+ SLJIT_ASSERT(argw <= 0xfff && argw >= I12_MIN);
+
+ ins = data_transfer_insts[flags & MEM_MASK] |
+ ((flags & MEM_MASK) <= GPR_REG ? RD(reg) : FRD(reg)) |
+ RJ(base) | IMM_I12(argw);
+ }
+ return push_inst(compiler, ins);
+}
+
+/* Can perform an operation using at most 1 instruction. */
+static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
+{
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+
+ /* argw == 0 (ldx/stx rd, rj, rk) can be used.
+ * argw in [-2048, 2047] (ld/st rd, rj, imm) can be used. */
+ if (!argw || (!(arg & OFFS_REG_MASK) && (argw <= I12_MAX && argw >= I12_MIN))) {
+ /* Works for both absolute and relative addresses. */
+ if (SLJIT_UNLIKELY(flags & ARG_TEST))
+ return 1;
+
+ FAIL_IF(push_mem_inst(compiler, flags, reg, arg, argw));
+ return -1;
+ }
+ return 0;
+}
+
+#define TO_ARGW_HI(argw) (((argw) & ~0xfff) + (((argw) & 0x800) ? 0x1000 : 0))
+
+/* See getput_arg below.
+ Note: can_cache is called only for binary operators. */
+static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
+{
+ SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
+
+ if (arg & OFFS_REG_MASK)
+ return 0;
+
+ if (arg == next_arg) {
+ if (((next_argw - argw) <= I12_MAX && (next_argw - argw) >= I12_MIN)
+ || TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw))
+ return 1;
+ return 0;
+ }
+
+ return 0;
+}
+
+/* Emit the necessary instructions. See can_cache above. */
+static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
+{
+ sljit_s32 base = arg & REG_MASK;
+ sljit_s32 tmp_r = (flags & MEM_USE_TMP2) ? TMP_REG2 : TMP_REG1;
+ sljit_sw offset;
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+ if (!(next_arg & SLJIT_MEM)) {
+ next_arg = 0;
+ next_argw = 0;
+ }
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ argw &= 0x3;
+
+ if (SLJIT_UNLIKELY(argw))
+ FAIL_IF(push_inst(compiler, SLLI_D | RD(TMP_REG3) | RJ(OFFS_REG(arg)) | IMM_I12(argw)));
+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM2(base, TMP_REG3), 0);
+ }
+
+ if (compiler->cache_arg == arg && argw - compiler->cache_argw <= I12_MAX && argw - compiler->cache_argw >= I12_MIN)
+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(TMP_REG3), argw - compiler->cache_argw);
+
+ if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw <= I12_MAX) && (argw - compiler->cache_argw >= I12_MIN)) {
+ offset = argw - compiler->cache_argw;
+ } else {
+ sljit_sw argw_hi=TO_ARGW_HI(argw);
+ compiler->cache_arg = SLJIT_MEM;
+
+ if (next_arg && next_argw - argw <= I12_MAX && next_argw - argw >= I12_MIN && argw_hi != TO_ARGW_HI(next_argw)) {
+ FAIL_IF(load_immediate(compiler, TMP_REG3, argw));
+ compiler->cache_argw = argw;
+ offset = 0;
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG3, argw_hi));
+ compiler->cache_argw = argw_hi;
+ offset = argw & 0xfff;
+ argw = argw_hi;
+ }
+ }
+
+ if (!base)
+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(TMP_REG3), offset);
+
+ if (arg == next_arg && next_argw - argw <= I12_MAX && next_argw - argw >= I12_MIN) {
+ compiler->cache_arg = arg;
+ FAIL_IF(push_inst(compiler, ADD_D | RD(TMP_REG3) | RJ(TMP_REG3) | RK(base)));
+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(TMP_REG3), offset);
+ }
+
+ if (!offset)
+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM2(base, TMP_REG3), 0);
+
+ FAIL_IF(push_inst(compiler, ADD_D | RD(tmp_r) | RJ(TMP_REG3) | RK(base)));
+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(tmp_r), offset);
+}
+
+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
+{
+ sljit_s32 base = arg & REG_MASK;
+ sljit_s32 tmp_r = TMP_REG1;
+
+ if (getput_arg_fast(compiler, flags, reg, arg, argw))
+ return compiler->error;
+
+ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA))
+ tmp_r = reg;
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ argw &= 0x3;
+
+ if (SLJIT_UNLIKELY(argw))
+ FAIL_IF(push_inst(compiler, SLLI_D | RD(tmp_r) | RJ(OFFS_REG(arg)) | IMM_I12(argw)));
+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM2(base, tmp_r), 0);
+ } else {
+ FAIL_IF(load_immediate(compiler, tmp_r, argw));
+
+ if (base != 0)
+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM2(base, tmp_r), 0);
+ return push_mem_inst(compiler, flags, reg, SLJIT_MEM1(tmp_r), 0);
+ }
+}
+
+static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
+{
+ if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
+ return compiler->error;
+ return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
+}
+
+#define IMM_EXTEND(v) (IMM_I12((op & SLJIT_32) ? (v) : (32 + (v))))
+
+/* andi/ori/xori are zero-extended */
+#define EMIT_LOGICAL(op_imm, op_reg) \
+ if (flags & SRC2_IMM) { \
+ if (op & SLJIT_SET_Z) {\
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(EQUAL_FLAG) | RJ(TMP_ZERO) | IMM_I12(src2))); \
+ FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RJ(src1) | RK(EQUAL_FLAG))); \
+ } \
+ if (!(flags & UNUSED_DEST)) { \
+ if (dst == src1) { \
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(TMP_ZERO) | IMM_I12(src2))); \
+ FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RJ(src1) | RK(TMP_REG1))); \
+ } else { \
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(dst) | RJ(TMP_ZERO) | IMM_I12(src2))); \
+ FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RJ(src1) | RK(dst))); \
+ } \
+ } \
+ } else { \
+ if (op & SLJIT_SET_Z) \
+ FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RJ(src1) | RK(src2))); \
+ if (!(flags & UNUSED_DEST)) \
+ FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RJ(src1) | RK(src2))); \
+ } \
+ while (0)
+
+#define EMIT_SHIFT(imm, reg) \
+ op_imm = (imm); \
+ op_reg = (reg)
+
+static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+ sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
+{
+ sljit_s32 is_overflow, is_carry, carry_src_r, is_handled, reg;
+ sljit_ins op_imm, op_reg;
+ sljit_ins word_size = ((op & SLJIT_32) ? 32 : 64);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if (dst != src2)
+ return push_inst(compiler, INST(ADD, op) | RD(dst) | RJ(src2) | IMM_I12(0));
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_U8:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
+ return push_inst(compiler, ANDI | RD(dst) | RJ(src2) | IMM_I12(0xff));
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_S8:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
+ return push_inst(compiler, EXT_W_B | RD(dst) | RJ(src2));
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_U16:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
+ return push_inst(compiler, INST(BSTRPICK, op) | RD(dst) | RJ(src2) | (15 << 16));
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_S16:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
+ return push_inst(compiler, EXT_W_H | RD(dst) | RJ(src2));
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_U32:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
+ return push_inst(compiler, BSTRPICK_D | RD(dst) | RJ(src2) | (31 << 16));
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_S32:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
+ return push_inst(compiler, SLLI_W | RD(dst) | RJ(src2) | IMM_I12(0));
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_CLZ:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ return push_inst(compiler, INST(CLZ, op) | RD(dst) | RJ(src2));
+
+ case SLJIT_CTZ:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ return push_inst(compiler, INST(CTZ, op) | RD(dst) | RJ(src2));
+
+ case SLJIT_REV:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ return push_inst(compiler, ((op & SLJIT_32) ? REVB_2W : REVB_D) | RD(dst) | RJ(src2));
+
+ case SLJIT_REV_S16:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ FAIL_IF(push_inst(compiler, REVB_2H | RD(dst) | RJ(src2)));
+ return push_inst(compiler, EXT_W_H | RD(dst) | RJ(dst));
+
+ case SLJIT_REV_U16:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ FAIL_IF(push_inst(compiler, REVB_2H | RD(dst) | RJ(src2)));
+ return push_inst(compiler, INST(BSTRPICK, op) | RD(dst) | RJ(dst) | (15 << 16));
+
+ case SLJIT_REV_S32:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM) && dst != TMP_REG1);
+ FAIL_IF(push_inst(compiler, REVB_2W | RD(dst) | RJ(src2)));
+ return push_inst(compiler, SLLI_W | RD(dst) | RJ(dst) | IMM_I12(0));
+
+ case SLJIT_REV_U32:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM) && dst != TMP_REG1);
+ FAIL_IF(push_inst(compiler, REVB_2W | RD(dst) | RJ(src2)));
+ return push_inst(compiler, BSTRPICK_D | RD(dst) | RJ(dst) | (31 << 16));
+
+ case SLJIT_ADD:
+ /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */
+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+ carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;
+
+ if (flags & SRC2_IMM) {
+ if (is_overflow) {
+ if (src2 >= 0)
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(0)));
+ else {
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(TMP_ZERO) | IMM_I12(-1)));
+ FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(src1) | RK(EQUAL_FLAG)));
+ }
+ } else if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(src2)));
+
+ /* Only the zero flag is needed. */
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(src2)));
+ } else {
+ if (is_overflow)
+ FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));
+ else if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, INST(ADD, op) | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));
+
+ if (is_overflow || carry_src_r != 0) {
+ if (src1 != dst)
+ carry_src_r = (sljit_s32)src1;
+ else if (src2 != dst)
+ carry_src_r = (sljit_s32)src2;
+ else {
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(OTHER_FLAG) | RJ(src1) | IMM_I12(0)));
+ carry_src_r = OTHER_FLAG;
+ }
+ }
+
+ /* Only the zero flag is needed. */
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
+ FAIL_IF(push_inst(compiler, INST(ADD, op) | RD(dst) | RJ(src1) | RK(src2)));
+ }
+
+ /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
+ if (is_overflow || carry_src_r != 0) {
+ if (flags & SRC2_IMM)
+ FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RJ(dst) | IMM_I12(src2)));
+ else
+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(dst) | RK(carry_src_r)));
+ }
+
+ if (!is_overflow)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RJ(dst) | RK(EQUAL_FLAG)));
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, INST(ADD, op) | RD(EQUAL_FLAG) | RJ(dst) | IMM_I12(0)));
+ FAIL_IF(push_inst(compiler, INST(SRLI, op) | RD(TMP_REG1) | RJ(TMP_REG1) | IMM_EXTEND(31)));
+ return push_inst(compiler, XOR | RD(OTHER_FLAG) | RJ(TMP_REG1) | RK(OTHER_FLAG));
+
+ case SLJIT_ADDC:
+ carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;
+
+ if (flags & SRC2_IMM) {
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(dst) | RJ(src1) | IMM_I12(src2)));
+ } else {
+ if (carry_src_r != 0) {
+ if (src1 != dst)
+ carry_src_r = (sljit_s32)src1;
+ else if (src2 != dst)
+ carry_src_r = (sljit_s32)src2;
+ else {
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(0)));
+ carry_src_r = EQUAL_FLAG;
+ }
+ }
+
+ FAIL_IF(push_inst(compiler, ADD_D | RD(dst) | RJ(src1) | RK(src2)));
+ }
+
+ /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
+ if (carry_src_r != 0) {
+ if (flags & SRC2_IMM)
+ FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RJ(dst) | IMM_I12(src2)));
+ else
+ FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RJ(dst) | RK(carry_src_r)));
+ }
+
+ FAIL_IF(push_inst(compiler, ADD_D | RD(dst) | RJ(dst) | RK(OTHER_FLAG)));
+
+ if (carry_src_r == 0)
+ return SLJIT_SUCCESS;
+
+ /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(dst) | RK(OTHER_FLAG)));
+ /* Set carry flag. */
+ return push_inst(compiler, OR | RD(OTHER_FLAG) | RJ(OTHER_FLAG) | RK(EQUAL_FLAG));
+
+ case SLJIT_SUB:
+ if ((flags & SRC2_IMM) && src2 == I12_MIN) {
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG2) | RJ(TMP_ZERO) | IMM_I12(src2)));
+ src2 = TMP_REG2;
+ flags &= ~SRC2_IMM;
+ }
+
+ is_handled = 0;
+
+ if (flags & SRC2_IMM) {
+ if (GET_FLAG_TYPE(op) == SLJIT_LESS) {
+ FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RJ(src1) | IMM_I12(src2)));
+ is_handled = 1;
+ } else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) {
+ FAIL_IF(push_inst(compiler, SLTI | RD(OTHER_FLAG) | RJ(src1) | IMM_I12(src2)));
+ is_handled = 1;
+ }
+ }
+
+ if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
+ is_handled = 1;
+
+ if (flags & SRC2_IMM) {
+ reg = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(reg) | RJ(TMP_ZERO) | IMM_I12(src2)));
+ src2 = reg;
+ flags &= ~SRC2_IMM;
+ }
+
+ switch (GET_FLAG_TYPE(op)) {
+ case SLJIT_LESS:
+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(src1) | RK(src2)));
+ break;
+ case SLJIT_GREATER:
+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(src2) | RK(src1)));
+ break;
+ case SLJIT_SIG_LESS:
+ FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RJ(src1) | RK(src2)));
+ break;
+ case SLJIT_SIG_GREATER:
+ FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RJ(src2) | RK(src1)));
+ break;
+ }
+ }
+
+ if (is_handled) {
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(-src2)));
+ if (!(flags & UNUSED_DEST))
+ return push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(-src2));
+ } else {
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));
+ if (!(flags & UNUSED_DEST))
+ return push_inst(compiler, INST(SUB, op) | RD(dst) | RJ(src1) | RK(src2));
+ }
+ return SLJIT_SUCCESS;
+ }
+
+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+ is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;
+
+ if (flags & SRC2_IMM) {
+ if (is_overflow) {
+ if (src2 >= 0)
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(0)));
+ else {
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(TMP_ZERO) | IMM_I12(-1)));
+ FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(src1) | RK(EQUAL_FLAG)));
+ }
+ } else if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(-src2)));
+
+ if (is_overflow || is_carry)
+ FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RJ(src1) | IMM_I12(src2)));
+
+ /* Only the zero flag is needed. */
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(-src2)));
+ } else {
+ if (is_overflow)
+ FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));
+ else if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));
+
+ if (is_overflow || is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RJ(src1) | RK(src2)));
+
+ /* Only the zero flag is needed. */
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
+ FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(dst) | RJ(src1) | RK(src2)));
+ }
+
+ if (!is_overflow)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RJ(dst) | RK(EQUAL_FLAG)));
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(dst) | IMM_I12(0)));
+ FAIL_IF(push_inst(compiler, INST(SRLI, op) | RD(TMP_REG1) | RJ(TMP_REG1) | IMM_EXTEND(31)));
+ return push_inst(compiler, XOR | RD(OTHER_FLAG) | RJ(TMP_REG1) | RK(OTHER_FLAG));
+
+ case SLJIT_SUBC:
+ if ((flags & SRC2_IMM) && src2 == I12_MIN) {
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(TMP_REG2) | RJ(TMP_ZERO) | IMM_I12(src2)));
+ src2 = TMP_REG2;
+ flags &= ~SRC2_IMM;
+ }
+
+ is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;
+
+ if (flags & SRC2_IMM) {
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(src2)));
+
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(-src2)));
+ } else {
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));
+
+ FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(dst) | RJ(src1) | RK(src2)));
+ }
+
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | RD(TMP_REG1) | RJ(dst) | RK(OTHER_FLAG)));
+
+ FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(dst) | RJ(dst) | RK(OTHER_FLAG)));
+
+ if (!is_carry)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, OR | RD(OTHER_FLAG) | RJ(EQUAL_FLAG) | RK(TMP_REG1));
+
+ case SLJIT_MUL:
+ SLJIT_ASSERT(!(flags & SRC2_IMM));
+
+ if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW)
+ return push_inst(compiler, INST(MUL, op) | RD(dst) | RJ(src1) | RK(src2));
+
+ if (op & SLJIT_32) {
+ FAIL_IF(push_inst(compiler, MUL_D | RD(OTHER_FLAG) | RJ(src1) | RK(src2)));
+ FAIL_IF(push_inst(compiler, MUL_W | RD(dst) | RJ(src1) | RK(src2)));
+ return push_inst(compiler, SUB_D | RD(OTHER_FLAG) | RJ(dst) | RK(OTHER_FLAG));
+ }
+
+ FAIL_IF(push_inst(compiler, MULH_D | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));
+ FAIL_IF(push_inst(compiler, MUL_D | RD(dst) | RJ(src1) | RK(src2)));
+ FAIL_IF(push_inst(compiler, SRAI_D | RD(OTHER_FLAG) | RJ(dst) | IMM_I12((63))));
+ return push_inst(compiler, SUB_D | RD(OTHER_FLAG) | RJ(EQUAL_FLAG) | RK(OTHER_FLAG));
+
+ case SLJIT_AND:
+ EMIT_LOGICAL(ANDI, AND);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_OR:
+ EMIT_LOGICAL(ORI, OR);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_XOR:
+ EMIT_LOGICAL(XORI, XOR);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ if (op & SLJIT_32) {
+ EMIT_SHIFT(SLLI_W, SLL_W);
+ } else {
+ EMIT_SHIFT(SLLI_D, SLL_D);
+ }
+ break;
+
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ if (op & SLJIT_32) {
+ EMIT_SHIFT(SRLI_W, SRL_W);
+ } else {
+ EMIT_SHIFT(SRLI_D, SRL_D);
+ }
+ break;
+
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ if (op & SLJIT_32) {
+ EMIT_SHIFT(SRAI_W, SRA_W);
+ } else {
+ EMIT_SHIFT(SRAI_D, SRA_D);
+ }
+ break;
+
+ case SLJIT_ROTL:
+ case SLJIT_ROTR:
+ if (flags & SRC2_IMM) {
+ SLJIT_ASSERT(src2 != 0);
+
+ if (GET_OPCODE(op) == SLJIT_ROTL)
+ src2 = word_size - src2;
+ return push_inst(compiler, INST(ROTRI, op) | RD(dst) | RJ(src1) | IMM_I12(src2));
+ }
+
+ if (src2 == TMP_ZERO) {
+ if (dst != src1)
+ return push_inst(compiler, INST(ADDI, op) | RD(dst) | RJ(src1) | IMM_I12(0));
+ return SLJIT_SUCCESS;
+ }
+
+ if (GET_OPCODE(op) == SLJIT_ROTL) {
+ FAIL_IF(push_inst(compiler, INST(SUB, op)| RD(OTHER_FLAG) | RJ(TMP_ZERO) | RK(src2)));
+ src2 = OTHER_FLAG;
+ }
+ return push_inst(compiler, INST(ROTR, op) | RD(dst) | RJ(src1) | RK(src2));
+
+ default:
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
+ }
+
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, op_imm | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(src2)));
+
+ if (flags & UNUSED_DEST)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, op_imm | RD(dst) | RJ(src1) | IMM_I12(src2));
+ }
+
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RJ(src1) | RK(src2)));
+
+ if (flags & UNUSED_DEST)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, op_reg | RD(dst) | RJ(src1) | RK(src2));
+}
+
+#undef IMM_EXTEND
+
+static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ /* arg1 goes to TMP_REG1 or src reg
+ arg2 goes to TMP_REG2, imm or src reg
+ TMP_REG3 can be used for caching
+ result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
+ sljit_s32 dst_r = TMP_REG2;
+ sljit_s32 src1_r;
+ sljit_sw src2_r = 0;
+ sljit_s32 src2_tmp_reg = (GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;
+
+ if (!(flags & ALT_KEEP_CACHE)) {
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ }
+
+ if (dst == 0) {
+ SLJIT_ASSERT(HAS_FLAGS(op));
+ flags |= UNUSED_DEST;
+ dst = TMP_REG2;
+ } else if (FAST_IS_REG(dst)) {
+ dst_r = dst;
+ flags |= REG_DEST;
+ if (flags & MOVE_OP)
+ src2_tmp_reg = dst_r;
+ } else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))
+ flags |= SLOW_DEST;
+
+ if (flags & IMM_OP) {
+ if (src2 == SLJIT_IMM && src2w != 0 && src2w <= I12_MAX && src2w >= I12_MIN) {
+ flags |= SRC2_IMM;
+ src2_r = src2w;
+ } else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && src1w <= I12_MAX && src1w >= I12_MIN) {
+ flags |= SRC2_IMM;
+ src2_r = src1w;
+
+ /* And swap arguments. */
+ src1 = src2;
+ src1w = src2w;
+ src2 = SLJIT_IMM;
+ /* src2w = src2_r unneeded. */
+ }
+ }
+
+ /* Source 1. */
+ if (FAST_IS_REG(src1)) {
+ src1_r = src1;
+ flags |= REG1_SOURCE;
+ } else if (src1 == SLJIT_IMM) {
+ if (src1w) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+ src1_r = TMP_REG1;
+ }
+ else
+ src1_r = TMP_ZERO;
+ } else {
+ if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w))
+ FAIL_IF(compiler->error);
+ else
+ flags |= SLOW_SRC1;
+ src1_r = TMP_REG1;
+ }
+
+ /* Source 2. */
+ if (FAST_IS_REG(src2)) {
+ src2_r = src2;
+ flags |= REG2_SOURCE;
+ if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)
+ dst_r = (sljit_s32)src2_r;
+ } else if (src2 == SLJIT_IMM) {
+ if (!(flags & SRC2_IMM)) {
+ if (src2w) {
+ FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w));
+ src2_r = src2_tmp_reg;
+ } else {
+ src2_r = TMP_ZERO;
+ if (flags & MOVE_OP) {
+ if (dst & SLJIT_MEM)
+ dst_r = 0;
+ else
+ op = SLJIT_MOV;
+ }
+ }
+ }
+ } else {
+ if (getput_arg_fast(compiler, flags | LOAD_DATA, src2_tmp_reg, src2, src2w))
+ FAIL_IF(compiler->error);
+ else
+ flags |= SLOW_SRC2;
+
+ src2_r = src2_tmp_reg;
+ }
+
+ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
+ SLJIT_ASSERT(src2_r == TMP_REG2);
+ if ((flags & SLOW_DEST) && !can_cache(src2, src2w, src1, src1w) && can_cache(src2, src2w, dst, dstw)) {
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA | MEM_USE_TMP2, TMP_REG2, src2, src2w, dst, dstw));
+ } else {
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+ }
+ }
+ else if (flags & SLOW_SRC1)
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+ else if (flags & SLOW_SRC2)
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA | ((src1_r == TMP_REG1) ? MEM_USE_TMP2 : 0), src2_tmp_reg, src2, src2w, dst, dstw));
+
+ FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
+
+ if (dst & SLJIT_MEM) {
+ if (!(flags & SLOW_DEST)) {
+ getput_arg_fast(compiler, flags, dst_r, dst, dstw);
+ return compiler->error;
+ }
+ return getput_arg(compiler, flags, dst_r, dst, dstw, 0, 0);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op0(compiler, op));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_BREAKPOINT:
+ return push_inst(compiler, BREAK);
+ case SLJIT_NOP:
+ return push_inst(compiler, NOP);
+ case SLJIT_LMUL_UW:
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(SLJIT_R1) | IMM_I12(0)));
+ FAIL_IF(push_inst(compiler, MULH_DU | RD(SLJIT_R1) | RJ(SLJIT_R0) | RK(SLJIT_R1)));
+ return push_inst(compiler, MUL_D | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(TMP_REG1));
+ case SLJIT_LMUL_SW:
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(SLJIT_R1) | IMM_I12(0)));
+ FAIL_IF(push_inst(compiler, MULH_D | RD(SLJIT_R1) | RJ(SLJIT_R0) | RK(SLJIT_R1)));
+ return push_inst(compiler, MUL_D | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(TMP_REG1));
+ case SLJIT_DIVMOD_UW:
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(TMP_REG1) | RJ(SLJIT_R0) | IMM_I12(0)));
+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32)? DIV_WU: DIV_DU) | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(SLJIT_R1)));
+ return push_inst(compiler, ((op & SLJIT_32)? MOD_WU: MOD_DU) | RD(SLJIT_R1) | RJ(TMP_REG1) | RK(SLJIT_R1));
+ case SLJIT_DIVMOD_SW:
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(TMP_REG1) | RJ(SLJIT_R0) | IMM_I12(0)));
+ FAIL_IF(push_inst(compiler, INST(DIV, op) | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(SLJIT_R1)));
+ return push_inst(compiler, INST(MOD, op) | RD(SLJIT_R1) | RJ(TMP_REG1) | RK(SLJIT_R1));
+ case SLJIT_DIV_UW:
+ return push_inst(compiler, ((op & SLJIT_32)? DIV_WU: DIV_DU) | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(SLJIT_R1));
+ case SLJIT_DIV_SW:
+ return push_inst(compiler, INST(DIV, op) | RD(SLJIT_R0) | RJ(SLJIT_R0) | RK(SLJIT_R1));
+ case SLJIT_MEMORY_BARRIER:
+ return push_inst(compiler, DBAR);
+ case SLJIT_ENDBR:
+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
+ return SLJIT_SUCCESS;
+ }
+
+ SLJIT_UNREACHABLE();
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 flags = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (op & SLJIT_32)
+ flags = INT_DATA | SIGNED_DATA;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, srcw);
+
+ case SLJIT_MOV_U32:
+ return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw);
+
+ case SLJIT_MOV_S32:
+ /* Logical operators have no W variant, so sign extended input is necessary for them. */
+ case SLJIT_MOV32:
+ return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s32)srcw : srcw);
+
+ case SLJIT_MOV_U8:
+ return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);
+
+ case SLJIT_MOV_S8:
+ return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);
+
+ case SLJIT_MOV_U16:
+ return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);
+
+ case SLJIT_MOV_S16:
+ return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);
+
+ case SLJIT_CLZ:
+ case SLJIT_CTZ:
+ case SLJIT_REV:
+ return emit_op(compiler, op, flags, dst, dstw, TMP_ZERO, 0, src, srcw);
+
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+ return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_ZERO, 0, src, srcw);
+
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+ return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_ZERO, 0, src, srcw);
+ }
+
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 flags = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ if (op & SLJIT_32) {
+ flags |= INT_DATA | SIGNED_DATA;
+ if (src1 == SLJIT_IMM)
+ src1w = (sljit_s32)src1w;
+ if (src2 == SLJIT_IMM)
+ src2w = (sljit_s32)src2w;
+ }
+
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD:
+ case SLJIT_ADDC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_SUB:
+ case SLJIT_SUBC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_MUL:
+ compiler->status_flags_state = 0;
+ return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_AND:
+ case SLJIT_OR:
+ case SLJIT_XOR:
+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ case SLJIT_ROTL:
+ case SLJIT_ROTR:
+ if (src2 == SLJIT_IMM) {
+ if (op & SLJIT_32)
+ src2w &= 0x1f;
+ else
+ src2w &= 0x3f;
+ }
+
+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MULADD:
+ SLJIT_SKIP_CHECKS(compiler);
+ FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));
+ return push_inst(compiler, ADD_D | RD(dst_reg) | RJ(dst_reg) | RK(TMP_REG2));
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1_reg,
+ sljit_s32 src2_reg,
+ sljit_s32 src3, sljit_sw src3w)
+{
+ sljit_s32 is_left;
+ sljit_ins ins1, ins2, ins3;
+ sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
+ sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;
+
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
+
+ is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);
+
+ if (src1_reg == src2_reg) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);
+ }
+
+ ADJUST_LOCAL_OFFSET(src3, src3w);
+
+ if (src3 == SLJIT_IMM) {
+ src3w &= bit_length - 1;
+
+ if (src3w == 0)
+ return SLJIT_SUCCESS;
+
+ if (is_left) {
+ ins1 = INST(SLLI, op) | IMM_I12(src3w);
+ src3w = bit_length - src3w;
+ ins2 = INST(SRLI, op) | IMM_I12(src3w);
+ } else {
+ ins1 = INST(SRLI, op) | IMM_I12(src3w);
+ src3w = bit_length - src3w;
+ ins2 = INST(SLLI, op) | IMM_I12(src3w);
+ }
+
+ FAIL_IF(push_inst(compiler, ins1 | RD(dst_reg) | RJ(src1_reg)));
+ FAIL_IF(push_inst(compiler, ins2 | RD(TMP_REG1) | RJ(src2_reg)));
+ return push_inst(compiler, OR | RD(dst_reg) | RJ(dst_reg) | RK(TMP_REG1));
+ }
+
+ if (src3 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w));
+ src3 = TMP_REG2;
+ } else if (dst_reg == src3) {
+ push_inst(compiler, INST(ADDI, op) | RD(TMP_REG2) | RJ(src3) | IMM_I12(0));
+ src3 = TMP_REG2;
+ }
+
+ if (is_left) {
+ ins1 = INST(SLL, op);
+ ins2 = INST(SRLI, op);
+ ins3 = INST(SRL, op);
+ } else {
+ ins1 = INST(SRL, op);
+ ins2 = INST(SLLI, op);
+ ins3 = INST(SLL, op);
+ }
+
+ FAIL_IF(push_inst(compiler, ins1 | RD(dst_reg) | RJ(src1_reg) | RK(src3)));
+
+ if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {
+ FAIL_IF(push_inst(compiler, ins2 | RD(TMP_REG1) | RJ(src2_reg) | IMM_I12(1)));
+ FAIL_IF(push_inst(compiler, XORI | RD(TMP_REG2) | RJ(src3) | IMM_I12((sljit_ins)bit_length - 1)));
+ src2_reg = TMP_REG1;
+ } else
+ FAIL_IF(push_inst(compiler, INST(SUB, op) | RD(TMP_REG2) | RJ(TMP_ZERO) | RK(src3)));
+
+ FAIL_IF(push_inst(compiler, ins3 | RD(TMP_REG1) | RJ(src2_reg) | RK(TMP_REG2)));
+ return push_inst(compiler, OR | RD(dst_reg) | RJ(dst_reg) | RK(TMP_REG1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r, tmp_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);
+
+ if (src2 == SLJIT_IMM) {
+ src2w = (sljit_sw)((sljit_uw)src2w << shift_arg);
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
+ src2 = TMP_REG2;
+ }
+
+ if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+ src1 = TMP_REG1;
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+ src1 = TMP_REG1;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(push_inst(compiler, SLLI_D | RD(tmp_r) | RJ(src2) | IMM_I12(shift_arg)));
+ FAIL_IF(push_inst(compiler, ADD_D | RD(dst_r) | RJ(src1) | RK(tmp_r)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, WORD_DATA, dst_r, dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 base = src & REG_MASK;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ switch (op) {
+ case SLJIT_FAST_RETURN:
+ if (FAST_IS_REG(src)) {
+ if (src != RETURN_ADDR_REG)
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(RETURN_ADDR_REG) | RJ(src) | IMM_I12(0)));
+ } else
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
+
+ return push_inst(compiler, JIRL | RD(TMP_ZERO) | RJ(RETURN_ADDR_REG) | IMM_I12(0));
+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
+ return SLJIT_SUCCESS;
+ case SLJIT_PREFETCH_L1:
+ case SLJIT_PREFETCH_L2:
+ case SLJIT_PREFETCH_L3:
+ case SLJIT_PREFETCH_ONCE:
+ if (SLJIT_UNLIKELY(src & OFFS_REG_MASK)) {
+ srcw &= 0x3;
+ if (SLJIT_UNLIKELY(srcw))
+ FAIL_IF(push_inst(compiler, SLLI_D | RD(TMP_REG1) | RJ(OFFS_REG(src)) | IMM_I12(srcw)));
+ FAIL_IF(push_inst(compiler, ADD_D | RD(TMP_REG1) | RJ(base) | RK(TMP_REG1)));
+ } else {
+ if (base && srcw <= I12_MAX && srcw >= I12_MIN)
+ return push_inst(compiler,PRELD | RJ(base) | IMM_I12(srcw));
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ if (base != 0)
+ FAIL_IF(push_inst(compiler, ADD_D | RD(TMP_REG1) | RJ(base) | RK(TMP_REG1)));
+ }
+ return push_inst(compiler, PRELD | RD(0) | RJ(TMP_REG1));
+ }
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ switch (op) {
+ case SLJIT_FAST_ENTER:
+ if (FAST_IS_REG(dst)) {
+ if (dst == RETURN_ADDR_REG)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, ADDI_D | RD(dst) | RJ(RETURN_ADDR_REG) | IMM_I12(0));
+ }
+
+ SLJIT_ASSERT(RETURN_ADDR_REG == TMP_REG2);
+ break;
+ case SLJIT_GET_RETURN_ADDRESS:
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw)));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
+{
+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
+
+ if (type == SLJIT_GP_REGISTER)
+ return reg_map[reg];
+
+ if (type != SLJIT_FLOAT_REGISTER && type != SLJIT_SIMD_REG_128 && type != SLJIT_SIMD_REG_256)
+ return -1;
+
+ return freg_map[reg];
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_u32 size)
+{
+ SLJIT_UNUSED_ARG(size);
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
+
+ return push_inst(compiler, *(sljit_ins*)instruction);
+}
+
+/* --------------------------------------------------------------------- */
+/* Floating point operators */
+/* --------------------------------------------------------------------- */
+#define SET_COND(cond) (sljit_ins)(cond << 15)
+
+#define COND_CUN SET_COND(0x8) /* UN */
+#define COND_CEQ SET_COND(0x4) /* EQ */
+#define COND_CUEQ SET_COND(0xc) /* UN EQ */
+#define COND_CLT SET_COND(0x2) /* LT */
+#define COND_CULT SET_COND(0xa) /* UN LT */
+#define COND_CLE SET_COND(0x6) /* LT EQ */
+#define COND_CULE SET_COND(0xe) /* UN LT EQ */
+#define COND_CNE SET_COND(0x10) /* GT LT */
+#define COND_CUNE SET_COND(0x18) /* UN GT LT */
+#define COND_COR SET_COND(0x14) /* GT LT EQ */
+
+#define FINST(inst, type) (sljit_ins)((type & SLJIT_32) ? inst##_S : inst##_D)
+#define FCD(cd) (sljit_ins)(cd & 0x7)
+#define FCJ(cj) (sljit_ins)((cj & 0x7) << 5)
+#define FCA(ca) (sljit_ins)((ca & 0x7) << 15)
+#define F_OTHER_FLAG 1
+
+#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))
+
+/* convert to inter exact toward zero */
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins inst;
+ sljit_u32 word_data = 0;
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ switch (GET_OPCODE(op))
+ {
+ case SLJIT_CONV_SW_FROM_F64:
+ word_data = 1;
+ inst = FINST(FTINTRZ_L, op);
+ break;
+ case SLJIT_CONV_S32_FROM_F64:
+ inst = FINST(FTINTRZ_W, op);
+ break;
+ default:
+ inst = BREAK;
+ SLJIT_UNREACHABLE();
+ }
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
+ src = TMP_FREG1;
+ }
+
+ FAIL_IF(push_inst(compiler, inst | FRD(TMP_FREG1) | FRJ(src)));
+ FAIL_IF(push_inst(compiler, FINST(MOVFR2GR, word_data) | RD(dst_r) | FRJ(TMP_FREG1)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, word_data ? WORD_DATA : INT_DATA, TMP_REG2, dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins inst;
+ sljit_u32 word_data = 0;
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ switch (GET_OPCODE(op))
+ {
+ case SLJIT_CONV_F64_FROM_SW:
+ word_data = 1;
+ inst = (sljit_ins)((op & SLJIT_32) ? FFINT_S_L : FFINT_D_L);
+ break;
+ case SLJIT_CONV_F64_FROM_S32:
+ inst = (sljit_ins)((op & SLJIT_32) ? FFINT_S_W : FFINT_D_W);
+ break;
+ default:
+ inst = BREAK;
+ SLJIT_UNREACHABLE();
+ }
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, (word_data ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
+ src = TMP_REG1;
+ } else if (src == SLJIT_IMM) {
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
+ srcw = (sljit_s32)srcw;
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ src = TMP_REG1;
+ }
+ FAIL_IF(push_inst(compiler, (word_data ? MOVGR2FR_D : MOVGR2FR_W) | FRD(dst_r) | RJ(src)));
+ FAIL_IF(push_inst(compiler, inst | FRD(dst_r) | FRJ(dst_r)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ return sljit_emit_fop1_conv_f64_from_w(compiler, op, dst, dstw, src, srcw);
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins inst;
+ sljit_u32 word_data = 0;
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ switch (GET_OPCODE(op))
+ {
+ case SLJIT_CONV_F64_FROM_UW:
+ word_data = 1;
+ inst = (sljit_ins)((op & SLJIT_32) ? FFINT_S_L : FFINT_D_L);
+ break;
+ case SLJIT_CONV_F64_FROM_U32:
+ inst = (sljit_ins)((op & SLJIT_32) ? FFINT_S_W : FFINT_D_W);
+ break;
+ default:
+ inst = BREAK;
+ SLJIT_UNREACHABLE();
+ }
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, (word_data ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
+ src = TMP_REG1;
+ } else if (src == SLJIT_IMM) {
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32)
+ srcw = (sljit_u32)srcw;
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ src = TMP_REG1;
+ }
+
+ if (!word_data)
+ FAIL_IF(push_inst(compiler, SRLI_W | RD(src) | RJ(src) | IMM_I12(0)));
+
+ FAIL_IF(push_inst(compiler, BLT | RJ(src) | RD(TMP_ZERO) | IMM_I16(4)));
+
+ FAIL_IF(push_inst(compiler, (word_data ? MOVGR2FR_D : MOVGR2FR_W) | FRD(dst_r) | RJ(src)));
+ FAIL_IF(push_inst(compiler, inst | FRD(dst_r) | FRJ(dst_r)));
+ FAIL_IF(push_inst(compiler, B | IMM_I26(7)));
+
+ FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG2) | RJ(src) | IMM_I12(1)));
+ FAIL_IF(push_inst(compiler, (word_data ? SRLI_D : SRLI_W) | RD(TMP_REG1) | RJ(src) | IMM_I12(1)));
+ FAIL_IF(push_inst(compiler, OR | RD(TMP_REG1) | RJ(TMP_REG1) | RK(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, INST(MOVGR2FR, (!word_data)) | FRD(dst_r) | RJ(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, inst | FRD(dst_r) | FRJ(dst_r)));
+ FAIL_IF(push_inst(compiler, FINST(FADD, op) | FRD(dst_r) | FRJ(dst_r) | FRK(dst_r)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
+ src1 = TMP_FREG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
+ src2 = TMP_FREG2;
+ }
+
+ FAIL_IF(push_inst(compiler, XOR | RD(OTHER_FLAG) | RJ(OTHER_FLAG) | RK(OTHER_FLAG)));
+
+ switch (GET_FLAG_TYPE(op)) {
+ case SLJIT_F_EQUAL:
+ case SLJIT_ORDERED_EQUAL:
+ FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CEQ | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2)));
+ break;
+ case SLJIT_F_LESS:
+ case SLJIT_ORDERED_LESS:
+ FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CLT | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2)));
+ break;
+ case SLJIT_F_GREATER:
+ case SLJIT_ORDERED_GREATER:
+ FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CLT | FCD(F_OTHER_FLAG) | FRJ(src2) | FRK(src1)));
+ break;
+ case SLJIT_UNORDERED_OR_GREATER:
+ FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CULT | FCD(F_OTHER_FLAG) | FRJ(src2) | FRK(src1)));
+ break;
+ case SLJIT_UNORDERED_OR_LESS:
+ FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CULT | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2)));
+ break;
+ case SLJIT_UNORDERED_OR_EQUAL:
+ FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CUEQ | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2)));
+ break;
+ default: /* SLJIT_UNORDERED */
+ FAIL_IF(push_inst(compiler, FINST(FCMP_COND, op) | COND_CUN | FCD(F_OTHER_FLAG) | FRJ(src1) | FRK(src2)));
+ }
+ return push_inst(compiler, MOVCF2GR | RD(OTHER_FLAG) | FCJ(F_OTHER_FLAG));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
+
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
+ op ^= SLJIT_32;
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));
+ src = dst_r;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_F64:
+ if (src != dst_r) {
+ if (!(dst & SLJIT_MEM))
+ FAIL_IF(push_inst(compiler, FINST(FMOV, op) | FRD(dst_r) | FRJ(src)));
+ else
+ dst_r = src;
+ }
+ break;
+ case SLJIT_NEG_F64:
+ FAIL_IF(push_inst(compiler, FINST(FNEG, op) | FRD(dst_r) | FRJ(src)));
+ break;
+ case SLJIT_ABS_F64:
+ FAIL_IF(push_inst(compiler, FINST(FABS, op) | FRD(dst_r) | FRJ(src)));
+ break;
+ case SLJIT_CONV_F64_FROM_F32:
+ /* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */
+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? FCVT_D_S : FCVT_S_D) | FRD(dst_r) | FRJ(src)));
+ op ^= SLJIT_32;
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 dst_r, flags = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
+
+ if (src1 & SLJIT_MEM) {
+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
+ FAIL_IF(compiler->error);
+ src1 = TMP_FREG1;
+ } else
+ flags |= SLOW_SRC1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
+ FAIL_IF(compiler->error);
+ src2 = TMP_FREG2;
+ } else
+ flags |= SLOW_SRC2;
+ }
+
+ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
+ if ((dst & SLJIT_MEM) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
+ } else {
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
+ }
+ }
+ else if (flags & SLOW_SRC1)
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
+ else if (flags & SLOW_SRC2)
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
+
+ if (flags & SLOW_SRC1)
+ src1 = TMP_FREG1;
+ if (flags & SLOW_SRC2)
+ src2 = TMP_FREG2;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD_F64:
+ FAIL_IF(push_inst(compiler, FINST(FADD, op) | FRD(dst_r) | FRJ(src1) | FRK(src2)));
+ break;
+ case SLJIT_SUB_F64:
+ FAIL_IF(push_inst(compiler, FINST(FSUB, op) | FRD(dst_r) | FRJ(src1) | FRK(src2)));
+ break;
+ case SLJIT_MUL_F64:
+ FAIL_IF(push_inst(compiler, FINST(FMUL, op) | FRD(dst_r) | FRJ(src1) | FRK(src2)));
+ break;
+ case SLJIT_DIV_F64:
+ FAIL_IF(push_inst(compiler, FINST(FDIV, op) | FRD(dst_r) | FRJ(src1) | FRK(src2)));
+ break;
+ }
+
+ if (dst_r != dst)
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 reg;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fop2r(compiler, op, dst_freg, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src2, src2w, 0, 0));
+ src2 = TMP_FREG1;
+ }
+
+ if (src1 & SLJIT_MEM) {
+ reg = (dst_freg == src2) ? TMP_FREG1 : dst_freg;
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, reg, src1, src1w, 0, 0));
+ src1 = reg;
+ }
+
+ return push_inst(compiler, FINST(FCOPYSIGN, op) | FRD(dst_freg) | FRJ(src1) | FRK(src2));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f32 value)
+{
+ union {
+ sljit_s32 imm;
+ sljit_f32 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset32(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm == 0)
+ return push_inst(compiler, MOVGR2FR_W | RJ(TMP_ZERO) | FRD(freg));
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));
+ return push_inst(compiler, MOVGR2FR_W | RJ(TMP_REG1) | FRD(freg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value)
+{
+ union {
+ sljit_sw imm;
+ sljit_f64 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset64(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm == 0)
+ return push_inst(compiler, MOVGR2FR_D | RJ(TMP_ZERO) | FRD(freg));
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));
+ return push_inst(compiler, MOVGR2FR_D | RJ(TMP_REG1) | FRD(freg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg)
+{
+ sljit_ins inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
+
+ if (GET_OPCODE(op) == SLJIT_COPY_TO_F64)
+ inst = ((op & SLJIT_32) ? MOVGR2FR_W : MOVGR2FR_D) | FRD(freg) | RJ(reg);
+ else
+ inst = ((op & SLJIT_32) ? MOVFR2GR_S : MOVFR2GR_D) | RD(reg) | FRJ(freg);
+ return push_inst(compiler, inst);
+}
+
+/* --------------------------------------------------------------------- */
+/* Conditional instructions */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_label(compiler));
+
+ if (compiler->last_label && compiler->last_label->size == compiler->size)
+ return compiler->last_label;
+
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+ PTR_FAIL_IF(!label);
+ set_label(label, compiler);
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, i;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (alignment <= SLJIT_LABEL_ALIGN_4) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);
+
+ for (i = (mask >> 2); i != 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ for (i = (buffers->size + 3) >> 2; i > 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
+static sljit_ins get_jump_instruction(sljit_s32 type)
+{
+ switch (type) {
+ case SLJIT_EQUAL:
+ return BNE | RJ(EQUAL_FLAG) | RD(TMP_ZERO);
+ case SLJIT_NOT_EQUAL:
+ return BEQ | RJ(EQUAL_FLAG) | RD(TMP_ZERO);
+ case SLJIT_LESS:
+ case SLJIT_GREATER:
+ case SLJIT_SIG_LESS:
+ case SLJIT_SIG_GREATER:
+ case SLJIT_OVERFLOW:
+ case SLJIT_CARRY:
+ case SLJIT_ATOMIC_STORED:
+ return BEQ | RJ(OTHER_FLAG) | RD(TMP_ZERO);
+ case SLJIT_GREATER_EQUAL:
+ case SLJIT_LESS_EQUAL:
+ case SLJIT_SIG_GREATER_EQUAL:
+ case SLJIT_SIG_LESS_EQUAL:
+ case SLJIT_NOT_OVERFLOW:
+ case SLJIT_NOT_CARRY:
+ case SLJIT_ATOMIC_NOT_STORED:
+ return BNE | RJ(OTHER_FLAG) | RD(TMP_ZERO);
+ case SLJIT_F_EQUAL:
+ case SLJIT_ORDERED_EQUAL:
+ case SLJIT_F_LESS:
+ case SLJIT_ORDERED_LESS:
+ case SLJIT_ORDERED_GREATER:
+ case SLJIT_UNORDERED_OR_GREATER:
+ case SLJIT_F_GREATER:
+ case SLJIT_UNORDERED_OR_LESS:
+ case SLJIT_UNORDERED_OR_EQUAL:
+ case SLJIT_UNORDERED:
+ return BEQ | RJ(OTHER_FLAG) | RD(TMP_ZERO);
+ case SLJIT_ORDERED_NOT_EQUAL:
+ case SLJIT_ORDERED_LESS_EQUAL:
+ case SLJIT_ORDERED_GREATER_EQUAL:
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:
+ case SLJIT_UNORDERED_OR_LESS_EQUAL:
+ case SLJIT_F_LESS_EQUAL:
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_ORDERED:
+ return BNE | RJ(OTHER_FLAG) | RD(TMP_ZERO);
+ default:
+ /* Not conditional branch. */
+ return 0;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
+{
+ struct sljit_jump *jump;
+ sljit_ins inst;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_jump(compiler, type));
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ type &= 0xff;
+
+ inst = get_jump_instruction(type);
+
+ if (inst != 0) {
+ PTR_FAIL_IF(push_inst(compiler, inst));
+ jump->flags |= IS_COND;
+ }
+
+ jump->addr = compiler->size;
+ inst = JIRL | RJ(TMP_REG1) | IMM_I16(0);
+
+ if (type >= SLJIT_FAST_CALL) {
+ jump->flags |= IS_CALL;
+ inst |= RD(RETURN_ADDR_REG);
+ }
+
+ PTR_FAIL_IF(push_inst(compiler, inst));
+
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += JUMP_MAX_SIZE - 1;
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types)
+{
+ SLJIT_UNUSED_ARG(arg_types);
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
+
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_jump(compiler, type);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ struct sljit_jump *jump;
+ sljit_s32 flags;
+ sljit_ins inst;
+ sljit_s32 src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
+
+ if (src1 & SLJIT_MEM) {
+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, TMP_REG1, src1, src1w, src2, src2w));
+ src1 = TMP_REG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, src2_tmp_reg, src2, src2w, 0, 0));
+ src2 = src2_tmp_reg;
+ }
+
+ if (src1 == SLJIT_IMM) {
+ if (src1w != 0) {
+ PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+ src1 = TMP_REG1;
+ }
+ else
+ src1 = TMP_ZERO;
+ }
+
+ if (src2 == SLJIT_IMM) {
+ if (src2w != 0) {
+ PTR_FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w));
+ src2 = src2_tmp_reg;
+ }
+ else
+ src2 = TMP_ZERO;
+ }
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | IS_COND));
+ type &= 0xff;
+
+ switch (type) {
+ case SLJIT_EQUAL:
+ inst = BNE | RJ(src1) | RD(src2);
+ break;
+ case SLJIT_NOT_EQUAL:
+ inst = BEQ | RJ(src1) | RD(src2);
+ break;
+ case SLJIT_LESS:
+ inst = BGEU | RJ(src1) | RD(src2);
+ break;
+ case SLJIT_GREATER_EQUAL:
+ inst = BLTU | RJ(src1) | RD(src2);
+ break;
+ case SLJIT_GREATER:
+ inst = BGEU | RJ(src2) | RD(src1);
+ break;
+ case SLJIT_LESS_EQUAL:
+ inst = BLTU | RJ(src2) | RD(src1);
+ break;
+ case SLJIT_SIG_LESS:
+ inst = BGE | RJ(src1) | RD(src2);
+ break;
+ case SLJIT_SIG_GREATER_EQUAL:
+ inst = BLT | RJ(src1) | RD(src2);
+ break;
+ case SLJIT_SIG_GREATER:
+ inst = BGE | RJ(src2) | RD(src1);
+ break;
+ case SLJIT_SIG_LESS_EQUAL:
+ inst = BLT | RJ(src2) | RD(src1);
+ break;
+ default:
+ inst = BREAK;
+ SLJIT_UNREACHABLE();
+ }
+
+ PTR_FAIL_IF(push_inst(compiler, inst));
+
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(push_inst(compiler, JIRL | RD(TMP_ZERO) | RJ(TMP_REG1) | IMM_I12(0)));
+
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += JUMP_MAX_SIZE - 1;
+
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
+{
+ struct sljit_jump *jump;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
+
+ if (src != SLJIT_IMM) {
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
+ src = TMP_REG1;
+ }
+ return push_inst(compiler, JIRL | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RJ(src) | IMM_I12(0));
+ }
+
+ /* These jumps are converted to jump/call instructions when possible. */
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF(!jump);
+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_CALL : 0));
+ jump->u.target = (sljit_uw)srcw;
+
+ jump->addr = compiler->size;
+ FAIL_IF(push_inst(compiler, JIRL | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RJ(TMP_REG1) | IMM_I12(0)));
+
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += JUMP_MAX_SIZE - 1;
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types,
+ sljit_s32 src, sljit_sw srcw)
+{
+ SLJIT_UNUSED_ARG(arg_types);
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
+ src = TMP_REG1;
+ }
+
+ if (type & SLJIT_CALL_RETURN) {
+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(src) | IMM_I12(0)));
+ src = TMP_REG1;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 0));
+ type = SLJIT_JUMP;
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, type, src, srcw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 type)
+{
+ sljit_s32 src_r, dst_r, invert;
+ sljit_s32 saved_op = op;
+ sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ op = GET_OPCODE(op);
+ dst_r = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
+ FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));
+
+ if (type < SLJIT_F_EQUAL) {
+ src_r = OTHER_FLAG;
+ invert = type & 0x1;
+
+ switch (type) {
+ case SLJIT_EQUAL:
+ case SLJIT_NOT_EQUAL:
+ FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RJ(EQUAL_FLAG) | IMM_I12(1)));
+ src_r = dst_r;
+ break;
+ case SLJIT_ATOMIC_STORED:
+ case SLJIT_ATOMIC_NOT_STORED:
+ FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RJ(OTHER_FLAG) | IMM_I12(1)));
+ src_r = dst_r;
+ invert ^= 0x1;
+ break;
+ case SLJIT_OVERFLOW:
+ case SLJIT_NOT_OVERFLOW:
+ if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {
+ src_r = OTHER_FLAG;
+ break;
+ }
+ FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RJ(OTHER_FLAG) | IMM_I12(1)));
+ src_r = dst_r;
+ invert ^= 0x1;
+ break;
+ }
+ } else {
+ invert = 0;
+ src_r = OTHER_FLAG;
+
+ switch (type) {
+ case SLJIT_ORDERED_NOT_EQUAL:
+ case SLJIT_ORDERED_LESS_EQUAL:
+ case SLJIT_ORDERED_GREATER_EQUAL:
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:
+ case SLJIT_UNORDERED_OR_LESS_EQUAL:
+ case SLJIT_F_LESS_EQUAL:
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_ORDERED:
+ invert = 1;
+ break;
+ }
+ }
+
+ if (invert) {
+ FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RJ(src_r) | IMM_I12(1)));
+ src_r = dst_r;
+ }
+
+ if (op < SLJIT_ADD) {
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, mem_type, src_r, dst, dstw);
+
+ if (src_r != dst_r)
+ return push_inst(compiler, ADDI_D | RD(dst_r) | RJ(src_r) | IMM_I12(0));
+ return SLJIT_SUCCESS;
+ }
+
+ mem_type |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE;
+
+ if (dst & SLJIT_MEM)
+ return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, src_r, 0);
+ return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, src_r, 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_reg)
+{
+ sljit_ins *ptr;
+ sljit_uw size;
+ sljit_s32 is_compare = (type & SLJIT_COMPARE_SELECT);
+ sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ if (src1 == SLJIT_IMM && type & SLJIT_32)
+ src1w = (sljit_s32)src1w;
+
+ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);
+
+ if (dst_reg != src2_reg) {
+ if (dst_reg == src1) {
+ src1 = src2_reg;
+ src1w = 0;
+ if (!is_compare)
+ type ^= 0x1;
+ } else {
+ if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
+ SLJIT_ASSERT(!(type & SLJIT_COMPARE_SELECT));
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(dst_reg) | IMM_I12(0)));
+
+ if ((src1 & REG_MASK) == dst_reg)
+ src1 = (src1 & ~REG_MASK) | TMP_REG1;
+
+ if (OFFS_REG(src1) == dst_reg)
+ src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);
+ }
+
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(dst_reg) | RJ(src2_reg) | IMM_I12(0)));
+ }
+ }
+
+ if (is_compare) {
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG3, src1, src1w));
+ } else if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG3, src1w));
+ } else
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG3) | RJ(src1) | IMM_I12(0)));
+ }
+
+ size = compiler->size;
+
+ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ compiler->size++;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w));
+ } else if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, dst_reg, src1w));
+ } else
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(dst_reg) | RJ(src1) | IMM_I12(0)));
+
+ if (is_compare) {
+ switch (type) {
+ case SLJIT_LESS:
+ case SLJIT_LESS_EQUAL:
+ *ptr = BGEU;
+ break;
+ case SLJIT_GREATER:
+ case SLJIT_GREATER_EQUAL:
+ *ptr = BLTU;
+ break;
+ case SLJIT_SIG_LESS:
+ case SLJIT_SIG_LESS_EQUAL:
+ *ptr = BGE;
+ break;
+ default:
+ *ptr = BLT;
+ break;
+ }
+
+ *ptr |= RJ(TMP_REG3) | RD(dst_reg);
+ } else {
+ *ptr = get_jump_instruction(type);
+ }
+
+ *ptr |= IMM_I16(compiler->size - size);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_freg)
+{
+ sljit_s32 invert = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ if ((type & ~SLJIT_32) == SLJIT_EQUAL || (type & ~SLJIT_32) == SLJIT_NOT_EQUAL) {
+ if ((type & ~SLJIT_32) == SLJIT_EQUAL)
+ invert = 1;
+ FAIL_IF(push_inst(compiler, MOVGR2CF | FCD(F_OTHER_FLAG) | RJ(EQUAL_FLAG)));
+ } else {
+ if (get_jump_instruction(type & ~SLJIT_32) == (BNE | RJ(OTHER_FLAG) | RD(TMP_ZERO)))
+ invert = 1;
+ FAIL_IF(push_inst(compiler, MOVGR2CF | FCD(F_OTHER_FLAG) | RJ(OTHER_FLAG)));
+ }
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, TMP_FREG2, src1, src1w));
+ if (invert)
+ return push_inst(compiler, FSEL | FRD(dst_freg) | FRJ(TMP_FREG2) | FRK(src2_freg) | FCA(F_OTHER_FLAG));
+ return push_inst(compiler, FSEL | FRD(dst_freg) | FRJ(src2_freg) | FRK(TMP_FREG2) | FCA(F_OTHER_FLAG));
+ } else {
+ if (invert)
+ return push_inst(compiler, FSEL | FRD(dst_freg) | FRJ(src1) | FRK(src2_freg) | FCA(F_OTHER_FLAG));
+ return push_inst(compiler, FSEL | FRD(dst_freg) | FRJ(src2_freg) | FRK(src1) | FCA(F_OTHER_FLAG));
+ }
+}
+
+#undef FLOAT_DATA
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_s32 flags;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
+
+ if (!(reg & REG_PAIR_MASK))
+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
+
+ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
+ memw &= 0x3;
+
+ if (SLJIT_UNLIKELY(memw != 0)) {
+ FAIL_IF(push_inst(compiler, SLLI_D | RD(TMP_REG1) | RJ(OFFS_REG(mem)) | IMM_I12(memw)));
+ FAIL_IF(push_inst(compiler, ADD_D| RD(TMP_REG1) | RJ(TMP_REG1) | RK(mem & REG_MASK)));
+ } else
+ FAIL_IF(push_inst(compiler, ADD_D| RD(TMP_REG1) | RJ(mem & REG_MASK) | RK(OFFS_REG(mem))));
+
+ mem = TMP_REG1;
+ memw = 0;
+ } else if (memw > I12_MAX - SSIZE_OF(sw) || memw < I12_MIN) {
+ if (((memw + 0x800) & 0xfff) <= 0xfff - SSIZE_OF(sw)) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, TO_ARGW_HI(memw)));
+ memw &= 0xfff;
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, memw));
+ memw = 0;
+ }
+
+ if (mem & REG_MASK)
+ FAIL_IF(push_inst(compiler, ADD_D| RD(TMP_REG1) | RJ(TMP_REG1) | RK(mem & REG_MASK)));
+
+ mem = TMP_REG1;
+ } else {
+ mem &= REG_MASK;
+ memw &= 0xfff;
+ }
+
+ SLJIT_ASSERT((memw >= 0 && memw <= I12_MAX - SSIZE_OF(sw)) || (memw > I12_MAX && memw <= 0xfff));
+
+ if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {
+ FAIL_IF(push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), (memw + SSIZE_OF(sw)) & 0xfff));
+ return push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw);
+ }
+
+ flags = WORD_DATA | (!(type & SLJIT_MEM_STORE) ? LOAD_DATA : 0);
+
+ FAIL_IF(push_mem_inst(compiler, flags, REG_PAIR_FIRST(reg), SLJIT_MEM1(mem), memw));
+ return push_mem_inst(compiler, flags, REG_PAIR_SECOND(reg), SLJIT_MEM1(mem), (memw + SSIZE_OF(sw)) & 0xfff);
+}
+
+#undef TO_ARGW_HI
+
+static sljit_s32 sljit_emit_simd_mem_offset(struct sljit_compiler *compiler, sljit_s32 *mem_ptr, sljit_sw memw)
+{
+ sljit_s32 mem = *mem_ptr;
+
+ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
+ *mem_ptr = TMP_REG3;
+ FAIL_IF(push_inst(compiler, SLLI_D | RD(TMP_REG3) | RJ(OFFS_REG(mem)) | IMM_I12(memw & 0x3)));
+ return push_inst(compiler, ADD_D | RD(TMP_REG3) | RJ(TMP_REG3) | RK(mem & REG_MASK));
+ }
+
+ if (!(mem & REG_MASK)) {
+ *mem_ptr = TMP_REG3;
+ return load_immediate(compiler, TMP_REG3, memw);
+ }
+
+ mem &= REG_MASK;
+
+ if (memw == 0) {
+ *mem_ptr = mem;
+ return SLJIT_SUCCESS;
+ }
+
+ *mem_ptr = TMP_REG3;
+
+ FAIL_IF(load_immediate(compiler, TMP_REG3, memw));
+ return push_inst(compiler, ADD_D | RD(TMP_REG3) | RJ(TMP_REG3) | RK(mem));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_ins ins = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw));
+
+ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
+
+ if (reg_size != 5 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (reg_size == 5 && !(get_cpu_features(GET_HWCAP) & LOONGARCH_HWCAP_LASX))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (!(srcdst & SLJIT_MEM)) {
+ if (type & SLJIT_SIMD_STORE)
+ ins = FRD(srcdst) | FRJ(vreg) | FRK(vreg);
+ else
+ ins = FRD(vreg) | FRJ(srcdst) | FRK(srcdst);
+
+ if (reg_size == 5)
+ ins |= VOR_V | (sljit_ins)1 << 26;
+ else
+ ins |= VOR_V;
+
+ return push_inst(compiler, ins);
+ }
+
+ ins = (type & SLJIT_SIMD_STORE) ? VST : VLD;
+
+ if (reg_size == 5)
+ ins = (type & SLJIT_SIMD_STORE) ? XVST : XVLD;
+
+ if (FAST_IS_REG(srcdst) && srcdst >= 0 && (srcdstw >= I12_MIN && srcdstw <= I12_MAX))
+ return push_inst(compiler, ins | FRD(vreg) | RJ((sljit_u8)srcdst) | IMM_I12(srcdstw));
+ else {
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));
+ return push_inst(compiler, ins | FRD(vreg) | RJ(srcdst) | IMM_I12(0));
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw));
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (reg_size != 5 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (reg_size == 5 && !(get_cpu_features(GET_HWCAP) & LOONGARCH_HWCAP_LASX))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));
+
+ if (reg_size == 5)
+ ins = (sljit_ins)1 << 25;
+
+ return push_inst(compiler, VLDREPL | ins | FRD(vreg) | RJ(src) | (sljit_ins)1 << (23 - elem_size));
+ }
+
+ if (reg_size == 5)
+ ins = (sljit_ins)1 << 26;
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (src == SLJIT_IMM)
+ return push_inst(compiler, VREPLGR2VR | ins | FRD(vreg) | RJ(TMP_ZERO) | (sljit_ins)elem_size << 10);
+
+ FAIL_IF(push_inst(compiler, VREPLVE | ins | FRD(vreg) | FRJ(src) | RK(TMP_ZERO) | (sljit_ins)elem_size << 15));
+
+ if (reg_size == 5) {
+ ins = (sljit_ins)(0x44 << 10);
+ return push_inst(compiler, XVPERMI | ins | FRD(vreg) | FRJ(vreg));
+ }
+
+ return SLJIT_SUCCESS;
+ }
+
+ ins |= VREPLGR2VR | (sljit_ins)elem_size << 10;
+
+ if (src == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, srcw));
+ src = TMP_REG2;
+ }
+
+ return push_inst(compiler, ins | FRD(vreg) | RJ(src));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg, sljit_s32 lane_index,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw));
+
+ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
+
+ if (reg_size != 5 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (reg_size == 5 && !(get_cpu_features(GET_HWCAP) & LOONGARCH_HWCAP_LASX))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (type & SLJIT_SIMD_LANE_ZERO) {
+ ins = (reg_size == 5) ? ((sljit_ins)1 << 26) : 0;
+
+ if ((type & SLJIT_SIMD_FLOAT) && vreg == srcdst) {
+ FAIL_IF(push_inst(compiler, VOR_V | ins | FRD(TMP_FREG1) | FRJ(vreg) | FRK(vreg)));
+ srcdst = TMP_FREG1;
+ srcdstw = 0;
+ }
+
+ FAIL_IF(push_inst(compiler, VXOR_V | ins | FRD(vreg) | FRJ(vreg) | FRK(vreg)));
+ }
+
+ if (srcdst & SLJIT_MEM) {
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &srcdst, srcdstw));
+
+ if (reg_size == 5)
+ ins = (sljit_ins)1 << 25;
+
+ if (type & SLJIT_SIMD_STORE) {
+ ins |= (sljit_ins)lane_index << 18 | (sljit_ins)(1 << (23 - elem_size));
+ return push_inst(compiler, VSTELM | ins | FRD(vreg) | RJ(srcdst));
+ } else {
+ emit_op_mem(compiler, (elem_size == 3 ? WORD_DATA : (elem_size == 2 ? INT_DATA : (elem_size == 1 ? HALF_DATA : BYTE_DATA))) | LOAD_DATA, TMP_REG1, srcdst | SLJIT_MEM, 0);
+ srcdst = TMP_REG1;
+ ins = (sljit_ins)(0x3f ^ (0x1f >> elem_size)) << 10;
+
+ if (reg_size == 5) {
+ if (elem_size < 2) {
+ FAIL_IF(push_inst(compiler, VOR_V | (sljit_ins)1 << 26 | FRD(TMP_FREG1) | FRJ(vreg) | FRK(vreg)));
+ if (lane_index >= (2 << (3 - elem_size))) {
+ FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(vreg) | IMM_I8(1)));
+ FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(TMP_FREG1) | RJ(srcdst) | IMM_V(lane_index % (2 << (3 - elem_size)))));
+ return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(vreg) | FRJ(TMP_FREG1) | IMM_I8(2));
+ } else {
+ FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(vreg) | RJ(srcdst) | IMM_V(lane_index)));
+ return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(vreg) | FRJ(TMP_FREG1) | IMM_I8(18));
+ }
+ } else
+ ins = (sljit_ins)(0x3f ^ (0x3f >> elem_size)) << 10 | (sljit_ins)1 << 26;
+ }
+
+ return push_inst(compiler, VINSGR2VR | ins | FRD(vreg) | RJ(srcdst) | IMM_V(lane_index));
+ }
+ }
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ ins = (reg_size == 5) ? (sljit_ins)(0x3f ^ (0x3f >> elem_size)) << 10 | (sljit_ins)1 << 26 : (sljit_ins)(0x3f ^ (0x1f >> elem_size)) << 10;
+
+ if (type & SLJIT_SIMD_STORE) {
+ FAIL_IF(push_inst(compiler, VPICKVE2GR_U | ins | RD(TMP_REG1) | FRJ(vreg) | IMM_V(lane_index)));
+ return push_inst(compiler, VINSGR2VR | ins | FRD(srcdst) | RJ(TMP_REG1) | IMM_V(0));
+ } else {
+ FAIL_IF(push_inst(compiler, VPICKVE2GR_U | ins | RD(TMP_REG1) | FRJ(srcdst) | IMM_V(0)));
+ return push_inst(compiler, VINSGR2VR | ins | FRD(vreg) | RJ(TMP_REG1) | IMM_V(lane_index));
+ }
+ }
+
+ if (srcdst == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcdstw));
+ srcdst = TMP_REG1;
+ }
+
+ if (type & SLJIT_SIMD_STORE) {
+ ins = (sljit_ins)(0x3f ^ (0x1f >> elem_size)) << 10;
+
+ if (type & SLJIT_SIMD_LANE_SIGNED)
+ ins |= (sljit_ins)(VPICKVE2GR_U ^ (0x7 << 18));
+ else
+ ins |= VPICKVE2GR_U;
+
+ if (reg_size == 5) {
+ if (elem_size < 2) {
+ if (lane_index >= (2 << (3 - elem_size))) {
+ if (type & SLJIT_SIMD_LANE_SIGNED)
+ ins |= (sljit_ins)(VPICKVE2GR_U ^ (0x7 << 18));
+ else
+ ins |= VPICKVE2GR_U;
+
+ FAIL_IF(push_inst(compiler, VOR_V | (sljit_ins)1 << 26 | FRD(TMP_FREG1) | FRJ(vreg) | FRK(vreg)));
+ FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(vreg) | IMM_I8(1)));
+ return push_inst(compiler, ins | RD(srcdst) | FRJ(TMP_FREG1) | IMM_V(lane_index % (2 << (3 - elem_size))));
+ }
+ } else {
+ ins ^= (sljit_ins)1 << (15 - elem_size);
+ ins |= (sljit_ins)1 << 26;
+ }
+ }
+
+ return push_inst(compiler, ins | RD(srcdst) | FRJ(vreg) | IMM_V(lane_index));
+ } else {
+ ins = (sljit_ins)(0x3f ^ (0x1f >> elem_size)) << 10;
+
+ if (reg_size == 5) {
+ if (elem_size < 2) {
+ FAIL_IF(push_inst(compiler, VOR_V | (sljit_ins)1 << 26 | FRD(TMP_FREG1) | FRJ(vreg) | FRK(vreg)));
+ if (lane_index >= (2 << (3 - elem_size))) {
+ FAIL_IF(push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(TMP_FREG1) | FRJ(vreg) | IMM_I8(1)));
+ FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(TMP_FREG1) | RJ(srcdst) | IMM_V(lane_index % (2 << (3 - elem_size)))));
+ return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(vreg) | FRJ(TMP_FREG1) | IMM_I8(2));
+ } else {
+ FAIL_IF(push_inst(compiler, VINSGR2VR | ins | FRD(vreg) | RJ(srcdst) | IMM_V(lane_index)));
+ return push_inst(compiler, XVPERMI | (sljit_ins)1 << 18 | FRD(vreg) | FRJ(TMP_FREG1) | IMM_I8(18));
+ }
+ } else
+ ins = (sljit_ins)(0x3f ^ (0x3f >> elem_size)) << 10 | (sljit_ins)1 << 26;
+ }
+
+ return push_inst(compiler, VINSGR2VR | ins | FRD(vreg) | RJ(srcdst) | IMM_V(lane_index));
+ }
+
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_s32 src_lane_index)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index));
+
+ if (reg_size != 5 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (reg_size == 5 && !(get_cpu_features(GET_HWCAP) & LOONGARCH_HWCAP_LASX))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ ins = (sljit_ins)(0x3f ^ (0x1f >> elem_size)) << 10;
+
+ if (reg_size == 5) {
+ FAIL_IF(push_inst(compiler, VREPLVEI | (sljit_ins)1 << 26 | ins | FRD(vreg) | FRJ(src) | IMM_V(src_lane_index % (2 << (3 - elem_size)))));
+
+ ins = (src_lane_index < (2 << (3 - elem_size))) ? (sljit_ins)(0x44 << 10) : (sljit_ins)(0xee << 10);
+
+ return push_inst(compiler, XVPERMI | ins | FRD(vreg) | FRJ(vreg));
+ }
+
+ return push_inst(compiler, VREPLVEI | ins | FRD(vreg) | FRJ(src) | IMM_V(src_lane_index));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);
+ sljit_ins ins = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw));
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (reg_size != 5 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (reg_size == 5 && !(get_cpu_features(GET_HWCAP) & LOONGARCH_HWCAP_LASX))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (src & SLJIT_MEM) {
+ ins = (type & SLJIT_SIMD_STORE) ? VST : VLD;
+
+ if (reg_size == 5)
+ ins = (type & SLJIT_SIMD_STORE) ? XVST : XVLD;
+
+ if (FAST_IS_REG(src) && src >= 0 && (srcw >= I12_MIN && srcw <= I12_MAX))
+ FAIL_IF(push_inst(compiler, ins | FRD(vreg) | RJ(src) | IMM_I12(srcw)));
+ else {
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src, srcw));
+ FAIL_IF(push_inst(compiler, ins | FRD(vreg) | RJ(src) | IMM_I12(0)));
+ }
+ src = vreg;
+ }
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (elem_size != 2 || elem2_size != 3)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ ins = 0;
+ if (reg_size == 5) {
+ ins = (sljit_ins)1 << 26;
+ FAIL_IF(push_inst(compiler, XVPERMI | FRD(src) | FRJ(src) | IMM_I8(16)));
+ }
+
+ return push_inst(compiler, VFCVTL_D_S | ins | FRD(vreg) | FRJ(src));
+ }
+
+ ins = (type & SLJIT_SIMD_EXTEND_SIGNED) ? VSLLWIL : (VSLLWIL | (sljit_ins)1 << 18);
+
+ if (reg_size == 5)
+ ins |= (sljit_ins)1 << 26;
+
+ do {
+ if (reg_size == 5)
+ FAIL_IF(push_inst(compiler, XVPERMI | FRD(src) | FRJ(src) | IMM_I8(16)));
+
+ FAIL_IF(push_inst(compiler, ins | ((sljit_ins)1 << (13 + elem_size)) | FRD(vreg) | FRJ(src)));
+ src = vreg;
+ } while (++elem_size < elem2_size);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins = 0;
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw));
+
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ if (reg_size != 5 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (reg_size == 5 && !(get_cpu_features(GET_HWCAP) & LOONGARCH_HWCAP_LASX))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (elem_size > 3 || ((type & SLJIT_SIMD_FLOAT) && elem_size < 2))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (reg_size == 5)
+ ins = (sljit_ins)1 << 26;
+
+ FAIL_IF(push_inst(compiler, VMSKLTZ | ins | (sljit_ins)(elem_size << 10) | FRD(TMP_FREG1) | FRJ(vreg)));
+
+ FAIL_IF(push_inst(compiler, VPICKVE2GR_U | (sljit_ins)(0x3c << 10) | RD(dst_r) | FRJ(TMP_FREG1)));
+
+ if (reg_size == 5) {
+ FAIL_IF(push_inst(compiler, VPICKVE2GR_U | (sljit_ins)(0x38 << 10) | ins | RD(TMP_REG3) | FRJ(TMP_FREG1) | IMM_V(2)));
+ FAIL_IF(push_inst(compiler, SLLI_W | RD(TMP_REG3) | RJ(TMP_REG3) | IMM_I12(2 << (3 - elem_size))));
+ FAIL_IF(push_inst(compiler, OR | RD(dst_r) | RJ(dst_r) | RK(TMP_REG3)));
+ }
+
+ if (dst_r == TMP_REG2)
+ return emit_op_mem(compiler, ((type & SLJIT_32) ? INT_DATA : WORD_DATA), TMP_REG2, dst, dstw);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ if (reg_size != 5 && reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (reg_size == 5 && !(get_cpu_features(GET_HWCAP) & LOONGARCH_HWCAP_LASX))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(sljit_emit_simd_mem_offset(compiler, &src2, src2w));
+ FAIL_IF(push_inst(compiler, (reg_size == 4 ? VLD : XVLD) | FRD(TMP_FREG1) | RJ(src2) | IMM_I12(0)));
+ src2 = TMP_FREG1;
+ }
+
+ switch (SLJIT_SIMD_GET_OPCODE(type)) {
+ case SLJIT_SIMD_OP2_AND:
+ ins = VAND_V;
+ break;
+ case SLJIT_SIMD_OP2_OR:
+ ins = VOR_V;
+ break;
+ case SLJIT_SIMD_OP2_XOR:
+ ins = VXOR_V;
+ break;
+ case SLJIT_SIMD_OP2_SHUFFLE:
+ if (reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ return push_inst(compiler, VSHUF_B | FRD(dst_vreg) | FRJ(src1_vreg) | FRK(src1_vreg) | FRA(src2));
+ }
+
+ if (reg_size == 5)
+ ins |= (sljit_ins)1 << 26;
+
+ return push_inst(compiler, ins | FRD(dst_vreg) | FRJ(src1_vreg) | FRK(src2));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler,
+ sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 mem_reg)
+{
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));
+
+ if ((op & SLJIT_ATOMIC_USE_LS) || !LOONGARCH_SUPPORT_AMCAS) {
+ if (op & SLJIT_ATOMIC_USE_CAS)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ ins = LL_D;
+ break;
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ ins = LL_W;
+ break;
+
+ default:
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, ins | RD(dst_reg) | RJ(mem_reg));
+ }
+
+ switch(GET_OPCODE(op)) {
+ case SLJIT_MOV_S8:
+ ins = LD_B;
+ break;
+ case SLJIT_MOV_U8:
+ ins = LD_BU;
+ break;
+ case SLJIT_MOV_S16:
+ ins = LD_H;
+ break;
+ case SLJIT_MOV_U16:
+ ins = LD_HU;
+ break;
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ ins = LD_W;
+ break;
+ case SLJIT_MOV_U32:
+ ins = LD_WU;
+ break;
+ default:
+ ins = LD_D;
+ break;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, ins | RD(dst_reg) | RJ(mem_reg) | IMM_I12(0));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler,
+ sljit_s32 op,
+ sljit_s32 src_reg,
+ sljit_s32 mem_reg,
+ sljit_s32 temp_reg)
+{
+ sljit_ins ins = 0;
+ sljit_ins unsign = 0;
+ sljit_s32 tmp = temp_reg;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));
+
+ if ((op & SLJIT_ATOMIC_USE_LS) || !LOONGARCH_SUPPORT_AMCAS) {
+ if (op & SLJIT_ATOMIC_USE_CAS)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ ins = SC_D;
+ break;
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ ins = SC_W;
+ break;
+
+ default:
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst(compiler, ADD_D | RD(OTHER_FLAG) | RJ(src_reg) | RK(TMP_ZERO)));
+ return push_inst(compiler, ins | RD(OTHER_FLAG) | RJ(mem_reg));
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_S8:
+ ins = AMCAS_B;
+ break;
+ case SLJIT_MOV_U8:
+ ins = AMCAS_B;
+ unsign = BSTRPICK_D | (7 << 16);
+ break;
+ case SLJIT_MOV_S16:
+ ins = AMCAS_H;
+ break;
+ case SLJIT_MOV_U16:
+ ins = AMCAS_H;
+ unsign = BSTRPICK_D | (15 << 16);
+ break;
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ ins = AMCAS_W;
+ break;
+ case SLJIT_MOV_U32:
+ ins = AMCAS_W;
+ unsign = BSTRPICK_D | (31 << 16);
+ break;
+ default:
+ ins = AMCAS_D;
+ break;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ if (op & SLJIT_SET_ATOMIC_STORED) {
+ FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG3) | RJ(temp_reg) | RK(TMP_ZERO)));
+ tmp = TMP_REG3;
+ }
+ FAIL_IF(push_inst(compiler, ins | RD(tmp) | RJ(mem_reg) | RK(src_reg)));
+ if (!(op & SLJIT_SET_ATOMIC_STORED))
+ return SLJIT_SUCCESS;
+
+ if (unsign)
+ FAIL_IF(push_inst(compiler, unsign | RD(tmp) | RJ(tmp)));
+
+ FAIL_IF(push_inst(compiler, XOR | RD(OTHER_FLAG) | RJ(tmp) | RK(temp_reg)));
+ return push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RJ(OTHER_FLAG) | IMM_I12(1));
+}
+
+static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins)
+{
+ SLJIT_UNUSED_ARG(last_ins);
+
+ FAIL_IF(push_inst(compiler, LU12I_W | RD(dst) | (sljit_ins)(((init_value & 0xffffffff) >> 12) << 5)));
+ FAIL_IF(push_inst(compiler, LU32I_D | RD(dst) | (sljit_ins)(((init_value >> 32) & 0xfffff) << 5)));
+ FAIL_IF(push_inst(compiler, LU52I_D | RD(dst) | RJ(dst) | (sljit_ins)(IMM_I12(init_value >> 52))));
+ return push_inst(compiler, ORI | RD(dst) | RJ(dst) | IMM_I12(init_value));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
+{
+ sljit_ins *inst = (sljit_ins*)addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);
+
+ SLJIT_ASSERT((inst[0] & OPC_1RI20(0x7f)) == LU12I_W);
+ inst[0] = (inst[0] & (OPC_1RI20(0x7f) | 0x1f)) | (sljit_ins)(((new_target & 0xffffffff) >> 12) << 5);
+
+ SLJIT_ASSERT((inst[1] & OPC_1RI20(0x7f)) == LU32I_D);
+ inst[1] = (inst[1] & (OPC_1RI20(0x7f) | 0x1f)) | (sljit_ins)(sljit_ins)(((new_target >> 32) & 0xfffff) << 5);
+
+ SLJIT_ASSERT((inst[2] & OPC_2RI12(0x3ff)) == LU52I_D);
+ inst[2] = (inst[2] & (OPC_2RI12(0x3ff) | 0x3ff)) | IMM_I12(new_target >> 52);
+
+ SLJIT_ASSERT((inst[3] & OPC_2RI12(0x3ff)) == ORI || (inst[3] & OPC_2RI16(0x3f)) == JIRL);
+ if ((inst[3] & OPC_2RI12(0x3ff)) == ORI)
+ inst[3] = (inst[3] & (OPC_2RI12(0x3ff) | 0x3ff)) | IMM_I12(new_target);
+ else
+ inst[3] = (inst[3] & (OPC_2RI16(0x3f) | 0x3ff)) | IMM_I12((new_target & 0xfff) >> 2);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);
+
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 4);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
+{
+ struct sljit_const *const_;
+ sljit_s32 dst_r;
+ sljit_s32 mem_flags = WORD_DATA;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+ PTR_FAIL_IF(!const_);
+ set_const(const_, compiler);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ if (init_value & 0x100)
+ init_value |= 0xf00;
+ else
+ init_value &= 0xff;
+
+ PTR_FAIL_IF(push_inst(compiler, ADDI_D | RD(dst_r) | RJ(TMP_ZERO) | IMM_I12(init_value)));
+ mem_flags = BYTE_DATA;
+ break;
+
+ case SLJIT_MOV32:
+ mem_flags = INT_DATA;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_S32:
+ PTR_FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)((init_value >> 7) & 0x1ffffe0)));
+ PTR_FAIL_IF(push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(init_value)));
+ break;
+
+ default:
+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, 0));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, dst, dstw));
+
+ return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_jump *jump;
+ sljit_s32 dst_r, target_r;
+ SLJIT_UNUSED_ARG(op);
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = TMP_REG1;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, dst, dstw));
+ }
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_mov_addr(jump, compiler, 0);
+
+ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)target_r));
+
+ compiler->size += JUMP_MAX_SIZE - 1;
+
+ if (op == SLJIT_ADD_ABS_ADDR)
+ PTR_FAIL_IF(push_inst(compiler, ADD_D | RD(dst_r) | RJ(dst_r) | RK(TMP_REG1)));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
+
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
+{
+ sljit_ins* inst;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ inst = (sljit_ins*)addr;
+ SLJIT_ASSERT((inst[0] & OPC_2RI12(0xb)) == ADDI_D);
+
+ if (new_constant & 0x100)
+ new_constant |= 0xf00;
+ else
+ new_constant &= 0xff;
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
+ inst[0] = (inst[0] & 0xffc003ff) | (sljit_ins)((new_constant & 0xfff) << 10);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
+ return;
+
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & OPC_1RI20(0xa)) == LU12I_W && (inst[1] & OPC_2RI12(0xe)) == ORI);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ inst[0] = (inst[0] & (OPC_1RI20(0xa) | 0x1f)) | (sljit_ins)((new_constant >> 7) & 0x1ffffe0);
+ inst[1] = (inst[1] & (OPC_2RI12(0xe) | 0x3ff)) | (sljit_ins)((new_constant & 0xfff) << 10);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ return;
+
+ default:
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ return;
+ }
+}
diff --git a/deps/sljit/sljit_src/sljitNativeMIPS_32.c b/deps/sljit/sljit_src/sljitNativeMIPS_32.c
new file mode 100644
index 0000000..8397961
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativeMIPS_32.c
@@ -0,0 +1,467 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* mips 32-bit arch dependent functions. */
+
+static sljit_s32 emit_copysign(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_sw src1, sljit_sw src2, sljit_sw dst)
+{
+ int is_32 = (op & SLJIT_32);
+ sljit_ins mfhc = MFC1, mthc = MTC1;
+ sljit_ins src1_r = FS(src1), src2_r = FS(src2), dst_r = FS(dst);
+
+ if (!is_32) {
+ switch (cpu_feature_list & CPU_FEATURE_FR) {
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+ case CPU_FEATURE_FR:
+ mfhc = MFHC1;
+ mthc = MTHC1;
+ break;
+#endif /* SLJIT_MIPS_REV >= 2 */
+ default:
+ src1_r |= (1 << 11);
+ src2_r |= (1 << 11);
+ dst_r |= (1 << 11);
+ break;
+ }
+ }
+
+ FAIL_IF(push_inst(compiler, mfhc | T(TMP_REG1) | src1_r, DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, mfhc | T(TMP_REG2) | src2_r, DR(TMP_REG2)));
+ if (!is_32 && src1 != dst)
+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(src1) | FD(dst), MOVABLE_INS));
+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
+ else
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* MIPS III */
+ FAIL_IF(push_inst(compiler, XOR | T(TMP_REG1) | D(TMP_REG2) | S(TMP_REG2), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, SRL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, SLL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, XOR | T(TMP_REG2) | D(TMP_REG1) | S(TMP_REG1), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, mthc | T(TMP_REG1) | dst_r, MOVABLE_INS));
+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
+ if (mthc == MTC1)
+ return push_inst(compiler, NOP, UNMOVABLE_INS);
+#endif /* MIPS III */
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
+{
+ if (!(imm & ~0xffff))
+ return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
+
+ if (imm < 0 && imm >= SIMM_MIN)
+ return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
+
+ FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
+ return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
+{
+ FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst)));
+ return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value)
+{
+ union {
+ struct {
+#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN
+ sljit_s32 lo;
+ sljit_s32 hi;
+#else /* !SLJIT_LITTLE_ENDIAN */
+ sljit_s32 hi;
+ sljit_s32 lo;
+#endif /* SLJIT_LITTLE_ENDIAN */
+ } bin;
+ sljit_f64 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset64(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.bin.lo != 0)
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.bin.lo));
+ if (u.bin.hi != 0)
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG2), u.bin.hi));
+
+ FAIL_IF(push_inst(compiler, MTC1 | (u.bin.lo != 0 ? T(TMP_REG1) : TA(0)) | FS(freg), MOVABLE_INS));
+ switch (cpu_feature_list & CPU_FEATURE_FR) {
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+ case CPU_FEATURE_FR:
+ return push_inst(compiler, MTHC1 | (u.bin.hi != 0 ? T(TMP_REG2) : TA(0)) | FS(freg), MOVABLE_INS);
+#endif /* SLJIT_MIPS_REV >= 2 */
+ default:
+ FAIL_IF(push_inst(compiler, MTC1 | (u.bin.hi != 0 ? T(TMP_REG2) : TA(0)) | FS(freg) | (1 << 11), MOVABLE_INS));
+ break;
+ }
+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* MIPS III */
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg)
+{
+ sljit_s32 reg2 = 0;
+ sljit_ins inst = FS(freg);
+ sljit_ins mthc = MTC1, mfhc = MFC1;
+ int is_32 = (op & SLJIT_32);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
+
+ op = GET_OPCODE(op);
+ if (reg & REG_PAIR_MASK) {
+ reg2 = REG_PAIR_SECOND(reg);
+ reg = REG_PAIR_FIRST(reg);
+
+ inst |= T(reg2);
+
+ if (op == SLJIT_COPY_TO_F64)
+ FAIL_IF(push_inst(compiler, MTC1 | inst, MOVABLE_INS));
+ else
+ FAIL_IF(push_inst(compiler, MFC1 | inst, DR(reg2)));
+
+ inst = FS(freg) | (1 << 11);
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+ if (cpu_feature_list & CPU_FEATURE_FR) {
+ mthc = MTHC1;
+ mfhc = MFHC1;
+ inst = FS(freg);
+ }
+#endif /* SLJIT_MIPS_REV >= 2 */
+ }
+
+ inst |= T(reg);
+ if (!is_32 && !reg2) {
+ switch (cpu_feature_list & CPU_FEATURE_FR) {
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+ case CPU_FEATURE_FR:
+ mthc = MTHC1;
+ mfhc = MFHC1;
+ break;
+#endif /* SLJIT_MIPS_REV >= 2 */
+ default:
+ inst |= (1 << 11);
+ break;
+ }
+ }
+
+ if (op == SLJIT_COPY_TO_F64)
+ FAIL_IF(push_inst(compiler, mthc | inst, MOVABLE_INS));
+ else
+ FAIL_IF(push_inst(compiler, mfhc | inst, DR(reg)));
+
+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
+ if (mthc == MTC1 || mfhc == MFC1)
+ return push_inst(compiler, NOP, UNMOVABLE_INS);
+#endif /* MIPS III */
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
+{
+ sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_target >> 16);
+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_target);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+}
+
+static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr, sljit_u32 *extra_space)
+{
+ sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;
+ sljit_u32 offset = 0;
+ sljit_s32 float_arg_count = 0;
+ sljit_s32 word_arg_count = 0;
+ sljit_s32 types = 0;
+ sljit_ins prev_ins = NOP;
+ sljit_ins ins = NOP;
+ sljit_u8 offsets[4];
+ sljit_u8 *offsets_ptr = offsets;
+#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN
+ sljit_ins f64_hi = TA(7), f64_lo = TA(6);
+#else
+ sljit_ins f64_hi = TA(6), f64_lo = TA(7);
+#endif /* SLJIT_LITTLE_ENDIAN */
+
+ SLJIT_ASSERT(reg_map[TMP_REG2] == 4 && freg_map[TMP_FREG1] == 12);
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ /* See ABI description in sljit_emit_enter. */
+
+ while (arg_types) {
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
+ *offsets_ptr = (sljit_u8)offset;
+
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset & 0x7) {
+ offset += sizeof(sljit_sw);
+ *offsets_ptr = (sljit_u8)offset;
+ }
+
+ if (word_arg_count == 0 && float_arg_count <= 1)
+ *offsets_ptr = (sljit_u8)(254 + float_arg_count);
+
+ offset += sizeof(sljit_f64);
+ float_arg_count++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (word_arg_count == 0 && float_arg_count <= 1)
+ *offsets_ptr = (sljit_u8)(254 + float_arg_count);
+
+ offset += sizeof(sljit_f32);
+ float_arg_count++;
+ break;
+ default:
+ offset += sizeof(sljit_sw);
+ word_arg_count++;
+ break;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ offsets_ptr++;
+ }
+
+ /* Stack is aligned to 16 bytes. */
+ SLJIT_ASSERT(offset <= 8 * sizeof(sljit_sw));
+
+ if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {
+ if (is_tail_call) {
+ offset = (offset + sizeof(sljit_sw) + 15) & ~(sljit_uw)0xf;
+ FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset, &prev_ins));
+ *extra_space = offset;
+ } else {
+ FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-16), DR(SLJIT_SP)));
+ *extra_space = 16;
+ }
+ } else {
+ if (is_tail_call)
+ FAIL_IF(emit_stack_frame_release(compiler, 0, &prev_ins));
+ *extra_space = 0;
+ }
+
+ while (types) {
+ --offsets_ptr;
+
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (*offsets_ptr < 4 * sizeof(sljit_sw)) {
+ if (prev_ins != NOP)
+ FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
+
+ /* Must be preceded by at least one other argument,
+ * and its starting offset must be 8 because of alignment. */
+ SLJIT_ASSERT((*offsets_ptr >> 2) == 2);
+ switch (cpu_feature_list & CPU_FEATURE_FR) {
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+ case CPU_FEATURE_FR:
+ prev_ins = MFHC1 | f64_hi | FS(float_arg_count);
+ break;
+#endif /* SLJIT_MIPS_REV >= 2 */
+ default:
+ prev_ins = MFC1 | f64_hi | FS(float_arg_count) | (1 << 11);
+ break;
+ }
+ ins = MFC1 | f64_lo | FS(float_arg_count);
+ } else if (*offsets_ptr < 254)
+ ins = SDC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr);
+ else if (*offsets_ptr == 254)
+ ins = MOV_fmt(FMT_D) | FS(SLJIT_FR0) | FD(TMP_FREG1);
+
+ float_arg_count--;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (*offsets_ptr < 4 * sizeof (sljit_sw))
+ ins = MFC1 | TA(4 + (*offsets_ptr >> 2)) | FS(float_arg_count);
+ else if (*offsets_ptr < 254)
+ ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr);
+ else if (*offsets_ptr == 254)
+ ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1);
+
+ float_arg_count--;
+ break;
+ default:
+ if (*offsets_ptr >= 4 * sizeof (sljit_sw))
+ ins = SW | S(SLJIT_SP) | T(word_arg_count) | IMM(*offsets_ptr);
+ else if ((*offsets_ptr >> 2) != word_arg_count - 1)
+ ins = ADDU | S(word_arg_count) | TA(0) | DA(4 + (*offsets_ptr >> 2));
+ else if (*offsets_ptr == 0)
+ ins = ADDU | S(SLJIT_R0) | TA(0) | DA(4);
+
+ word_arg_count--;
+ break;
+ }
+
+ if (ins != NOP) {
+ if (prev_ins != NOP)
+ FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
+ prev_ins = ins;
+ ins = NOP;
+ }
+
+ types >>= SLJIT_ARG_SHIFT;
+ }
+
+ *ins_ptr = prev_ins;
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types)
+{
+ struct sljit_jump *jump;
+ sljit_u32 extra_space = 0;
+ sljit_ins ins = NOP;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
+ extra_space = (sljit_u32)type;
+ PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
+ } else if (type & SLJIT_CALL_RETURN)
+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
+
+ SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25);
+
+ if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)
+ jump->flags |= IS_MOVABLE;
+
+ if (!(type & SLJIT_CALL_RETURN) || extra_space > 0) {
+ jump->flags |= IS_JAL;
+
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)
+ jump->flags |= IS_CALL;
+
+ PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ } else
+ PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
+
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
+
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += 2;
+
+ if (extra_space == 0)
+ return jump;
+
+ if (type & SLJIT_CALL_RETURN)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG,
+ SLJIT_MEM1(SLJIT_SP), (sljit_sw)(extra_space - sizeof(sljit_sw))));
+
+ if (type & SLJIT_CALL_RETURN)
+ PTR_FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
+
+ PTR_FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(extra_space),
+ (type & SLJIT_CALL_RETURN) ? UNMOVABLE_INS : DR(SLJIT_SP)));
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u32 extra_space = (sljit_u32)type;
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
+ src = PIC_ADDR_REG;
+ srcw = 0;
+ }
+
+ if ((type & 0xff) == SLJIT_CALL_REG_ARG) {
+ if (type & SLJIT_CALL_RETURN) {
+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
+ src = PIC_ADDR_REG;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
+
+ if (ins != NOP)
+ FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, type, src, srcw);
+ }
+
+ SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25);
+
+ if (src == SLJIT_IMM)
+ FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
+ else if (src != PIC_ADDR_REG)
+ FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
+
+ FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
+
+ /* Register input. */
+ if (!(type & SLJIT_CALL_RETURN) || extra_space > 0)
+ FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ else
+ FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
+
+ if (extra_space == 0)
+ return SLJIT_SUCCESS;
+
+ if (type & SLJIT_CALL_RETURN)
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG,
+ SLJIT_MEM1(SLJIT_SP), (sljit_sw)(extra_space - sizeof(sljit_sw))));
+
+ if (type & SLJIT_CALL_RETURN)
+ FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
+
+ return push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(extra_space),
+ (type & SLJIT_CALL_RETURN) ? UNMOVABLE_INS : DR(SLJIT_SP));
+}
diff --git a/deps/sljit/sljit_src/sljitNativeMIPS_64.c b/deps/sljit/sljit_src/sljitNativeMIPS_64.c
new file mode 100644
index 0000000..965931b
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativeMIPS_64.c
@@ -0,0 +1,382 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* mips 64-bit arch dependent functions. */
+
+static sljit_s32 emit_copysign(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_s32 src2, sljit_s32 dst)
+{
+ FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | T(TMP_REG1) | FS(src1), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | T(TMP_REG2) | FS(src2), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, XOR | S(TMP_REG2) | T(TMP_REG1) | D(TMP_REG2), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | T(TMP_REG2) | D(TMP_REG1), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DMTC1, MTC1) | T(TMP_REG1) | FS(dst), MOVABLE_INS));
+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
+ if (!(op & SLJIT_32))
+ return push_inst(compiler, NOP, UNMOVABLE_INS);
+#endif /* MIPS III */
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
+{
+ sljit_s32 shift = 32;
+ sljit_s32 shift2;
+ sljit_s32 inv = 0;
+ sljit_ins ins;
+ sljit_uw uimm;
+
+ if (!(imm & ~0xffff))
+ return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
+
+ if (imm < 0 && imm >= SIMM_MIN)
+ return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
+
+ if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
+ FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
+ return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
+ }
+
+ /* Zero extended number. */
+ uimm = (sljit_uw)imm;
+ if (imm < 0) {
+ uimm = ~(sljit_uw)imm;
+ inv = 1;
+ }
+
+ while (!(uimm & 0xff00000000000000l)) {
+ shift -= 8;
+ uimm <<= 8;
+ }
+
+ if (!(uimm & 0xf000000000000000l)) {
+ shift -= 4;
+ uimm <<= 4;
+ }
+
+ if (!(uimm & 0xc000000000000000l)) {
+ shift -= 2;
+ uimm <<= 2;
+ }
+
+ if ((sljit_sw)uimm < 0) {
+ uimm >>= 1;
+ shift += 1;
+ }
+ SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32));
+
+ if (inv)
+ uimm = ~uimm;
+
+ FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
+ if (uimm & 0x0000ffff00000000l)
+ FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar));
+
+ imm &= (1l << shift) - 1;
+ if (!(imm & ~0xffff)) {
+ ins = (shift == 32) ? DSLL32 : DSLL;
+ if (shift < 32)
+ ins |= SH_IMM(shift);
+ FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar));
+ return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
+ }
+
+ /* Double shifts needs to be performed. */
+ uimm <<= 32;
+ shift2 = shift - 16;
+
+ while (!(uimm & 0xf000000000000000l)) {
+ shift2 -= 4;
+ uimm <<= 4;
+ }
+
+ if (!(uimm & 0xc000000000000000l)) {
+ shift2 -= 2;
+ uimm <<= 2;
+ }
+
+ if (!(uimm & 0x8000000000000000l)) {
+ shift2--;
+ uimm <<= 1;
+ }
+
+ SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16));
+
+ FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar));
+ FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
+ FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar));
+
+ imm &= (1l << shift2) - 1;
+ return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
+}
+
+static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
+{
+ FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst)));
+ FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst)));
+ FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
+ FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst)));
+ FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
+ return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value)
+{
+ union {
+ sljit_sw imm;
+ sljit_f64 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset64(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm == 0) {
+ FAIL_IF(push_inst(compiler, DMTC1 | TA(0) | FS(freg), MOVABLE_INS));
+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* MIPS III */
+ return SLJIT_SUCCESS;
+ }
+
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.imm));
+ FAIL_IF(push_inst(compiler, DMTC1 | T(TMP_REG1) | FS(freg), MOVABLE_INS));
+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* MIPS III */
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg)
+{
+ sljit_ins inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
+
+ inst = T(reg) | FS(freg);
+
+ if (GET_OPCODE(op) == SLJIT_COPY_TO_F64)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DMTC1, MTC1) | inst, MOVABLE_INS));
+ else
+ FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | inst, DR(reg)));
+
+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
+ if (!(op & SLJIT_32))
+ return push_inst(compiler, NOP, UNMOVABLE_INS);
+#endif /* MIPS III */
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
+{
+ sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 0);
+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_target >> 48);
+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_target >> 32);
+ inst[3] = (inst[3] & 0xffff0000) | IMM(new_target >> 16);
+ inst[5] = (inst[5] & 0xffff0000) | IMM(new_target);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 6);
+}
+
+static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)
+{
+ sljit_s32 arg_count = 0;
+ sljit_s32 word_arg_count = 0;
+ sljit_s32 float_arg_count = 0;
+ sljit_s32 types = 0;
+ sljit_ins prev_ins = *ins_ptr;
+ sljit_ins ins = NOP;
+
+ SLJIT_ASSERT(reg_map[TMP_REG2] == 4 && freg_map[TMP_FREG1] == 12);
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ while (arg_types) {
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
+
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ case SLJIT_ARG_TYPE_F32:
+ arg_count++;
+ float_arg_count++;
+ break;
+ default:
+ arg_count++;
+ word_arg_count++;
+ break;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ while (types) {
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (arg_count != float_arg_count)
+ ins = MOV_fmt(FMT_D) | FS(float_arg_count) | FD(arg_count);
+ else if (arg_count == 1)
+ ins = MOV_fmt(FMT_D) | FS(SLJIT_FR0) | FD(TMP_FREG1);
+ arg_count--;
+ float_arg_count--;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (arg_count != float_arg_count)
+ ins = MOV_fmt(FMT_S) | FS(float_arg_count) | FD(arg_count);
+ else if (arg_count == 1)
+ ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1);
+ arg_count--;
+ float_arg_count--;
+ break;
+ default:
+ if (arg_count != word_arg_count)
+ ins = DADDU | S(word_arg_count) | TA(0) | D(arg_count);
+ else if (arg_count == 1)
+ ins = DADDU | S(SLJIT_R0) | TA(0) | DA(4);
+ arg_count--;
+ word_arg_count--;
+ break;
+ }
+
+ if (ins != NOP) {
+ if (prev_ins != NOP)
+ FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
+ prev_ins = ins;
+ ins = NOP;
+ }
+
+ types >>= SLJIT_ARG_SHIFT;
+ }
+
+ *ins_ptr = prev_ins;
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types)
+{
+ struct sljit_jump *jump;
+ sljit_ins ins = NOP;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+
+ if (type & SLJIT_CALL_RETURN)
+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
+
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)
+ PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
+
+ SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25);
+
+ if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)
+ jump->flags |= IS_MOVABLE;
+
+ if (!(type & SLJIT_CALL_RETURN)) {
+ jump->flags |= IS_JAL;
+
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)
+ jump->flags |= IS_CALL;
+
+ PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ } else
+ PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
+
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
+
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += 6;
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins ins = NOP;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
+ src = PIC_ADDR_REG;
+ srcw = 0;
+ }
+
+ if ((type & 0xff) == SLJIT_CALL_REG_ARG) {
+ if (type & SLJIT_CALL_RETURN) {
+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
+ src = PIC_ADDR_REG;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
+
+ if (ins != NOP)
+ FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, type, src, srcw);
+ }
+
+ SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG1);
+
+ if (src == SLJIT_IMM)
+ FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
+ else if (src != PIC_ADDR_REG)
+ FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
+
+ if (type & SLJIT_CALL_RETURN)
+ FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
+
+ FAIL_IF(call_with_args(compiler, arg_types, &ins));
+
+ /* Register input. */
+ if (!(type & SLJIT_CALL_RETURN))
+ FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ else
+ FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
+ return push_inst(compiler, ins, UNMOVABLE_INS);
+}
diff --git a/deps/sljit/sljit_src/sljitNativeMIPS_common.c b/deps/sljit/sljit_src/sljitNativeMIPS_common.c
new file mode 100644
index 0000000..96fa342
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativeMIPS_common.c
@@ -0,0 +1,4597 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* Latest MIPS architecture. */
+
+#ifdef HAVE_PRCTL
+#include
+#endif
+
+#if !defined(__mips_hard_float) || defined(__mips_single_float)
+/* Disable automatic detection, covers both -msoft-float and -mno-float */
+#define SLJIT_IS_FPU_AVAILABLE 0
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
+{
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ return "MIPS32-R6" SLJIT_CPUINFO;
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ return "MIPS64-R6" SLJIT_CPUINFO;
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 5)
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ return "MIPS32-R5" SLJIT_CPUINFO;
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ return "MIPS64-R5" SLJIT_CPUINFO;
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ return "MIPS32-R2" SLJIT_CPUINFO;
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ return "MIPS64-R2" SLJIT_CPUINFO;
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ return "MIPS32-R1" SLJIT_CPUINFO;
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ return "MIPS64-R1" SLJIT_CPUINFO;
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+#else /* SLJIT_MIPS_REV < 1 */
+ return "MIPS III" SLJIT_CPUINFO;
+#endif /* SLJIT_MIPS_REV >= 6 */
+}
+
+/* Length of an instruction word
+ Both for mips-32 and mips-64 */
+typedef sljit_u32 sljit_ins;
+
+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
+#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
+
+/* For position independent code, t9 must contain the function address. */
+#define PIC_ADDR_REG TMP_REG1
+
+/* Floating point status register. */
+#define FCSR_REG 31
+/* Return address register. */
+#define RETURN_ADDR_REG 31
+
+/* Flags are kept in volatile registers. */
+#define EQUAL_FLAG 3
+#define OTHER_FLAG 1
+
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
+ 0, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 24, 23, 22, 21, 20, 19, 18, 17, 16, 29, 25, 4, 31, 3, 1
+};
+
+#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
+#define TMP_FREG3 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3)
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+
+static const sljit_u8 freg_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3) << 1) + 1] = {
+ 0,
+ 0, 14, 2, 4, 6, 8, 18, 30, 28, 26, 24, 22, 20,
+ 12, 10, 16,
+ 1, 15, 3, 5, 7, 9, 19, 31, 29, 27, 25, 23, 21,
+ 13, 11, 17
+};
+
+#else /* !SLJIT_CONFIG_MIPS_32 */
+
+static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
+ 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 1, 2, 3, 4, 5, 6, 7, 8, 9, 31, 30, 29, 28, 27, 26, 25, 24, 12, 11, 10
+};
+
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+/* --------------------------------------------------------------------- */
+/* Instruction forms */
+/* --------------------------------------------------------------------- */
+
+#define S(s) ((sljit_ins)reg_map[s] << 21)
+#define T(t) ((sljit_ins)reg_map[t] << 16)
+#define D(d) ((sljit_ins)reg_map[d] << 11)
+#define FT(t) ((sljit_ins)freg_map[t] << 16)
+#define FS(s) ((sljit_ins)freg_map[s] << 11)
+#define FD(d) ((sljit_ins)freg_map[d] << 6)
+/* Absolute registers. */
+#define SA(s) ((sljit_ins)(s) << 21)
+#define TA(t) ((sljit_ins)(t) << 16)
+#define DA(d) ((sljit_ins)(d) << 11)
+#define IMM(imm) ((sljit_ins)(imm) & 0xffff)
+#define SH_IMM(imm) ((sljit_ins)(imm) << 6)
+
+#define DR(dr) (reg_map[dr])
+#define FR(dr) (freg_map[dr])
+#define HI(opcode) ((sljit_ins)(opcode) << 26)
+#define LO(opcode) ((sljit_ins)(opcode))
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+/* CMP.cond.fmt */
+/* S = (20 << 21) D = (21 << 21) */
+#define CMP_FMT_S (20 << 21)
+#endif /* SLJIT_MIPS_REV >= 6 */
+/* S = (16 << 21) D = (17 << 21) */
+#define FMT_S (16 << 21)
+#define FMT_D (17 << 21)
+
+#define ABS_S (HI(17) | FMT_S | LO(5))
+#define ADD_S (HI(17) | FMT_S | LO(0))
+#define ADDIU (HI(9))
+#define ADDU (HI(0) | LO(33))
+#define AND (HI(0) | LO(36))
+#define ANDI (HI(12))
+#define B (HI(4))
+#define BAL (HI(1) | (17 << 16))
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+#define BC1EQZ (HI(17) | (9 << 21) | FT(TMP_FREG3))
+#define BC1NEZ (HI(17) | (13 << 21) | FT(TMP_FREG3))
+#else /* SLJIT_MIPS_REV < 6 */
+#define BC1F (HI(17) | (8 << 21))
+#define BC1T (HI(17) | (8 << 21) | (1 << 16))
+#endif /* SLJIT_MIPS_REV >= 6 */
+#define BEQ (HI(4))
+#define BGEZ (HI(1) | (1 << 16))
+#define BGTZ (HI(7))
+#define BLEZ (HI(6))
+#define BLTZ (HI(1) | (0 << 16))
+#define BNE (HI(5))
+#define BREAK (HI(0) | LO(13))
+#define CFC1 (HI(17) | (2 << 21))
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+#define C_EQ_S (HI(17) | CMP_FMT_S | LO(2))
+#define C_OLE_S (HI(17) | CMP_FMT_S | LO(6))
+#define C_OLT_S (HI(17) | CMP_FMT_S | LO(4))
+#define C_UEQ_S (HI(17) | CMP_FMT_S | LO(3))
+#define C_ULE_S (HI(17) | CMP_FMT_S | LO(7))
+#define C_ULT_S (HI(17) | CMP_FMT_S | LO(5))
+#define C_UN_S (HI(17) | CMP_FMT_S | LO(1))
+#define C_FD (FD(TMP_FREG3))
+#else /* SLJIT_MIPS_REV < 6 */
+#define C_EQ_S (HI(17) | FMT_S | LO(50))
+#define C_OLE_S (HI(17) | FMT_S | LO(54))
+#define C_OLT_S (HI(17) | FMT_S | LO(52))
+#define C_UEQ_S (HI(17) | FMT_S | LO(51))
+#define C_ULE_S (HI(17) | FMT_S | LO(55))
+#define C_ULT_S (HI(17) | FMT_S | LO(53))
+#define C_UN_S (HI(17) | FMT_S | LO(49))
+#define C_FD (0)
+#endif /* SLJIT_MIPS_REV >= 6 */
+#define CVT_S_S (HI(17) | FMT_S | LO(32))
+#define DADDIU (HI(25))
+#define DADDU (HI(0) | LO(45))
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+#define DDIV (HI(0) | (2 << 6) | LO(30))
+#define DDIVU (HI(0) | (2 << 6) | LO(31))
+#define DMOD (HI(0) | (3 << 6) | LO(30))
+#define DMODU (HI(0) | (3 << 6) | LO(31))
+#define DIV (HI(0) | (2 << 6) | LO(26))
+#define DIVU (HI(0) | (2 << 6) | LO(27))
+#define DMUH (HI(0) | (3 << 6) | LO(28))
+#define DMUHU (HI(0) | (3 << 6) | LO(29))
+#define DMUL (HI(0) | (2 << 6) | LO(28))
+#define DMULU (HI(0) | (2 << 6) | LO(29))
+#else /* SLJIT_MIPS_REV < 6 */
+#define DDIV (HI(0) | LO(30))
+#define DDIVU (HI(0) | LO(31))
+#define DIV (HI(0) | LO(26))
+#define DIVU (HI(0) | LO(27))
+#define DMULT (HI(0) | LO(28))
+#define DMULTU (HI(0) | LO(29))
+#endif /* SLJIT_MIPS_REV >= 6 */
+#define DIV_S (HI(17) | FMT_S | LO(3))
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+#define DINSU (HI(31) | LO(6))
+#endif /* SLJIT_MIPS_REV >= 2 */
+#define DMFC1 (HI(17) | (1 << 21))
+#define DMTC1 (HI(17) | (5 << 21))
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+#define DROTR (HI(0) | (1 << 21) | LO(58))
+#define DROTR32 (HI(0) | (1 << 21) | LO(62))
+#define DROTRV (HI(0) | (1 << 6) | LO(22))
+#define DSBH (HI(31) | (2 << 6) | LO(36))
+#define DSHD (HI(31) | (5 << 6) | LO(36))
+#endif /* SLJIT_MIPS_REV >= 2 */
+#define DSLL (HI(0) | LO(56))
+#define DSLL32 (HI(0) | LO(60))
+#define DSLLV (HI(0) | LO(20))
+#define DSRA (HI(0) | LO(59))
+#define DSRA32 (HI(0) | LO(63))
+#define DSRAV (HI(0) | LO(23))
+#define DSRL (HI(0) | LO(58))
+#define DSRL32 (HI(0) | LO(62))
+#define DSRLV (HI(0) | LO(22))
+#define DSUBU (HI(0) | LO(47))
+#define J (HI(2))
+#define JAL (HI(3))
+#define JALR (HI(0) | LO(9))
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+#define JR (HI(0) | LO(9))
+#else /* SLJIT_MIPS_REV < 6 */
+#define JR (HI(0) | LO(8))
+#endif /* SLJIT_MIPS_REV >= 6 */
+#define LD (HI(55))
+#define LDL (HI(26))
+#define LDR (HI(27))
+#define LDC1 (HI(53))
+#define LL (HI(48))
+#define LLD (HI(52))
+#define LUI (HI(15))
+#define LW (HI(35))
+#define LWL (HI(34))
+#define LWR (HI(38))
+#define LWC1 (HI(49))
+#define MFC1 (HI(17))
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+#define MFHC1 (HI(17) | (3 << 21))
+#endif /* SLJIT_MIPS_REV >= 2 */
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+#define MOD (HI(0) | (3 << 6) | LO(26))
+#define MODU (HI(0) | (3 << 6) | LO(27))
+#else /* SLJIT_MIPS_REV < 6 */
+#define MFHI (HI(0) | LO(16))
+#define MFLO (HI(0) | LO(18))
+#endif /* SLJIT_MIPS_REV >= 6 */
+#define MTC1 (HI(17) | (4 << 21))
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+#define MTHC1 (HI(17) | (7 << 21))
+#endif /* SLJIT_MIPS_REV >= 2 */
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+#define MUH (HI(0) | (3 << 6) | LO(24))
+#define MUHU (HI(0) | (3 << 6) | LO(25))
+#define MUL (HI(0) | (2 << 6) | LO(24))
+#define MULU (HI(0) | (2 << 6) | LO(25))
+#else /* SLJIT_MIPS_REV < 6 */
+#define MULT (HI(0) | LO(24))
+#define MULTU (HI(0) | LO(25))
+#endif /* SLJIT_MIPS_REV >= 6 */
+#define MUL_S (HI(17) | FMT_S | LO(2))
+#define NEG_S (HI(17) | FMT_S | LO(7))
+#define NOP (HI(0) | LO(0))
+#define NOR (HI(0) | LO(39))
+#define OR (HI(0) | LO(37))
+#define ORI (HI(13))
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+#define ROTR (HI(0) | (1 << 21) | LO(2))
+#define ROTRV (HI(0) | (1 << 6) | LO(6))
+#endif /* SLJIT_MIPS_REV >= 2 */
+#define SC (HI(56))
+#define SCD (HI(60))
+#define SD (HI(63))
+#define SDL (HI(44))
+#define SDR (HI(45))
+#define SDC1 (HI(61))
+#define SLT (HI(0) | LO(42))
+#define SLTI (HI(10))
+#define SLTIU (HI(11))
+#define SLTU (HI(0) | LO(43))
+#define SLL (HI(0) | LO(0))
+#define SLLV (HI(0) | LO(4))
+#define SRL (HI(0) | LO(2))
+#define SRLV (HI(0) | LO(6))
+#define SRA (HI(0) | LO(3))
+#define SRAV (HI(0) | LO(7))
+#define SUB_S (HI(17) | FMT_S | LO(1))
+#define SUBU (HI(0) | LO(35))
+#define SW (HI(43))
+#define SWL (HI(42))
+#define SWR (HI(46))
+#define SWC1 (HI(57))
+#define SYNC (HI(0) | LO(15))
+#define TRUNC_W_S (HI(17) | FMT_S | LO(13))
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+#define WSBH (HI(31) | (2 << 6) | LO(32))
+#endif /* SLJIT_MIPS_REV >= 2 */
+#define XOR (HI(0) | LO(38))
+#define XORI (HI(14))
+
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
+#define CLZ (HI(28) | LO(32))
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+#define DCLZ (LO(18))
+#else /* SLJIT_MIPS_REV < 6 */
+#define DCLZ (HI(28) | LO(36))
+#define MOVF (HI(0) | (0 << 16) | LO(1))
+#define MOVF_S (HI(17) | FMT_S | (0 << 16) | LO(17))
+#define MOVN (HI(0) | LO(11))
+#define MOVN_S (HI(17) | FMT_S | LO(19))
+#define MOVT (HI(0) | (1 << 16) | LO(1))
+#define MOVT_S (HI(17) | FMT_S | (1 << 16) | LO(17))
+#define MOVZ (HI(0) | LO(10))
+#define MOVZ_S (HI(17) | FMT_S | LO(18))
+#define MUL (HI(28) | LO(2))
+#endif /* SLJIT_MIPS_REV >= 6 */
+#define PREF (HI(51))
+#define PREFX (HI(19) | LO(15))
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+#define SEB (HI(31) | (16 << 6) | LO(32))
+#define SEH (HI(31) | (24 << 6) | LO(32))
+#endif /* SLJIT_MIPS_REV >= 2 */
+#endif /* SLJIT_MIPS_REV >= 1 */
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#define ADDU_W ADDU
+#define ADDIU_W ADDIU
+#define SLL_W SLL
+#define SRA_W SRA
+#define SUBU_W SUBU
+#define STORE_W SW
+#define LOAD_W LW
+#else
+#define ADDU_W DADDU
+#define ADDIU_W DADDIU
+#define SLL_W DSLL
+#define SRA_W DSRA
+#define SUBU_W DSUBU
+#define STORE_W SD
+#define LOAD_W LD
+#endif
+
+#define MOV_fmt(f) (HI(17) | f | LO(6))
+
+#define SIMM_MAX (0x7fff)
+#define SIMM_MIN (-0x8000)
+#define UIMM_MAX (0xffff)
+
+#define CPU_FEATURE_DETECTED (1 << 0)
+#define CPU_FEATURE_FPU (1 << 1)
+#define CPU_FEATURE_FP64 (1 << 2)
+#define CPU_FEATURE_FR (1 << 3)
+
+static sljit_u32 cpu_feature_list = 0;
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
+ && (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+
+static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s32 fr, sljit_s32 is_32)
+{
+ if (compiler->scratches == -1)
+ return 0;
+
+ if (is_32 && fr >= SLJIT_F64_SECOND(SLJIT_FR0))
+ fr -= SLJIT_F64_SECOND(0);
+
+ return (fr >= SLJIT_FR0 && fr < (SLJIT_FR0 + compiler->real_fscratches))
+ || (fr > (SLJIT_FS0 - compiler->real_fsaveds) && fr <= SLJIT_FS0)
+ || (fr >= SLJIT_TMP_FREGISTER_BASE && fr < (SLJIT_TMP_FREGISTER_BASE + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS));
+}
+
+static sljit_s32 function_check_is_vreg(struct sljit_compiler *compiler, sljit_s32 vr, sljit_s32 type)
+{
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(vr);
+ SLJIT_UNUSED_ARG(type);
+
+ /* SIMD is not supported. */
+ return 0;
+}
+
+#endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_ARGUMENT_CHECKS */
+
+static void get_cpu_features(void)
+{
+#if !defined(SLJIT_IS_FPU_AVAILABLE) && defined(__GNUC__)
+ sljit_u32 fir = 0;
+#endif /* !SLJIT_IS_FPU_AVAILABLE && __GNUC__ */
+ sljit_u32 feature_list = CPU_FEATURE_DETECTED;
+
+#if defined(SLJIT_IS_FPU_AVAILABLE)
+#if SLJIT_IS_FPU_AVAILABLE
+ feature_list |= CPU_FEATURE_FPU;
+#if SLJIT_IS_FPU_AVAILABLE == 64
+ feature_list |= CPU_FEATURE_FP64;
+#endif /* SLJIT_IS_FPU_AVAILABLE == 64 */
+#endif /* SLJIT_IS_FPU_AVAILABLE */
+#elif defined(__GNUC__)
+ __asm__ ("cfc1 %0, $0" : "=r"(fir));
+ if ((fir & (0x3 << 16)) == (0x3 << 16))
+ feature_list |= CPU_FEATURE_FPU;
+
+#if (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64) \
+ && (!defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV < 2)
+ if ((feature_list & CPU_FEATURE_FPU))
+ feature_list |= CPU_FEATURE_FP64;
+#else /* SLJIT_CONFIG_MIPS32 || SLJIT_MIPS_REV >= 2 */
+ if ((fir & (1 << 22)))
+ feature_list |= CPU_FEATURE_FP64;
+#endif /* SLJIT_CONFIG_MIPS_64 && SLJIT_MIPS_REV < 2 */
+#endif /* SLJIT_IS_FPU_AVAILABLE */
+
+ if ((feature_list & CPU_FEATURE_FPU) && (feature_list & CPU_FEATURE_FP64)) {
+#if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_32
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 6
+ feature_list |= CPU_FEATURE_FR;
+#elif defined(SLJIT_DETECT_FR) && SLJIT_DETECT_FR == 0
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 5
+ feature_list |= CPU_FEATURE_FR;
+#endif /* SLJIT_MIPS_REV >= 5 */
+#else
+ sljit_s32 flag = -1;
+#ifndef FR_GET_FP_MODE
+ sljit_f64 zero = 0.0;
+#else /* PR_GET_FP_MODE */
+ flag = prctl(PR_GET_FP_MODE);
+
+ if (flag > 0)
+ feature_list |= CPU_FEATURE_FR;
+#endif /* FP_GET_PR_MODE */
+#if ((defined(SLJIT_DETECT_FR) && SLJIT_DETECT_FR == 2) \
+ || (!defined(PR_GET_FP_MODE) && (!defined(SLJIT_DETECT_FR) || SLJIT_DETECT_FR >= 1))) \
+ && (defined(__GNUC__) && (defined(__mips) && __mips >= 2))
+ if (flag < 0) {
+ __asm__ (".set oddspreg\n"
+ "lwc1 $f17, %0\n"
+ "ldc1 $f16, %1\n"
+ "swc1 $f17, %0\n"
+ : "+m" (flag) : "m" (zero) : "$f16", "$f17");
+ if (flag)
+ feature_list |= CPU_FEATURE_FR;
+ }
+#endif /* (!PR_GET_FP_MODE || (PR_GET_FP_MODE && SLJIT_DETECT_FR == 2)) && __GNUC__ */
+#endif /* SLJIT_MIPS_REV >= 6 */
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ /* StatusFR=1 is the only mode supported by the code in MIPS64 */
+ feature_list |= CPU_FEATURE_FR;
+#endif /* SLJIT_CONFIG_MIPS_32 */
+ }
+
+ cpu_feature_list = feature_list;
+}
+
+/* dest_reg is the absolute name of the register
+ Useful for reordering instructions in the delay slot. */
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot)
+{
+ sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS
+ || (sljit_ins)delay_slot == ((ins >> 11) & 0x1f)
+ || (sljit_ins)delay_slot == ((ins >> 16) & 0x1f));
+ FAIL_IF(!ptr);
+ *ptr = ins;
+ compiler->size++;
+ compiler->delay_slot = delay_slot;
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_ins invert_branch(sljit_uw flags)
+{
+ if (flags & IS_BIT26_COND)
+ return (1 << 26);
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+ if (flags & IS_BIT23_COND)
+ return (1 << 23);
+#endif /* SLJIT_MIPS_REV >= 6 */
+ return (1 << 16);
+}
+
+static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
+{
+ sljit_sw diff;
+ sljit_uw target_addr;
+ sljit_ins *inst;
+ sljit_ins saved_inst;
+
+ inst = (sljit_ins *)jump->addr;
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
+ goto exit;
+#else
+ if (jump->flags & SLJIT_REWRITABLE_JUMP)
+ goto exit;
+#endif
+
+ if (jump->flags & JUMP_ADDR)
+ target_addr = jump->u.target;
+ else {
+ SLJIT_ASSERT(jump->u.label != NULL);
+ target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
+ }
+
+ if (jump->flags & IS_COND)
+ inst--;
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (jump->flags & IS_CALL)
+ goto preserve_addr;
+#endif
+
+ /* B instructions. */
+ if (jump->flags & IS_MOVABLE) {
+ diff = ((sljit_sw)target_addr - (sljit_sw)inst - executable_offset) >> 2;
+ if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
+ jump->flags |= PATCH_B;
+
+ if (!(jump->flags & IS_COND)) {
+ inst[0] = inst[-1];
+ inst[-1] = (jump->flags & IS_JAL) ? BAL : B;
+ jump->addr -= sizeof(sljit_ins);
+ return inst;
+ }
+ saved_inst = inst[0];
+ inst[0] = inst[-1];
+ inst[-1] = saved_inst ^ invert_branch(jump->flags);
+ jump->addr -= 2 * sizeof(sljit_ins);
+ return inst;
+ }
+ } else {
+ diff = ((sljit_sw)target_addr - (sljit_sw)(inst + 1) - executable_offset) >> 2;
+ if (diff <= SIMM_MAX && diff >= SIMM_MIN) {
+ jump->flags |= PATCH_B;
+
+ if (!(jump->flags & IS_COND)) {
+ inst[0] = (jump->flags & IS_JAL) ? BAL : B;
+ /* Keep inst[1] */
+ return inst + 1;
+ }
+ inst[0] ^= invert_branch(jump->flags);
+ inst[1] = NOP;
+ jump->addr -= sizeof(sljit_ins);
+ return inst + 1;
+ }
+ }
+
+ if (jump->flags & IS_COND) {
+ if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
+ jump->flags |= PATCH_J;
+ saved_inst = inst[0];
+ inst[0] = inst[-1];
+ inst[-1] = (saved_inst & 0xffff0000) | 3;
+ inst[1] = J;
+ inst[2] = NOP;
+ return inst + 2;
+ }
+ else if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
+ jump->flags |= PATCH_J;
+ inst[0] = (inst[0] & 0xffff0000) | 3;
+ inst[1] = NOP;
+ inst[2] = J;
+ inst[3] = NOP;
+ jump->addr += sizeof(sljit_ins);
+ return inst + 3;
+ }
+ }
+ else {
+ /* J instuctions. */
+ if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == (jump->addr & ~(sljit_uw)0xfffffff)) {
+ jump->flags |= PATCH_J;
+ inst[0] = inst[-1];
+ inst[-1] = (jump->flags & IS_JAL) ? JAL : J;
+ jump->addr -= sizeof(sljit_ins);
+ return inst;
+ }
+
+ if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
+ jump->flags |= PATCH_J;
+ inst[0] = (jump->flags & IS_JAL) ? JAL : J;
+ /* Keep inst[1] */
+ return inst + 1;
+ }
+ }
+
+ if (jump->flags & IS_COND)
+ inst++;
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+preserve_addr:
+ if (target_addr <= 0x7fffffff) {
+ jump->flags |= PATCH_ABS32;
+ if (jump->flags & IS_COND)
+ inst[-1] -= 4;
+
+ inst[2] = inst[0];
+ inst[3] = inst[1];
+ return inst + 3;
+ }
+ if (target_addr <= 0x7fffffffffffl) {
+ jump->flags |= PATCH_ABS48;
+ if (jump->flags & IS_COND)
+ inst[-1] -= 2;
+
+ inst[4] = inst[0];
+ inst[5] = inst[1];
+ return inst + 5;
+ }
+#endif
+
+exit:
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ inst[2] = inst[0];
+ inst[3] = inst[1];
+ return inst + 3;
+#else
+ inst[6] = inst[0];
+ inst[7] = inst[1];
+ return inst + 7;
+#endif
+}
+
+#ifdef __GNUC__
+static __attribute__ ((noinline)) void sljit_cache_flush(void* code, void* code_ptr)
+{
+ SLJIT_CACHE_FLUSH(code, code_ptr);
+}
+#endif
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+
+static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
+{
+ sljit_uw addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ if (jump->flags & JUMP_ADDR)
+ addr = jump->u.target;
+ else
+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
+
+ if (addr < 0x80000000l) {
+ jump->flags |= PATCH_ABS32;
+ return 1;
+ }
+
+ if (addr < 0x800000000000l) {
+ jump->flags |= PATCH_ABS48;
+ return 3;
+ }
+
+ return 5;
+}
+
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump)
+{
+ sljit_uw flags = jump->flags;
+ sljit_ins *ins = (sljit_ins*)jump->addr;
+ sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
+ sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : PIC_ADDR_REG;
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ ins[0] = LUI | T(reg) | IMM(addr >> 16);
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ if (flags & PATCH_ABS32) {
+ SLJIT_ASSERT(addr < 0x80000000l);
+ ins[0] = LUI | T(reg) | IMM(addr >> 16);
+ }
+ else if (flags & PATCH_ABS48) {
+ SLJIT_ASSERT(addr < 0x800000000000l);
+ ins[0] = LUI | T(reg) | IMM(addr >> 32);
+ ins[1] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
+ ins[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
+ ins += 2;
+ }
+ else {
+ ins[0] = LUI | T(reg) | IMM(addr >> 48);
+ ins[1] = ORI | S(reg) | T(reg) | IMM((addr >> 32) & 0xffff);
+ ins[2] = DSLL | T(reg) | D(reg) | SH_IMM(16);
+ ins[3] = ORI | S(reg) | T(reg) | IMM((addr >> 16) & 0xffff);
+ ins[4] = DSLL | T(reg) | D(reg) | SH_IMM(16);
+ ins += 4;
+ }
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+ ins[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);
+}
+
+static SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
+{
+ struct sljit_memory_fragment *buf;
+ sljit_ins *code;
+ sljit_ins *code_ptr;
+ sljit_ins *buf_ptr;
+ sljit_ins *buf_end;
+ sljit_uw word_count;
+ SLJIT_NEXT_DEFINE_TYPES;
+ sljit_sw executable_offset;
+ sljit_uw addr;
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
+ reverse_buf(compiler);
+
+ code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
+ PTR_FAIL_WITH_EXEC_IF(code);
+ buf = compiler->buf;
+
+ code_ptr = code;
+ word_count = 0;
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ SLJIT_NEXT_INIT_TYPES();
+ SLJIT_GET_NEXT_MIN();
+
+ do {
+ buf_ptr = (sljit_ins*)buf->memory;
+ buf_end = buf_ptr + (buf->used_size >> 2);
+ do {
+ *code_ptr = *buf_ptr++;
+ if (next_min_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+
+ /* These structures are ordered by their address. */
+ if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+ *code_ptr = buf_ptr[-1];
+ }
+
+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ if (next_min_addr == next_jump_addr) {
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ word_count += 2;
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ word_count += 6;
+#endif /* SLJIT_CONFIG_MIPS_32 */
+ jump->addr = (sljit_uw)(code_ptr - 1);
+ code_ptr = detect_jump_type(jump, code, executable_offset);
+ } else {
+ jump->addr = (sljit_uw)code_ptr;
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ code_ptr += 1;
+ word_count += 1;
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ code_ptr += mov_addr_get_length(jump, code, executable_offset);
+ word_count += 5;
+#endif /* SLJIT_CONFIG_MIPS_32 */
+ }
+
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ } else if (next_min_addr == next_const_addr) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+ }
+
+ SLJIT_GET_NEXT_MIN();
+ }
+ code_ptr++;
+ word_count++;
+ } while (buf_ptr < buf_end);
+
+ buf = buf->next;
+ } while (buf);
+
+ if (label && label->size == word_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
+ label->u.addr = (sljit_uw)code_ptr;
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ }
+
+ SLJIT_ASSERT(!label);
+ SLJIT_ASSERT(!jump);
+ SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
+
+ jump = compiler->jumps;
+ while (jump) {
+ do {
+ addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
+ buf_ptr = (sljit_ins *)jump->addr;
+
+ if (jump->flags & PATCH_B) {
+ addr = (sljit_uw)((sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) - sizeof(sljit_ins)) >> 2);
+ SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN);
+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((sljit_ins)addr & 0xffff);
+ break;
+ }
+ if (jump->flags & PATCH_J) {
+ SLJIT_ASSERT((addr & ~(sljit_uw)0xfffffff)
+ == (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff));
+ buf_ptr[0] |= (sljit_ins)(addr >> 2) & 0x03ffffff;
+ break;
+ }
+
+ load_addr_to_reg(jump);
+ } while (0);
+
+ jump = jump->next;
+ }
+
+ compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
+
+ code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+ code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
+#ifndef __GNUC__
+ SLJIT_CACHE_FLUSH(code, code_ptr);
+#else
+ /* GCC workaround for invalid code generation with -O2. */
+ sljit_cache_flush(code, code_ptr);
+#endif
+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
+ return code;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type) {
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
+ && (!defined(SLJIT_IS_FPU_AVAILABLE) || SLJIT_IS_FPU_AVAILABLE)
+ case SLJIT_HAS_F64_AS_F32_PAIR:
+ if (!cpu_feature_list)
+ get_cpu_features();
+
+ return (cpu_feature_list & CPU_FEATURE_FR) != 0;
+#endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_IS_FPU_AVAILABLE */
+ case SLJIT_HAS_FPU:
+ if (!cpu_feature_list)
+ get_cpu_features();
+
+ return (cpu_feature_list & CPU_FEATURE_FPU) != 0;
+ case SLJIT_HAS_ZERO_REGISTER:
+ case SLJIT_HAS_COPY_F32:
+ case SLJIT_HAS_COPY_F64:
+ return 1;
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
+ case SLJIT_HAS_CLZ:
+ case SLJIT_HAS_CMOV:
+ case SLJIT_HAS_PREFETCH:
+ case SLJIT_HAS_ATOMIC:
+ case SLJIT_HAS_MEMORY_BARRIER:
+ return 1;
+
+ case SLJIT_HAS_CTZ:
+ return 2;
+#endif /* SLJIT_MIPS_REV >= 1 */
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
+ case SLJIT_HAS_REV:
+ case SLJIT_HAS_ROT:
+ return 1;
+#endif /* SLJIT_MIPS_REV >= 2 */
+ default:
+ return 0;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
+{
+ SLJIT_UNUSED_ARG(type);
+ return 0;
+}
+
+/* --------------------------------------------------------------------- */
+/* Entry, exit */
+/* --------------------------------------------------------------------- */
+
+/* Creates an index in data_transfer_insts array. */
+#define LOAD_DATA 0x01
+#define WORD_DATA 0x00
+#define BYTE_DATA 0x02
+#define HALF_DATA 0x04
+#define INT_DATA 0x06
+#define SIGNED_DATA 0x08
+/* Separates integer and floating point registers */
+#define GPR_REG 0x0f
+#define DOUBLE_DATA 0x10
+#define SINGLE_DATA 0x12
+
+#define MEM_MASK 0x1f
+
+#define ARG_TEST 0x00020
+#define ALT_KEEP_CACHE 0x00040
+#define CUMULATIVE_OP 0x00080
+#define LOGICAL_OP 0x00100
+#define IMM_OP 0x00200
+#define MOVE_OP 0x00400
+#define SRC2_IMM 0x00800
+
+#define UNUSED_DEST 0x01000
+#define REG_DEST 0x02000
+#define REG1_SOURCE 0x04000
+#define REG2_SOURCE 0x08000
+#define SLOW_SRC1 0x10000
+#define SLOW_SRC2 0x20000
+#define SLOW_DEST 0x40000
+
+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr);
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#define SELECT_OP(d, w) (w)
+#else
+#define SELECT_OP(d, w) (!(op & SLJIT_32) ? (d) : (w))
+#endif
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#include "sljitNativeMIPS_32.c"
+#else
+#include "sljitNativeMIPS_64.c"
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);
+ sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);
+ sljit_ins base;
+ sljit_s32 i, tmp, offset;
+ sljit_s32 arg_count, word_arg_count, float_arg_count;
+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+
+ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if ((local_size & SSIZE_OF(sw)) != 0)
+ local_size += SSIZE_OF(sw);
+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+ }
+
+ local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
+#else
+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+ local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;
+#endif
+ compiler->local_size = local_size;
+
+ offset = 0;
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ if (!(options & SLJIT_ENTER_REG_ARG)) {
+ tmp = arg_types >> SLJIT_ARG_SHIFT;
+ arg_count = 0;
+
+ while (tmp) {
+ offset = arg_count;
+ if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) {
+ if ((arg_count & 0x1) != 0)
+ arg_count++;
+ arg_count++;
+ }
+
+ arg_count++;
+ tmp >>= SLJIT_ARG_SHIFT;
+ }
+
+ compiler->args_size = (sljit_uw)arg_count << 2;
+ offset = (offset >= 4) ? (offset << 2) : 0;
+ }
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+ if (local_size + offset <= -SIMM_MIN) {
+ /* Frequent case. */
+ FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));
+ base = S(SLJIT_SP);
+ offset = local_size - SSIZE_OF(sw);
+ } else {
+ FAIL_IF(load_immediate(compiler, OTHER_FLAG, local_size));
+ FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | TA(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));
+ base = S(TMP_REG1);
+ offset = -SSIZE_OF(sw);
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ local_size = 0;
+#endif
+ }
+
+ FAIL_IF(push_inst(compiler, STORE_W | base | TA(RETURN_ADDR_REG) | IMM(offset), UNMOVABLE_INS));
+
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS));
+ }
+
+ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STORE_W | base | T(i) | IMM(offset), MOVABLE_INS));
+ }
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ /* This alignment is valid because offset is not used after storing FPU regs. */
+ if ((offset & SSIZE_OF(sw)) != 0)
+ offset -= SSIZE_OF(sw);
+#endif
+
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));
+ }
+
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));
+ }
+
+ if (options & SLJIT_ENTER_REG_ARG)
+ return SLJIT_SUCCESS;
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ arg_count = 0;
+ word_arg_count = 0;
+ float_arg_count = 0;
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ /* The first maximum two floating point arguments are passed in floating point
+ registers if no integer argument precedes them. The first 16 byte data is
+ passed in four integer registers, the rest is placed onto the stack.
+ The floating point registers are also part of the first 16 byte data, so
+ their corresponding integer registers are not used when they are present. */
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ float_arg_count++;
+ if ((arg_count & 0x1) != 0)
+ arg_count++;
+
+ if (word_arg_count == 0 && float_arg_count <= 2) {
+ if (float_arg_count == 1)
+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
+ } else if (arg_count < 4) {
+ FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
+ switch (cpu_feature_list & CPU_FEATURE_FR) {
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+ case CPU_FEATURE_FR:
+ FAIL_IF(push_inst(compiler, MTHC1 | TA(5 + arg_count) | FS(float_arg_count), MOVABLE_INS));
+ break;
+#endif /* SLJIT_MIPS_REV >= 2 */
+ default:
+ FAIL_IF(push_inst(compiler, MTC1 | TA(5 + arg_count) | FS(float_arg_count) | (1 << 11), MOVABLE_INS));
+ break;
+ }
+ } else
+ FAIL_IF(push_inst(compiler, LDC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
+ arg_count++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ float_arg_count++;
+
+ if (word_arg_count == 0 && float_arg_count <= 2) {
+ if (float_arg_count == 1)
+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
+ } else if (arg_count < 4)
+ FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
+ else
+ FAIL_IF(push_inst(compiler, LWC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
+ break;
+ default:
+ word_arg_count++;
+
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ tmp = SLJIT_S0 - saved_arg_count;
+ saved_arg_count++;
+ } else if (word_arg_count != arg_count + 1 || arg_count == 0)
+ tmp = word_arg_count;
+ else
+ break;
+
+ if (arg_count < 4)
+ FAIL_IF(push_inst(compiler, ADDU_W | SA(4 + arg_count) | TA(0) | D(tmp), DR(tmp)));
+ else
+ FAIL_IF(push_inst(compiler, LW | base | T(tmp) | IMM(local_size + (arg_count << 2)), DR(tmp)));
+ break;
+ }
+ arg_count++;
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ SLJIT_ASSERT(compiler->args_size == (sljit_uw)arg_count << 2);
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ while (arg_types) {
+ arg_count++;
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ float_arg_count++;
+ if (arg_count != float_arg_count)
+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
+ else if (arg_count == 1)
+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT_D) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ float_arg_count++;
+ if (arg_count != float_arg_count)
+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
+ else if (arg_count == 1)
+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
+ break;
+ default:
+ word_arg_count++;
+
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ tmp = SLJIT_S0 - saved_arg_count;
+ saved_arg_count++;
+ } else if (word_arg_count != arg_count || word_arg_count <= 1)
+ tmp = word_arg_count;
+ else
+ break;
+
+ FAIL_IF(push_inst(compiler, ADDU_W | SA(3 + arg_count) | TA(0) | D(tmp), DR(tmp)));
+ break;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);
+ sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+
+ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if ((local_size & SSIZE_OF(sw)) != 0)
+ local_size += SSIZE_OF(sw);
+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+ }
+
+ compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
+#else
+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+ compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;
+#endif
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr)
+{
+ sljit_s32 local_size, i, tmp, offset;
+ sljit_s32 load_return_addr = (frame_size == 0);
+ sljit_s32 scratches = compiler->scratches;
+ sljit_s32 saveds = compiler->saveds;
+ sljit_s32 fsaveds = compiler->fsaveds;
+ sljit_s32 fscratches = compiler->fscratches;
+ sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);
+
+ SLJIT_ASSERT(frame_size == 1 || (frame_size & 0xf) == 0);
+ frame_size &= ~0xf;
+
+ local_size = compiler->local_size;
+
+ tmp = GET_SAVED_REGISTERS_SIZE(scratches, saveds - kept_saveds_count, 1);
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if ((tmp & SSIZE_OF(sw)) != 0)
+ tmp += SSIZE_OF(sw);
+ tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+ }
+#else
+ tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+#endif
+
+ if (local_size <= SIMM_MAX) {
+ if (local_size < frame_size) {
+ FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size), DR(SLJIT_SP)));
+ local_size = frame_size;
+ }
+ } else {
+ if (tmp < frame_size)
+ tmp = frame_size;
+
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG2), local_size - tmp));
+ FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG2) | D(SLJIT_SP), DR(SLJIT_SP)));
+ local_size = tmp;
+ }
+
+ SLJIT_ASSERT(local_size >= frame_size);
+
+ offset = local_size - SSIZE_OF(sw);
+ if (load_return_addr)
+ FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG));
+
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0 - kept_saveds_count; i > tmp; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));
+ }
+
+ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, LOAD_W | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));
+ }
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ /* This alignment is valid because offset is not used after storing FPU regs. */
+ if ((offset & SSIZE_OF(sw)) != 0)
+ offset -= SSIZE_OF(sw);
+#endif
+
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));
+ }
+
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));
+ }
+
+ if (local_size > frame_size)
+ *ins_ptr = ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size);
+ else
+ *ins_ptr = NOP;
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ emit_stack_frame_release(compiler, 0, &ins);
+
+ FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ return push_inst(compiler, ins, UNMOVABLE_INS);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
+ src = PIC_ADDR_REG;
+ srcw = 0;
+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
+ src = PIC_ADDR_REG;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 1, &ins));
+
+ if (src != SLJIT_IMM) {
+ FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));
+ return push_inst(compiler, ins, UNMOVABLE_INS);
+ }
+
+ if (ins != NOP)
+ FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
+}
+
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#define ARCH_32_64(a, b) a
+#else
+#define ARCH_32_64(a, b) b
+#endif
+
+static const sljit_ins data_transfer_insts[16 + 4] = {
+/* u w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
+/* u w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
+/* u b s */ HI(40) /* sb */,
+/* u b l */ HI(36) /* lbu */,
+/* u h s */ HI(41) /* sh */,
+/* u h l */ HI(37) /* lhu */,
+/* u i s */ HI(43) /* sw */,
+/* u i l */ ARCH_32_64(HI(35) /* lw */, HI(39) /* lwu */),
+
+/* s w s */ ARCH_32_64(HI(43) /* sw */, HI(63) /* sd */),
+/* s w l */ ARCH_32_64(HI(35) /* lw */, HI(55) /* ld */),
+/* s b s */ HI(40) /* sb */,
+/* s b l */ HI(32) /* lb */,
+/* s h s */ HI(41) /* sh */,
+/* s h l */ HI(33) /* lh */,
+/* s i s */ HI(43) /* sw */,
+/* s i l */ HI(35) /* lw */,
+
+/* d s */ HI(61) /* sdc1 */,
+/* d l */ HI(53) /* ldc1 */,
+/* s s */ HI(57) /* swc1 */,
+/* s l */ HI(49) /* lwc1 */,
+};
+
+#undef ARCH_32_64
+
+/* reg_ar is an absoulute register! */
+
+/* Can perform an operation using at most 1 instruction. */
+static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
+{
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+
+ if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
+ /* Works for both absoulte and relative addresses. */
+ if (SLJIT_UNLIKELY(flags & ARG_TEST))
+ return 1;
+ FAIL_IF(push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(arg & REG_MASK)
+ | TA(reg_ar) | IMM(argw), ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) ? reg_ar : MOVABLE_INS));
+ return -1;
+ }
+ return 0;
+}
+
+#define TO_ARGW_HI(argw) (((argw) & ~0xffff) + (((argw) & 0x8000) ? 0x10000 : 0))
+
+/* See getput_arg below.
+ Note: can_cache is called only for binary operators. */
+static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
+{
+ SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
+
+ /* Simple operation except for updates. */
+ if (arg & OFFS_REG_MASK) {
+ argw &= 0x3;
+ next_argw &= 0x3;
+ if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))
+ return 1;
+ return 0;
+ }
+
+ if (arg == next_arg) {
+ if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)
+ || TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw))
+ return 1;
+ return 0;
+ }
+
+ return 0;
+}
+
+/* Emit the necessary instructions. See can_cache above. */
+static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
+{
+ sljit_s32 tmp_ar, base, delay_slot;
+ sljit_sw offset, argw_hi;
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+ if (!(next_arg & SLJIT_MEM)) {
+ next_arg = 0;
+ next_argw = 0;
+ }
+
+ /* Since tmp can be the same as base or offset registers,
+ * these might be unavailable after modifying tmp. */
+ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
+ tmp_ar = reg_ar;
+ delay_slot = reg_ar;
+ }
+ else {
+ tmp_ar = DR(TMP_REG1);
+ delay_slot = MOVABLE_INS;
+ }
+ base = arg & REG_MASK;
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ argw &= 0x3;
+
+ /* Using the cache. */
+ if (argw == compiler->cache_argw) {
+ if (arg == compiler->cache_arg)
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
+
+ if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
+ if (arg == next_arg && argw == (next_argw & 0x3)) {
+ compiler->cache_arg = arg;
+ compiler->cache_argw = argw;
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar), delay_slot);
+ }
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(TMP_REG3) | DA(tmp_ar), tmp_ar));
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
+ }
+ }
+
+ if (SLJIT_UNLIKELY(argw)) {
+ compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
+ compiler->cache_argw = argw;
+ FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG3) | SH_IMM(argw), DR(TMP_REG3)));
+ }
+
+ if (arg == next_arg && argw == (next_argw & 0x3)) {
+ compiler->cache_arg = arg;
+ compiler->cache_argw = argw;
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | D(TMP_REG3), DR(TMP_REG3)));
+ tmp_ar = DR(TMP_REG3);
+ }
+ else
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(!argw ? OFFS_REG(arg) : TMP_REG3) | DA(tmp_ar), tmp_ar));
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
+ }
+
+ if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(argw - compiler->cache_argw), delay_slot);
+
+ if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw) <= SIMM_MAX && (argw - compiler->cache_argw) >= SIMM_MIN) {
+ offset = argw - compiler->cache_argw;
+ } else {
+ compiler->cache_arg = SLJIT_MEM;
+
+ argw_hi = TO_ARGW_HI(argw);
+
+ if (next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN && argw_hi != TO_ARGW_HI(next_argw)) {
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw));
+ compiler->cache_argw = argw;
+ offset = 0;
+ } else {
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG3), argw_hi));
+ compiler->cache_argw = argw_hi;
+ offset = argw & 0xffff;
+ argw = argw_hi;
+ }
+ }
+
+ if (!base)
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot);
+
+ if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {
+ compiler->cache_arg = arg;
+ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | D(TMP_REG3), DR(TMP_REG3)));
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | S(TMP_REG3) | TA(reg_ar) | IMM(offset), delay_slot);
+ }
+
+ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | T(base) | DA(tmp_ar), tmp_ar));
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(offset), delay_slot);
+}
+
+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
+{
+ sljit_s32 tmp_ar, base, delay_slot;
+
+ if (getput_arg_fast(compiler, flags, reg_ar, arg, argw))
+ return compiler->error;
+
+ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) {
+ tmp_ar = reg_ar;
+ delay_slot = reg_ar;
+ }
+ else {
+ tmp_ar = DR(TMP_REG1);
+ delay_slot = MOVABLE_INS;
+ }
+ base = arg & REG_MASK;
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ argw &= 0x3;
+
+ if (SLJIT_UNLIKELY(argw)) {
+ FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | DA(tmp_ar) | SH_IMM(argw), tmp_ar));
+ FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar));
+ }
+ else
+ FAIL_IF(push_inst(compiler, ADDU_W | S(base) | T(OFFS_REG(arg)) | DA(tmp_ar), tmp_ar));
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
+ }
+
+ FAIL_IF(load_immediate(compiler, tmp_ar, TO_ARGW_HI(argw)));
+
+ if (base != 0)
+ FAIL_IF(push_inst(compiler, ADDU_W | SA(tmp_ar) | T(base) | DA(tmp_ar), tmp_ar));
+
+ return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(argw), delay_slot);
+}
+
+static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
+{
+ if (getput_arg_fast(compiler, flags, reg_ar, arg1, arg1w))
+ return compiler->error;
+ return getput_arg(compiler, flags, reg_ar, arg1, arg1w, arg2, arg2w);
+}
+
+#define EMIT_LOGICAL(op_imm, op_reg) \
+ if (flags & SRC2_IMM) { \
+ if (op & SLJIT_SET_Z) \
+ FAIL_IF(push_inst(compiler, op_imm | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG)); \
+ if (!(flags & UNUSED_DEST)) \
+ FAIL_IF(push_inst(compiler, op_imm | S(src1) | T(dst) | IMM(src2), DR(dst))); \
+ } \
+ else { \
+ if (op & SLJIT_SET_Z) \
+ FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
+ if (!(flags & UNUSED_DEST)) \
+ FAIL_IF(push_inst(compiler, op_reg | S(src1) | T(src2) | D(dst), DR(dst))); \
+ }
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+
+#define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \
+ op_imm = (imm); \
+ op_v = (v);
+
+#else /* !SLJIT_CONFIG_MIPS_32 */
+
+
+#define EMIT_SHIFT(dimm, dimm32, imm, dv, v) \
+ op_dimm = (dimm); \
+ op_dimm32 = (dimm32); \
+ op_imm = (imm); \
+ op_dv = (dv); \
+ op_v = (v);
+
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV < 1)
+
+static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
+{
+ sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ);
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;
+#else /* !SLJIT_CONFIG_MIPS_64 */
+ sljit_ins word_size = 32;
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+ /* The TMP_REG2 is the next value. */
+ if (src != TMP_REG2)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
+
+ FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(is_clz ? 13 : 14), UNMOVABLE_INS));
+ /* The OTHER_FLAG is the counter. Delay slot. */
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(word_size), OTHER_FLAG));
+
+ if (!is_clz) {
+ FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG2) | T(TMP_REG1) | IMM(1), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, BNE | S(TMP_REG1) | TA(0) | IMM(11), UNMOVABLE_INS));
+ } else
+ FAIL_IF(push_inst(compiler, BLTZ | S(TMP_REG2) | TA(0) | IMM(11), UNMOVABLE_INS));
+
+ /* Delay slot. */
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | TA(OTHER_FLAG) | IMM(0), OTHER_FLAG));
+
+ /* The TMP_REG1 is the next shift. */
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(TMP_REG1) | IMM(word_size), DR(TMP_REG1)));
+
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(TMP_REG2) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));
+
+ FAIL_IF(push_inst(compiler, (is_clz ? SELECT_OP(DSRLV, SRLV) : SELECT_OP(DSLLV, SLLV)) | S(TMP_REG1) | TA(EQUAL_FLAG) | D(TMP_REG2), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, BNE | S(TMP_REG2) | TA(0) | IMM(-4), UNMOVABLE_INS));
+ /* Delay slot. */
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(TMP_REG1) | T(TMP_REG2) | IMM(-1), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, (is_clz ? SELECT_OP(DSRLV, SRLV) : SELECT_OP(DSLLV, SLLV)) | S(TMP_REG2) | TA(EQUAL_FLAG) | D(TMP_REG2), DR(TMP_REG2)));
+
+ FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG2) | TA(0) | IMM(-7), UNMOVABLE_INS));
+ /* Delay slot. */
+ FAIL_IF(push_inst(compiler, OR | SA(OTHER_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG));
+
+ return push_inst(compiler, SELECT_OP(DADDU, ADDU) | SA(OTHER_FLAG) | TA(0) | D(dst), DR(dst));
+}
+
+#endif /* SLJIT_MIPS_REV < 1 */
+
+static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
+{
+#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64
+ int is_32 = (op & SLJIT_32);
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+ op = GET_OPCODE(op);
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64
+ if (!is_32 && (op == SLJIT_REV)) {
+ FAIL_IF(push_inst(compiler, DSBH | T(src) | D(dst), DR(dst)));
+ return push_inst(compiler, DSHD | T(dst) | D(dst), DR(dst));
+ }
+ if (op != SLJIT_REV && src != TMP_REG2) {
+ FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG1), DR(TMP_REG1)));
+ src = TMP_REG1;
+ }
+#endif /* SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, WSBH | T(src) | D(dst), DR(dst)));
+ FAIL_IF(push_inst(compiler, ROTR | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
+#if defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64
+ if (op == SLJIT_REV_U32 && dst != TMP_REG2 && dst != TMP_REG3)
+ FAIL_IF(push_inst(compiler, DINSU | T(dst) | SA(0) | (31 << 11), DR(dst)));
+#endif /* SLJIT_CONFIG_MIPS_64 */
+#else /* SLJIT_MIPS_REV < 2 */
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (!is_32) {
+ FAIL_IF(push_inst(compiler, DSRL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, ORI | SA(0) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG));
+ FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(dst) | SH_IMM(0), DR(dst)));
+ FAIL_IF(push_inst(compiler, DSLL32 | TA(OTHER_FLAG) | DA(OTHER_FLAG) | SH_IMM(0), OTHER_FLAG));
+ FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));
+
+ FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xffff, OTHER_FLAG));
+ FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
+ FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, DSLL | TA(OTHER_FLAG) | DA(EQUAL_FLAG) | SH_IMM(8), EQUAL_FLAG));
+ FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
+ FAIL_IF(push_inst(compiler, XOR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
+ FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));
+
+ FAIL_IF(push_inst(compiler, DSRL | T(dst) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
+ FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(8), DR(dst)));
+ return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));
+ }
+
+ if (op != SLJIT_REV && src != TMP_REG2) {
+ FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG2) | SH_IMM(0), DR(TMP_REG2)));
+ src = TMP_REG2;
+ }
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+ FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(16), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, LUI | TA(OTHER_FLAG) | 0xff, OTHER_FLAG));
+ FAIL_IF(push_inst(compiler, SLL | T(src) | D(dst) | SH_IMM(16), DR(dst)));
+ FAIL_IF(push_inst(compiler, ORI | SA(OTHER_FLAG) | TA(OTHER_FLAG) | 0xff, OTHER_FLAG));
+ FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));
+
+ FAIL_IF(push_inst(compiler, SRL | T(dst) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, AND | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
+ FAIL_IF(push_inst(compiler, AND | S(TMP_REG1) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, SLL | T(dst) | D(dst) | SH_IMM(8), DR(dst)));
+ FAIL_IF(push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst)));
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (op == SLJIT_REV_U32 && dst != TMP_REG2 && dst != TMP_REG3) {
+ FAIL_IF(push_inst(compiler, DSLL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)));
+ FAIL_IF(push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst)));
+ }
+#endif /* SLJIT_CONFIG_MIPS_64 */
+#endif /* SLJIT_MIPR_REV >= 2 */
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
+{
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+#if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_32
+ FAIL_IF(push_inst(compiler, WSBH | T(src) | D(dst), DR(dst)));
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ FAIL_IF(push_inst(compiler, DSBH | T(src) | D(dst), DR(dst)));
+#endif /* SLJIT_CONFIG_MIPS_32 */
+ if (GET_OPCODE(op) == SLJIT_REV_U16)
+ return push_inst(compiler, ANDI | S(dst) | T(dst) | 0xffff, DR(dst));
+ else
+ return push_inst(compiler, SEH | T(dst) | D(dst), DR(dst));
+#else /* SLJIT_MIPS_REV < 2 */
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRL, SRL) | T(src) | D(TMP_REG1) | SH_IMM(8), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | T(src) | D(dst) | SH_IMM(24), DR(dst)));
+ FAIL_IF(push_inst(compiler, ANDI | S(TMP_REG1) | T(TMP_REG1) | 0xff, DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SELECT_OP(DSRL32, SRL) : SELECT_OP(DSRA32, SRA)) | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
+ return push_inst(compiler, OR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));
+#endif /* SLJIT_MIPS_REV >= 2 */
+}
+
+static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+ sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
+{
+ sljit_s32 is_overflow, is_carry, carry_src_ar, is_handled, reg;
+ sljit_ins op_imm, op_v;
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ sljit_ins ins, op_dimm, op_dimm32, op_dv;
+#endif
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if (dst != src2)
+ return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_U8:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
+ return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_S8:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
+ return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
+#else /* SLJIT_MIPS_REV < 2 */
+ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
+ return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
+#endif /* SLJIT_MIPS_REV >= 2 */
+#else /* !SLJIT_CONFIG_MIPS_32 */
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
+ if (op & SLJIT_32)
+ return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
+#endif /* SLJIT_MIPS_REV >= 2 */
+ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
+ return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
+#endif /* SLJIT_CONFIG_MIPS_32 */
+ }
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_U16:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
+ return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_S16:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
+ return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
+#else /* SLJIT_MIPS_REV < 2 */
+ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
+ return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
+#endif /* SLJIT_MIPS_REV >= 2 */
+#else /* !SLJIT_CONFIG_MIPS_32 */
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
+ if (op & SLJIT_32)
+ return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
+#endif /* SLJIT_MIPS_REV >= 2 */
+ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
+ return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
+#endif /* SLJIT_CONFIG_MIPS_32 */
+ }
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ case SLJIT_MOV_U32:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
+ if (dst == src2)
+ return push_inst(compiler, DINSU | T(src2) | SA(0) | (31 << 11), DR(dst));
+#endif /* SLJIT_MIPS_REV >= 2 */
+ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
+ return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
+ }
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_S32:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
+ }
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
+ case SLJIT_CLZ:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+ return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | D(dst), DR(dst));
+#else /* SLJIT_MIPS_REV < 6 */
+ return push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst));
+#endif /* SLJIT_MIPS_REV >= 6 */
+ case SLJIT_CTZ:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, AND | S(src2) | T(TMP_REG1) | D(dst), DR(dst)));
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | D(dst), DR(dst)));
+#else /* SLJIT_MIPS_REV < 6 */
+ FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(dst) | T(dst) | D(dst), DR(dst)));
+#endif /* SLJIT_MIPS_REV >= 6 */
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(TMP_REG1) | IMM(SELECT_OP(-64, -32)), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(SELECT_OP(26, 27)), DR(TMP_REG1)));
+ return push_inst(compiler, XOR | S(dst) | T(TMP_REG1) | D(dst), DR(dst));
+#else /* SLJIT_MIPS_REV < 1 */
+ case SLJIT_CLZ:
+ case SLJIT_CTZ:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ return emit_clz_ctz(compiler, op, dst, src2);
+#endif /* SLJIT_MIPS_REV >= 1 */
+
+ case SLJIT_REV:
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && src2 != TMP_REG1 && dst != TMP_REG1);
+ return emit_rev(compiler, op, dst, src2);
+
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ return emit_rev16(compiler, op, dst, src2);
+
+ case SLJIT_ADD:
+ /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */
+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+ carry_src_ar = GET_FLAG_TYPE(op) == SLJIT_CARRY;
+
+ if (flags & SRC2_IMM) {
+ if (is_overflow) {
+ if (src2 >= 0)
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ else
+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ }
+ else if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
+
+ /* Only the zero flag is needed. */
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
+ }
+ else {
+ if (is_overflow)
+ FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ else if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+
+ if (is_overflow || carry_src_ar != 0) {
+ if (src1 != dst)
+ carry_src_ar = DR(src1);
+ else if (src2 != dst)
+ carry_src_ar = DR(src2);
+ else {
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(OTHER_FLAG), OTHER_FLAG));
+ carry_src_ar = OTHER_FLAG;
+ }
+ }
+
+ /* Only the zero flag is needed. */
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
+ }
+
+ /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
+ if (is_overflow || carry_src_ar != 0) {
+ if (flags & SRC2_IMM)
+ FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+ else
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(OTHER_FLAG), OTHER_FLAG));
+ }
+
+ if (!is_overflow)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
+ return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
+
+ case SLJIT_ADDC:
+ carry_src_ar = GET_FLAG_TYPE(op) == SLJIT_CARRY;
+
+ if (flags & SRC2_IMM) {
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(src2), DR(dst)));
+ } else {
+ if (carry_src_ar != 0) {
+ if (src1 != dst)
+ carry_src_ar = DR(src1);
+ else if (src2 != dst)
+ carry_src_ar = DR(src2);
+ else {
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ carry_src_ar = EQUAL_FLAG;
+ }
+ }
+
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | T(src2) | D(dst), DR(dst)));
+ }
+
+ /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
+ if (carry_src_ar != 0) {
+ if (flags & SRC2_IMM)
+ FAIL_IF(push_inst(compiler, SLTIU | S(dst) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
+ else
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(carry_src_ar) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ }
+
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
+
+ if (carry_src_ar == 0)
+ return SLJIT_SUCCESS;
+
+ /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG));
+ /* Set carry flag. */
+ return push_inst(compiler, OR | SA(OTHER_FLAG) | TA(EQUAL_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
+
+ case SLJIT_SUB:
+ if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
+ src2 = TMP_REG2;
+ flags &= ~SRC2_IMM;
+ }
+
+ is_handled = 0;
+
+ if (flags & SRC2_IMM) {
+ if (GET_FLAG_TYPE(op) == SLJIT_LESS) {
+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+ is_handled = 1;
+ }
+ else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) {
+ FAIL_IF(push_inst(compiler, SLTI | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+ is_handled = 1;
+ }
+ }
+
+ if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
+ is_handled = 1;
+
+ if (flags & SRC2_IMM) {
+ reg = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(reg) | IMM(src2), DR(reg)));
+ src2 = reg;
+ flags &= ~SRC2_IMM;
+ }
+
+ switch (GET_FLAG_TYPE(op)) {
+ case SLJIT_LESS:
+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
+ break;
+ case SLJIT_GREATER:
+ FAIL_IF(push_inst(compiler, SLTU | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
+ break;
+ case SLJIT_SIG_LESS:
+ FAIL_IF(push_inst(compiler, SLT | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
+ break;
+ case SLJIT_SIG_GREATER:
+ FAIL_IF(push_inst(compiler, SLT | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
+ break;
+ }
+ }
+
+ if (is_handled) {
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
+ if (!(flags & UNUSED_DEST))
+ return push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst));
+ }
+ else {
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ if (!(flags & UNUSED_DEST))
+ return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst));
+ }
+ return SLJIT_SUCCESS;
+ }
+
+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+ is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;
+
+ if (flags & SRC2_IMM) {
+ if (is_overflow) {
+ if (src2 >= 0)
+ FAIL_IF(push_inst(compiler, OR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ else
+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ }
+ else if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | TA(EQUAL_FLAG) | IMM(-src2), EQUAL_FLAG));
+
+ if (is_overflow || is_carry)
+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(OTHER_FLAG) | IMM(src2), OTHER_FLAG));
+
+ /* Only the zero flag is needed. */
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
+ }
+ else {
+ if (is_overflow)
+ FAIL_IF(push_inst(compiler, XOR | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ else if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+
+ if (is_overflow || is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(OTHER_FLAG), OTHER_FLAG));
+
+ /* Only the zero flag is needed. */
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
+ }
+
+ if (!is_overflow)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst(compiler, XOR | S(dst) | TA(EQUAL_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(31), DR(TMP_REG1)));
+ return push_inst(compiler, XOR | S(TMP_REG1) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
+
+ case SLJIT_SUBC:
+ if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
+ FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(TMP_REG2) | IMM(src2), DR(TMP_REG2)));
+ src2 = TMP_REG2;
+ flags &= ~SRC2_IMM;
+ }
+
+ is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;
+
+ if (flags & SRC2_IMM) {
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTIU | S(src1) | TA(EQUAL_FLAG) | IMM(src2), EQUAL_FLAG));
+
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(src1) | T(dst) | IMM(-src2), DR(dst)));
+ }
+ else {
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(src1) | T(src2) | D(dst), DR(dst)));
+ }
+
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | S(dst) | TA(OTHER_FLAG) | D(TMP_REG1), DR(TMP_REG1)));
+
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst)));
+
+ if (!is_carry)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, OR | SA(EQUAL_FLAG) | T(TMP_REG1) | DA(OTHER_FLAG), OTHER_FLAG);
+
+ case SLJIT_MUL:
+ SLJIT_ASSERT(!(flags & SRC2_IMM));
+
+ if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW) {
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+ return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst));
+#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ if (op & SLJIT_32)
+ return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
+ FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
+ return push_inst(compiler, MFLO | D(dst), DR(dst));
+#endif /* SLJIT_CONFIG_MIPS_32 */
+#else /* SLJIT_MIPS_REV < 1 */
+ FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
+ return push_inst(compiler, MFLO | D(dst), DR(dst));
+#endif /* SLJIT_MIPS_REV >= 6 */
+ }
+
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+ FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)));
+ FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+#else /* SLJIT_MIPS_REV < 6 */
+ FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
+ FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
+#endif /* SLJIT_MIPS_REV >= 6 */
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
+ return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);
+
+ case SLJIT_AND:
+ EMIT_LOGICAL(ANDI, AND);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_OR:
+ EMIT_LOGICAL(ORI, OR);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_XOR:
+ if (!(flags & LOGICAL_OP)) {
+ SLJIT_ASSERT((flags & SRC2_IMM) && src2 == -1);
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
+ if (!(flags & UNUSED_DEST))
+ FAIL_IF(push_inst(compiler, NOR | S(src1) | T(src1) | D(dst), DR(dst)));
+ return SLJIT_SUCCESS;
+ }
+ EMIT_LOGICAL(XORI, XOR);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ EMIT_SHIFT(DSLL, DSLL32, SLL, DSLLV, SLLV);
+ break;
+
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ EMIT_SHIFT(DSRL, DSRL32, SRL, DSRLV, SRLV);
+ break;
+
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ EMIT_SHIFT(DSRA, DSRA32, SRA, DSRAV, SRAV);
+ break;
+
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
+ case SLJIT_ROTL:
+ if ((flags & SRC2_IMM) || src2 == 0) {
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ src2 = -src2 & 0x1f;
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ src2 = -src2 & ((op & SLJIT_32) ? 0x1f : 0x3f);
+#endif /* SLJIT_CONFIG_MIPS_32 */
+ } else {
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG2), DR(TMP_REG2)));
+ src2 = TMP_REG2;
+ }
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_ROTR:
+ EMIT_SHIFT(DROTR, DROTR32, ROTR, DROTRV, ROTRV);
+ break;
+#else /* SLJIT_MIPS_REV < 1 */
+ case SLJIT_ROTL:
+ case SLJIT_ROTR:
+ if (flags & SRC2_IMM) {
+ SLJIT_ASSERT(src2 != 0);
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (!(op & SLJIT_32)) {
+ if (GET_OPCODE(op) == SLJIT_ROTL)
+ op_imm = ((src2 < 32) ? DSLL : DSLL32);
+ else
+ op_imm = ((src2 < 32) ? DSRL : DSRL32);
+
+ FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | (((sljit_ins)src2 & 0x1f) << 6), OTHER_FLAG));
+
+ src2 = 64 - src2;
+ if (GET_OPCODE(op) == SLJIT_ROTL)
+ op_imm = ((src2 < 32) ? DSRL : DSRL32);
+ else
+ op_imm = ((src2 < 32) ? DSLL : DSLL32);
+
+ FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst)));
+ return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));
+ }
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+ op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL;
+ FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(OTHER_FLAG) | ((sljit_ins)src2 << 6), OTHER_FLAG));
+
+ src2 = 32 - src2;
+ op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL;
+ FAIL_IF(push_inst(compiler, op_imm | T(src1) | D(dst) | (((sljit_ins)src2 & 0x1f) << 6), DR(dst)));
+ return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));
+ }
+
+ if (src2 == 0) {
+ if (dst != src1)
+ return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src1) | TA(0) | D(dst), DR(dst));
+ return SLJIT_SUCCESS;
+ }
+
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (!(op & SLJIT_32)) {
+ op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSLLV : DSRLV;
+ FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
+ op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? DSRLV : DSLLV;
+ FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst)));
+ return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));
+ }
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+ op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLV : SRLV;
+ FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(OTHER_FLAG), OTHER_FLAG));
+ op_v = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLV : SLLV;
+ FAIL_IF(push_inst(compiler, op_v | SA(EQUAL_FLAG) | T(src1) | D(dst), DR(dst)));
+ return push_inst(compiler, OR | S(dst) | TA(OTHER_FLAG) | D(dst), DR(dst));
+#endif /* SLJIT_MIPS_REV >= 2 */
+
+ default:
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
+ }
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ if ((flags & SRC2_IMM) || src2 == 0) {
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, op_imm | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG));
+
+ if (flags & UNUSED_DEST)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, op_imm | T(src1) | D(dst) | SH_IMM(src2), DR(dst));
+ }
+
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, op_v | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
+
+ if (flags & UNUSED_DEST)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, op_v | S(src2) | T(src1) | D(dst), DR(dst));
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ if ((flags & SRC2_IMM) || src2 == 0) {
+ if (src2 >= 32) {
+ SLJIT_ASSERT(!(op & SLJIT_32));
+ ins = op_dimm32;
+ src2 -= 32;
+ }
+ else
+ ins = (op & SLJIT_32) ? op_imm : op_dimm;
+
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG));
+
+ if (flags & UNUSED_DEST)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst));
+ }
+
+ ins = (op & SLJIT_32) ? op_v : op_dv;
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG));
+
+ if (flags & UNUSED_DEST)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, ins | S(src2) | T(src1) | D(dst), DR(dst));
+#endif /* SLJIT_CONFIG_MIPS_32 */
+}
+
+#define CHECK_IMM(flags, srcw) \
+ ((!((flags) & LOGICAL_OP) && ((srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)) \
+ || (((flags) & LOGICAL_OP) && !((srcw) & ~UIMM_MAX)))
+
+static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ /* arg1 goes to TMP_REG1 or src reg
+ arg2 goes to TMP_REG2, imm or src reg
+ TMP_REG3 can be used for caching
+ result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
+ sljit_s32 dst_r = TMP_REG2;
+ sljit_s32 src1_r;
+ sljit_sw src2_r = 0;
+ sljit_s32 src2_tmp_reg = (GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;
+
+ if (!(flags & ALT_KEEP_CACHE)) {
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ }
+
+ if (dst == 0) {
+ SLJIT_ASSERT(HAS_FLAGS(op));
+ flags |= UNUSED_DEST;
+ dst = TMP_REG2;
+ }
+ else if (FAST_IS_REG(dst)) {
+ dst_r = dst;
+ flags |= REG_DEST;
+ if (flags & MOVE_OP)
+ src2_tmp_reg = dst_r;
+ }
+ else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))
+ flags |= SLOW_DEST;
+
+ if (flags & IMM_OP) {
+ if (src2 == SLJIT_IMM && src2w != 0 && CHECK_IMM(flags, src2w)) {
+ flags |= SRC2_IMM;
+ src2_r = src2w;
+ } else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && CHECK_IMM(flags, src1w)) {
+ flags |= SRC2_IMM;
+ src2_r = src1w;
+
+ /* And swap arguments. */
+ src1 = src2;
+ src1w = src2w;
+ src2 = SLJIT_IMM;
+ /* src2w = src2_r unneeded. */
+ }
+ }
+
+ /* Source 1. */
+ if (FAST_IS_REG(src1)) {
+ src1_r = src1;
+ flags |= REG1_SOURCE;
+ }
+ else if (src1 == SLJIT_IMM) {
+ if (src1w) {
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
+ src1_r = TMP_REG1;
+ }
+ else
+ src1_r = 0;
+ }
+ else {
+ if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w))
+ FAIL_IF(compiler->error);
+ else
+ flags |= SLOW_SRC1;
+ src1_r = TMP_REG1;
+ }
+
+ /* Source 2. */
+ if (FAST_IS_REG(src2)) {
+ src2_r = src2;
+ flags |= REG2_SOURCE;
+ if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)
+ dst_r = (sljit_s32)src2_r;
+ }
+ else if (src2 == SLJIT_IMM) {
+ if (!(flags & SRC2_IMM)) {
+ if (src2w) {
+ FAIL_IF(load_immediate(compiler, DR(src2_tmp_reg), src2w));
+ src2_r = src2_tmp_reg;
+ }
+ else {
+ src2_r = 0;
+ if (flags & MOVE_OP) {
+ if (dst & SLJIT_MEM)
+ dst_r = 0;
+ else
+ op = SLJIT_MOV;
+ }
+ }
+ }
+ }
+ else {
+ if (getput_arg_fast(compiler, flags | LOAD_DATA, DR(src2_tmp_reg), src2, src2w))
+ FAIL_IF(compiler->error);
+ else
+ flags |= SLOW_SRC2;
+ src2_r = src2_tmp_reg;
+ }
+
+ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
+ SLJIT_ASSERT(src2_r == TMP_REG2);
+ if ((flags & SLOW_DEST) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
+ }
+ else {
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, src2, src2w));
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG2), src2, src2w, dst, dstw));
+ }
+ }
+ else if (flags & SLOW_SRC1)
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
+ else if (flags & SLOW_SRC2)
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, DR(src2_tmp_reg), src2, src2w, dst, dstw));
+
+ FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
+
+ if (dst & SLJIT_MEM) {
+ if (!(flags & SLOW_DEST)) {
+ getput_arg_fast(compiler, flags, DR(dst_r), dst, dstw);
+ return compiler->error;
+ }
+ return getput_arg(compiler, flags, DR(dst_r), dst, dstw, 0, 0);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+#undef CHECK_IMM
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
+{
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ sljit_s32 int_op = op & SLJIT_32;
+#endif
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op0(compiler, op));
+
+ op = GET_OPCODE(op);
+ switch (op) {
+ case SLJIT_BREAKPOINT:
+ return push_inst(compiler, BREAK, UNMOVABLE_INS);
+ case SLJIT_NOP:
+ return push_inst(compiler, NOP, UNMOVABLE_INS);
+ case SLJIT_LMUL_UW:
+ case SLJIT_LMUL_SW:
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
+#else /* !SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULU : MUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MUHU : MUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
+#endif /* SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
+ return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
+#else /* SLJIT_MIPS_REV < 6 */
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+#else /* !SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? MULTU : MULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+#endif /* SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
+ return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
+#endif /* SLJIT_MIPS_REV >= 6 */
+ case SLJIT_DIVMOD_UW:
+ case SLJIT_DIVMOD_SW:
+ case SLJIT_DIV_UW:
+ case SLJIT_DIV_SW:
+ SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (int_op) {
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
+ }
+ else {
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DMODU : DMOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
+ }
+#else /* !SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? MODU : MOD) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
+#endif /* SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
+ return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
+#else /* SLJIT_MIPS_REV < 6 */
+#if !(defined SLJIT_MIPS_REV)
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* !SLJIT_MIPS_REV */
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (int_op)
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+ else
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+#else /* !SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
+#endif /* SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
+ return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
+#endif /* SLJIT_MIPS_REV >= 6 */
+ case SLJIT_MEMORY_BARRIER:
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
+ return push_inst(compiler, SYNC, UNMOVABLE_INS);
+#else /* SLJIT_MIPS_REV < 1 */
+ return SLJIT_ERR_UNSUPPORTED;
+#endif /* SLJIT_MIPS_REV >= 1 */
+ case SLJIT_ENDBR:
+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
+ return SLJIT_SUCCESS;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
+static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+ if (!(src & OFFS_REG_MASK)) {
+ if (srcw <= SIMM_MAX && srcw >= SIMM_MIN)
+ return push_inst(compiler, PREF | S(src & REG_MASK) | IMM(srcw), MOVABLE_INS);
+
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
+ return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
+ }
+
+ srcw &= 0x3;
+
+ if (SLJIT_UNLIKELY(srcw != 0)) {
+ FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(src)) | D(TMP_REG1) | SH_IMM(srcw), DR(TMP_REG1)));
+ return push_inst(compiler, PREFX | S(src & REG_MASK) | T(TMP_REG1), MOVABLE_INS);
+ }
+
+ return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS);
+}
+#endif /* SLJIT_MIPS_REV >= 1 */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 flags = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (op & SLJIT_32)
+ flags = INT_DATA | SIGNED_DATA;
+#endif
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+#endif
+ case SLJIT_MOV_P:
+ return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw);
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ case SLJIT_MOV_U32:
+ return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw);
+
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s32)srcw : srcw);
+#endif
+
+ case SLJIT_MOV_U8:
+ return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);
+
+ case SLJIT_MOV_S8:
+ return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);
+
+ case SLJIT_MOV_U16:
+ return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);
+
+ case SLJIT_MOV_S16:
+ return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);
+
+ case SLJIT_CLZ:
+ case SLJIT_CTZ:
+ case SLJIT_REV:
+ return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+ return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+ return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+ }
+
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 flags = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (op & SLJIT_32) {
+ flags |= INT_DATA | SIGNED_DATA;
+ if (src1 == SLJIT_IMM)
+ src1w = (sljit_s32)src1w;
+ if (src2 == SLJIT_IMM)
+ src2w = (sljit_s32)src2w;
+ }
+#endif
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD:
+ case SLJIT_ADDC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_SUB:
+ case SLJIT_SUBC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_MUL:
+ compiler->status_flags_state = 0;
+ return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_XOR:
+ if ((src1 == SLJIT_IMM && src1w == -1) || (src2 == SLJIT_IMM && src2w == -1)) {
+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+ }
+ SLJIT_FALLTHROUGH
+ case SLJIT_AND:
+ case SLJIT_OR:
+ return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ case SLJIT_ROTL:
+ case SLJIT_ROTR:
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ if (src2 == SLJIT_IMM)
+ src2w &= 0x1f;
+#else
+ if (src2 == SLJIT_IMM) {
+ if (op & SLJIT_32)
+ src2w &= 0x1f;
+ else
+ src2w &= 0x3f;
+ }
+#endif
+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w);
+}
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+#define SELECT_OP3(op, src2w, D, D32, W) (((op & SLJIT_32) ? (W) : ((src2w) < 32) ? (D) : (D32)) | (((sljit_ins)src2w & 0x1f) << 6))
+#else /* !SLJIT_CONFIG_MIPS_64 */
+#define SELECT_OP3(op, src2w, D, D32, W) ((W) | ((sljit_ins)(src2w) << 6))
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MULADD:
+ SLJIT_SKIP_CHECKS(compiler);
+ FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));
+ return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(dst_reg) | T(TMP_REG2) | D(dst_reg), DR(dst_reg));
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1_reg,
+ sljit_s32 src2_reg,
+ sljit_s32 src3, sljit_sw src3w)
+{
+ sljit_s32 is_left;
+ sljit_ins ins1, ins2, ins3;
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
+ sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;
+#else /* !SLJIT_CONFIG_MIPS_64 */
+ sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
+ sljit_sw bit_length = 32;
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
+
+ is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);
+
+ if (src1_reg == src2_reg) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);
+ }
+
+ ADJUST_LOCAL_OFFSET(src3, src3w);
+
+ if (src3 == SLJIT_IMM) {
+ src3w &= bit_length - 1;
+
+ if (src3w == 0)
+ return SLJIT_SUCCESS;
+
+ if (is_left) {
+ ins1 = SELECT_OP3(op, src3w, DSLL, DSLL32, SLL);
+ src3w = bit_length - src3w;
+ ins2 = SELECT_OP3(op, src3w, DSRL, DSRL32, SRL);
+ } else {
+ ins1 = SELECT_OP3(op, src3w, DSRL, DSRL32, SRL);
+ src3w = bit_length - src3w;
+ ins2 = SELECT_OP3(op, src3w, DSLL, DSLL32, SLL);
+ }
+
+ FAIL_IF(push_inst(compiler, ins1 | T(src1_reg) | D(dst_reg), DR(dst_reg)));
+ FAIL_IF(push_inst(compiler, ins2 | T(src2_reg) | D(TMP_REG1), DR(TMP_REG1)));
+ return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg));
+ }
+
+ if (src3 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG2), src3, src3w));
+ src3 = TMP_REG2;
+ } else if (dst_reg == src3) {
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src3) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
+ src3 = TMP_REG2;
+ }
+
+ if (is_left) {
+ ins1 = SELECT_OP(DSRL, SRL);
+ ins2 = SELECT_OP(DSLLV, SLLV);
+ ins3 = SELECT_OP(DSRLV, SRLV);
+ } else {
+ ins1 = SELECT_OP(DSLL, SLL);
+ ins2 = SELECT_OP(DSRLV, SRLV);
+ ins3 = SELECT_OP(DSLLV, SLLV);
+ }
+
+ FAIL_IF(push_inst(compiler, ins2 | S(src3) | T(src1_reg) | D(dst_reg), DR(dst_reg)));
+
+ if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {
+ FAIL_IF(push_inst(compiler, ins1 | T(src2_reg) | D(TMP_REG1) | (1 << 6), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, XORI | S(src3) | T(TMP_REG2) | ((sljit_ins)bit_length - 1), DR(TMP_REG2)));
+ src2_reg = TMP_REG1;
+ } else
+ FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src3) | D(TMP_REG2), DR(TMP_REG2)));
+
+ FAIL_IF(push_inst(compiler, ins3 | S(TMP_REG2) | T(src2_reg) | D(TMP_REG1), DR(TMP_REG1)));
+ return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r, tmp_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);
+
+ if (src2 == SLJIT_IMM) {
+ src2w = (sljit_sw)((sljit_uw)src2w << shift_arg);
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));
+ src2 = TMP_REG2;
+ }
+
+ if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
+ src1 = TMP_REG1;
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
+ src1 = TMP_REG1;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ FAIL_IF(push_inst(compiler, (shift_arg >= 32 ? DSLL32 : DSLL) | T(src2) | D(tmp_r) | SH_IMM(shift_arg & 0x1f), DR(tmp_r)));
+#else /* !SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(tmp_r) | SH_IMM(shift_arg), DR(tmp_r)));
+#endif /* SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, ADDU_W | S(src1) | T(tmp_r) | D(dst_r), DR(dst_r)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, WORD_DATA, DR(dst_r), dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
+#undef SELECT_OP3
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ switch (op) {
+ case SLJIT_FAST_RETURN:
+ if (FAST_IS_REG(src)) {
+ if (DR(src) != RETURN_ADDR_REG)
+ FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
+ } else
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
+
+ FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ return push_inst(compiler, NOP, UNMOVABLE_INS);
+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
+ return SLJIT_SUCCESS;
+ case SLJIT_PREFETCH_L1:
+ case SLJIT_PREFETCH_L2:
+ case SLJIT_PREFETCH_L3:
+ case SLJIT_PREFETCH_ONCE:
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
+ return emit_prefetch(compiler, src, srcw);
+#else /* SLJIT_MIPS_REV < 1 */
+ return SLJIT_SUCCESS;
+#endif /* SLJIT_MIPS_REV >= 1 */
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 dst_ar = RETURN_ADDR_REG;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ switch (op) {
+ case SLJIT_FAST_ENTER:
+ if (FAST_IS_REG(dst)) {
+ if (DR(dst) == RETURN_ADDR_REG)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS);
+ }
+ break;
+ case SLJIT_GET_RETURN_ADDRESS:
+ dst_ar = DR(FAST_IS_REG(dst) ? dst : TMP_REG2);
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_ar, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw)));
+ break;
+ }
+
+ if (dst & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw));
+
+ if (op == SLJIT_FAST_ENTER)
+ compiler->delay_slot = UNMOVABLE_INS;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
+{
+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
+
+ if (type == SLJIT_GP_REGISTER)
+ return reg_map[reg];
+
+ if (type != SLJIT_FLOAT_REGISTER)
+ return -1;
+
+ return FR(reg);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_u32 size)
+{
+ SLJIT_UNUSED_ARG(size);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
+
+ return push_inst(compiler, *(sljit_ins*)instruction, UNMOVABLE_INS);
+}
+
+/* --------------------------------------------------------------------- */
+/* Floating point operators */
+/* --------------------------------------------------------------------- */
+
+#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))
+#define FMT(op) (FMT_S | (~(sljit_ins)op & SLJIT_32) << (21 - (5 + 3)))
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ sljit_u32 flags = 0;
+#else
+ sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;
+#endif
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
+ src = TMP_FREG1;
+ }
+
+ FAIL_IF(push_inst(compiler, (TRUNC_W_S ^ (flags >> 19)) | FMT(op) | FS(src) | FD(TMP_FREG1), MOVABLE_INS));
+
+ if (FAST_IS_REG(dst)) {
+ FAIL_IF(push_inst(compiler, MFC1 | flags | T(dst) | FS(TMP_FREG1), MOVABLE_INS));
+#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* MIPS III */
+ return SLJIT_SUCCESS;
+ }
+
+ return emit_op_mem2(compiler, flags ? DOUBLE_DATA : SINGLE_DATA, FR(TMP_FREG1), dst, dstw, 0, 0);
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ sljit_u32 flags = 0;
+#else
+ sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)) << 21;
+#endif
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (src & SLJIT_MEM)
+ FAIL_IF(emit_op_mem2(compiler, (flags ? DOUBLE_DATA : SINGLE_DATA) | LOAD_DATA, FR(TMP_FREG1), src, srcw, dst, dstw));
+ else {
+ if (src == SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
+ srcw = (sljit_s32)srcw;
+#endif
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
+ src = TMP_REG1;
+ }
+
+ FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
+#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* MIPS III */
+ }
+
+ FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ sljit_u32 flags = 0;
+#else
+ sljit_u32 flags = 1 << 21;
+#endif
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW ? WORD_DATA : INT_DATA) | LOAD_DATA, DR(TMP_REG1), src, srcw, dst, dstw));
+ src = TMP_REG1;
+ } else if (src == SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32)
+ srcw = (sljit_u32)srcw;
+#endif
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
+ src = TMP_REG1;
+ }
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {
+ if (src != TMP_REG1) {
+ FAIL_IF(push_inst(compiler, DSLL32 | T(src) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, DSRL32 | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(0), DR(TMP_REG1)));
+ }
+
+ FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
+#if !defined(SLJIT_MIPS_REV)
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* MIPS III */
+
+ FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+ }
+#else /* !SLJIT_CONFIG_MIPS_64 */
+ if (!(op & SLJIT_32)) {
+ FAIL_IF(push_inst(compiler, SLL | T(src) | D(TMP_REG2) | SH_IMM(1), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, SRL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(1), DR(TMP_REG2)));
+
+ FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG2) | FS(TMP_FREG1), MOVABLE_INS));
+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* MIPS III */
+
+ FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | 1 | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
+
+#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)
+ FAIL_IF(push_inst(compiler, BGEZ | S(src) | 5, UNMOVABLE_INS));
+#else /* SLJIT_MIPS_REV >= 1 */
+ FAIL_IF(push_inst(compiler, BGEZ | S(src) | 4, UNMOVABLE_INS));
+#endif /* SLJIT_MIPS_REV < 1 */
+
+ FAIL_IF(push_inst(compiler, LUI | T(TMP_REG2) | IMM(0x41e0), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, MTC1 | TA(0) | FS(TMP_FREG2), UNMOVABLE_INS));
+ switch (cpu_feature_list & CPU_FEATURE_FR) {
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+ case CPU_FEATURE_FR:
+ FAIL_IF(push_inst(compiler, MTHC1 | T(TMP_REG2) | FS(TMP_FREG2), UNMOVABLE_INS));
+ break;
+#endif /* SLJIT_MIPS_REV >= 2 */
+ default:
+ FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(TMP_FREG2) | (1 << 11), UNMOVABLE_INS));
+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* MIPS III */
+ break;
+ }
+ FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(TMP_FREG2) | FS(dst_r) | FD(dst_r), UNMOVABLE_INS));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+ }
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)
+ FAIL_IF(push_inst(compiler, BLTZ | S(src) | 5, UNMOVABLE_INS));
+#else /* SLJIT_MIPS_REV >= 1 */
+ FAIL_IF(push_inst(compiler, BLTZ | S(src) | 4, UNMOVABLE_INS));
+#endif /* SLJIT_MIPS_REV < 1 */
+ FAIL_IF(push_inst(compiler, ANDI | S(src) | T(TMP_REG2) | IMM(1), DR(TMP_REG2)));
+
+ FAIL_IF(push_inst(compiler, MTC1 | flags | T(src) | FS(TMP_FREG1), MOVABLE_INS));
+#if !defined(SLJIT_MIPS_REV)
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* !SLJIT_MIPS_REV */
+
+ FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
+
+#if (!defined SLJIT_MIPS_REV || SLJIT_MIPS_REV <= 1)
+ FAIL_IF(push_inst(compiler, BEQ | 6, UNMOVABLE_INS));
+#else /* SLJIT_MIPS_REV >= 1 */
+ FAIL_IF(push_inst(compiler, BEQ | 5, UNMOVABLE_INS));
+#endif /* SLJIT_MIPS_REV < 1 */
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ FAIL_IF(push_inst(compiler, DSRL | T(src) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));
+#else /* !SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, SRL | T(src) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+ FAIL_IF(push_inst(compiler, OR | S(TMP_REG1) | T(TMP_REG2) | D(TMP_REG1), DR(TMP_REG1)));
+
+ FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
+#if !defined(SLJIT_MIPS_REV)
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* !SLJIT_MIPS_REV */
+
+ FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((~(sljit_ins)op & SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(dst_r) | FS(dst_r) | FD(dst_r), UNMOVABLE_INS));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_ins inst;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
+ src1 = TMP_FREG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, 0, 0));
+ src2 = TMP_FREG2;
+ }
+
+ switch (GET_FLAG_TYPE(op)) {
+ case SLJIT_F_EQUAL:
+ case SLJIT_ORDERED_EQUAL:
+ inst = C_EQ_S;
+ break;
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_EQUAL:
+ inst = C_UEQ_S;
+ break;
+ case SLJIT_F_LESS:
+ case SLJIT_ORDERED_LESS:
+ inst = C_OLT_S;
+ break;
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_UNORDERED_OR_LESS:
+ inst = C_ULT_S;
+ break;
+ case SLJIT_F_GREATER:
+ case SLJIT_ORDERED_GREATER:
+ inst = C_ULE_S;
+ break;
+ case SLJIT_F_LESS_EQUAL:
+ case SLJIT_UNORDERED_OR_GREATER:
+ inst = C_OLE_S;
+ break;
+ default:
+ SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_UNORDERED);
+ inst = C_UN_S;
+ break;
+ }
+ return push_inst(compiler, inst | FMT(op) | FT(src2) | FS(src1) | C_FD, UNMOVABLE_INS);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
+
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
+ op ^= SLJIT_32;
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(dst_r), src, srcw, dst, dstw));
+ src = dst_r;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_F64:
+ if (src != dst_r) {
+ if (!(dst & SLJIT_MEM))
+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT(op)) | FS(src) | FD(dst_r), MOVABLE_INS));
+ else
+ dst_r = src;
+ }
+ break;
+ case SLJIT_NEG_F64:
+ FAIL_IF(push_inst(compiler, NEG_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
+ break;
+ case SLJIT_ABS_F64:
+ FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
+ break;
+ case SLJIT_CONV_F64_FROM_F32:
+ /* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */
+ FAIL_IF(push_inst(compiler, CVT_S_S | (sljit_ins)((op & SLJIT_32) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));
+ op ^= SLJIT_32;
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, FLOAT_DATA(op), FR(dst_r), dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 dst_r, flags = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
+
+ if (src1 & SLJIT_MEM) {
+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w)) {
+ FAIL_IF(compiler->error);
+ src1 = TMP_FREG1;
+ } else
+ flags |= SLOW_SRC1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w)) {
+ FAIL_IF(compiler->error);
+ src2 = TMP_FREG2;
+ } else
+ flags |= SLOW_SRC2;
+ }
+
+ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
+ if ((dst & SLJIT_MEM) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, src1, src1w));
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
+ } else {
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, src2, src2w));
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
+ }
+ }
+ else if (flags & SLOW_SRC1)
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG1), src1, src1w, dst, dstw));
+ else if (flags & SLOW_SRC2)
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, FR(TMP_FREG2), src2, src2w, dst, dstw));
+
+ if (flags & SLOW_SRC1)
+ src1 = TMP_FREG1;
+ if (flags & SLOW_SRC2)
+ src2 = TMP_FREG2;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD_F64:
+ FAIL_IF(push_inst(compiler, ADD_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
+ break;
+ case SLJIT_SUB_F64:
+ FAIL_IF(push_inst(compiler, SUB_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
+ break;
+ case SLJIT_MUL_F64:
+ FAIL_IF(push_inst(compiler, MUL_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
+ break;
+ case SLJIT_DIV_F64:
+ FAIL_IF(push_inst(compiler, DIV_S | FMT(op) | FT(src2) | FS(src1) | FD(dst_r), MOVABLE_INS));
+ break;
+ case SLJIT_COPYSIGN_F64:
+ return emit_copysign(compiler, op, src1, src2, dst_r);
+ }
+
+ if (dst_r == TMP_FREG2)
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG2), dst, dstw, 0, 0));
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f32 value)
+{
+ union {
+ sljit_s32 imm;
+ sljit_f32 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset32(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm == 0)
+ return push_inst(compiler, MTC1 | TA(0) | FS(freg), MOVABLE_INS);
+
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.imm));
+ return push_inst(compiler, MTC1 | T(TMP_REG1) | FS(freg), MOVABLE_INS);
+}
+
+/* --------------------------------------------------------------------- */
+/* Conditional instructions */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_label(compiler));
+
+ if (compiler->last_label && compiler->last_label->size == compiler->size)
+ return compiler->last_label;
+
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+ PTR_FAIL_IF(!label);
+ set_label(label, compiler);
+ compiler->delay_slot = UNMOVABLE_INS;
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, i;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (alignment <= SLJIT_LABEL_ALIGN_4) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);
+
+ for (i = (mask >> 2); i != 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ for (i = (buffers->size + 3) >> 2; i > 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#define BRANCH_LENGTH 4
+#else
+#define BRANCH_LENGTH 8
+#endif
+
+#define BR_Z(src) \
+ inst = BEQ | SA(src) | TA(0) | BRANCH_LENGTH; \
+ flags = IS_BIT26_COND; \
+ delay_check = src;
+
+#define BR_NZ(src) \
+ inst = BNE | SA(src) | TA(0) | BRANCH_LENGTH; \
+ flags = IS_BIT26_COND; \
+ delay_check = src;
+
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+
+#define BR_T() \
+ inst = BC1NEZ; \
+ flags = IS_BIT23_COND; \
+ delay_check = FCSR_FCC;
+#define BR_F() \
+ inst = BC1EQZ; \
+ flags = IS_BIT23_COND; \
+ delay_check = FCSR_FCC;
+
+#else /* SLJIT_MIPS_REV < 6 */
+
+#define BR_T() \
+ inst = BC1T | BRANCH_LENGTH; \
+ flags = IS_BIT16_COND; \
+ delay_check = FCSR_FCC;
+#define BR_F() \
+ inst = BC1F | BRANCH_LENGTH; \
+ flags = IS_BIT16_COND; \
+ delay_check = FCSR_FCC;
+
+#endif /* SLJIT_MIPS_REV >= 6 */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
+{
+ struct sljit_jump *jump;
+ sljit_ins inst;
+ sljit_u32 flags = 0;
+ sljit_s32 delay_check = UNMOVABLE_INS;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_jump(compiler, type));
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ type &= 0xff;
+
+ switch (type) {
+ case SLJIT_EQUAL:
+ BR_NZ(EQUAL_FLAG);
+ break;
+ case SLJIT_NOT_EQUAL:
+ BR_Z(EQUAL_FLAG);
+ break;
+ case SLJIT_LESS:
+ case SLJIT_GREATER:
+ case SLJIT_SIG_LESS:
+ case SLJIT_SIG_GREATER:
+ case SLJIT_OVERFLOW:
+ case SLJIT_CARRY:
+ case SLJIT_ATOMIC_STORED:
+ BR_Z(OTHER_FLAG);
+ break;
+ case SLJIT_GREATER_EQUAL:
+ case SLJIT_LESS_EQUAL:
+ case SLJIT_SIG_GREATER_EQUAL:
+ case SLJIT_SIG_LESS_EQUAL:
+ case SLJIT_NOT_OVERFLOW:
+ case SLJIT_NOT_CARRY:
+ case SLJIT_ATOMIC_NOT_STORED:
+ BR_NZ(OTHER_FLAG);
+ break;
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_F_GREATER:
+ case SLJIT_UNORDERED_OR_NOT_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:
+ case SLJIT_ORDERED_GREATER_EQUAL:
+ case SLJIT_ORDERED_GREATER:
+ case SLJIT_UNORDERED_OR_GREATER:
+ case SLJIT_ORDERED:
+ BR_T();
+ break;
+ case SLJIT_F_EQUAL:
+ case SLJIT_F_LESS:
+ case SLJIT_F_LESS_EQUAL:
+ case SLJIT_ORDERED_EQUAL:
+ case SLJIT_UNORDERED_OR_EQUAL:
+ case SLJIT_ORDERED_LESS:
+ case SLJIT_UNORDERED_OR_LESS:
+ case SLJIT_UNORDERED_OR_LESS_EQUAL:
+ case SLJIT_ORDERED_LESS_EQUAL:
+ case SLJIT_UNORDERED:
+ BR_F();
+ break;
+ default:
+ /* Not conditional branch. */
+ inst = 0;
+ break;
+ }
+
+ jump->flags |= flags;
+ if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != delay_check))
+ jump->flags |= IS_MOVABLE;
+
+ if (inst)
+ PTR_FAIL_IF(push_inst(compiler, inst, UNMOVABLE_INS));
+
+ if (type <= SLJIT_JUMP)
+ PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
+ else {
+ jump->flags |= IS_JAL;
+ PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ }
+
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+
+ /* Maximum number of instructions required for generating a constant. */
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ compiler->size += 2;
+#else
+ compiler->size += 6;
+#endif
+ return jump;
+}
+
+#define RESOLVE_IMM1() \
+ if (src1 == SLJIT_IMM) { \
+ if (src1w) { \
+ PTR_FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w)); \
+ src1 = TMP_REG1; \
+ } \
+ else \
+ src1 = 0; \
+ }
+
+#define RESOLVE_IMM2() \
+ if (src2 == SLJIT_IMM) { \
+ if (src2w) { \
+ PTR_FAIL_IF(load_immediate(compiler, DR(src2_tmp_reg), src2w)); \
+ src2 = src2_tmp_reg; \
+ } \
+ else \
+ src2 = 0; \
+ }
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ struct sljit_jump *jump;
+ sljit_s32 flags;
+ sljit_ins inst;
+ sljit_s32 src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ flags = WORD_DATA | LOAD_DATA;
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+ if (src1 & SLJIT_MEM) {
+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));
+ src1 = TMP_REG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(src2_tmp_reg), src2, src2w, 0, 0));
+ src2 = src2_tmp_reg;
+ }
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ type &= 0xff;
+
+ if (type <= SLJIT_NOT_EQUAL) {
+ RESOLVE_IMM1();
+ RESOLVE_IMM2();
+ jump->flags |= IS_BIT26_COND;
+ if (compiler->delay_slot == MOVABLE_INS || (compiler->delay_slot != UNMOVABLE_INS && compiler->delay_slot != DR(src1) && compiler->delay_slot != DR(src2)))
+ jump->flags |= IS_MOVABLE;
+ PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(src1) | T(src2) | BRANCH_LENGTH, UNMOVABLE_INS));
+ } else if (type >= SLJIT_SIG_LESS && ((src1 == SLJIT_IMM && src1w == 0) || (src2 == SLJIT_IMM && src2w == 0))) {
+ inst = NOP;
+ if (src1 == SLJIT_IMM && src1w == 0) {
+ RESOLVE_IMM2();
+ switch (type) {
+ case SLJIT_SIG_LESS:
+ inst = BLEZ;
+ jump->flags |= IS_BIT26_COND;
+ break;
+ case SLJIT_SIG_GREATER_EQUAL:
+ inst = BGTZ;
+ jump->flags |= IS_BIT26_COND;
+ break;
+ case SLJIT_SIG_GREATER:
+ inst = BGEZ;
+ jump->flags |= IS_BIT16_COND;
+ break;
+ case SLJIT_SIG_LESS_EQUAL:
+ inst = BLTZ;
+ jump->flags |= IS_BIT16_COND;
+ break;
+ }
+ src1 = src2;
+ }
+ else {
+ RESOLVE_IMM1();
+ switch (type) {
+ case SLJIT_SIG_LESS:
+ inst = BGEZ;
+ jump->flags |= IS_BIT16_COND;
+ break;
+ case SLJIT_SIG_GREATER_EQUAL:
+ inst = BLTZ;
+ jump->flags |= IS_BIT16_COND;
+ break;
+ case SLJIT_SIG_GREATER:
+ inst = BLEZ;
+ jump->flags |= IS_BIT26_COND;
+ break;
+ case SLJIT_SIG_LESS_EQUAL:
+ inst = BGTZ;
+ jump->flags |= IS_BIT26_COND;
+ break;
+ }
+ }
+ PTR_FAIL_IF(push_inst(compiler, inst | S(src1) | BRANCH_LENGTH, UNMOVABLE_INS));
+ }
+ else {
+ if (type == SLJIT_LESS || type == SLJIT_GREATER_EQUAL || type == SLJIT_SIG_LESS || type == SLJIT_SIG_GREATER_EQUAL) {
+ RESOLVE_IMM1();
+ if (src2 == SLJIT_IMM && src2w <= SIMM_MAX && src2w >= SIMM_MIN)
+ PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src1) | T(TMP_REG1) | IMM(src2w), DR(TMP_REG1)));
+ else {
+ RESOLVE_IMM2();
+ PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src1) | T(src2) | D(TMP_REG1), DR(TMP_REG1)));
+ }
+ type = (type == SLJIT_LESS || type == SLJIT_SIG_LESS) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
+ }
+ else {
+ RESOLVE_IMM2();
+ if (src1 == SLJIT_IMM && src1w <= SIMM_MAX && src1w >= SIMM_MIN)
+ PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTIU : SLTI) | S(src2) | T(TMP_REG1) | IMM(src1w), DR(TMP_REG1)));
+ else {
+ RESOLVE_IMM1();
+ PTR_FAIL_IF(push_inst(compiler, (type <= SLJIT_LESS_EQUAL ? SLTU : SLT) | S(src2) | T(src1) | D(TMP_REG1), DR(TMP_REG1)));
+ }
+ type = (type == SLJIT_GREATER || type == SLJIT_SIG_GREATER) ? SLJIT_NOT_EQUAL : SLJIT_EQUAL;
+ }
+
+ jump->flags |= IS_BIT26_COND;
+ PTR_FAIL_IF(push_inst(compiler, (type == SLJIT_EQUAL ? BNE : BEQ) | S(TMP_REG1) | TA(0) | BRANCH_LENGTH, UNMOVABLE_INS));
+ }
+
+ PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+
+ /* Maximum number of instructions required for generating a constant. */
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ compiler->size += 2;
+#else
+ compiler->size += 6;
+#endif
+ return jump;
+}
+
+#undef RESOLVE_IMM1
+#undef RESOLVE_IMM2
+
+#undef BRANCH_LENGTH
+#undef BR_Z
+#undef BR_NZ
+#undef BR_T
+#undef BR_F
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
+{
+ struct sljit_jump *jump = NULL;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
+
+ if (src == SLJIT_IMM) {
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF(!jump);
+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));
+ jump->u.target = (sljit_uw)srcw;
+
+ if (compiler->delay_slot != UNMOVABLE_INS)
+ jump->flags |= IS_MOVABLE;
+
+ src = PIC_ADDR_REG;
+ } else if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
+ src = PIC_ADDR_REG;
+ }
+
+ if (type <= SLJIT_JUMP)
+ FAIL_IF(push_inst(compiler, JR | S(src), UNMOVABLE_INS));
+ else
+ FAIL_IF(push_inst(compiler, JALR | S(src) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+
+ if (jump != NULL) {
+ jump->addr = compiler->size;
+
+ /* Maximum number of instructions required for generating a constant. */
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ compiler->size += 2;
+#else
+ compiler->size += 6;
+#endif
+ }
+
+ return push_inst(compiler, NOP, UNMOVABLE_INS);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 type)
+{
+ sljit_s32 src_ar, dst_ar, invert;
+ sljit_s32 saved_op = op;
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ sljit_s32 mem_type = WORD_DATA;
+#else
+ sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
+#endif
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ op = GET_OPCODE(op);
+ dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
+ FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, DR(TMP_REG1), dst, dstw, dst, dstw));
+
+ if (type < SLJIT_F_EQUAL) {
+ src_ar = OTHER_FLAG;
+ invert = type & 0x1;
+
+ switch (type) {
+ case SLJIT_EQUAL:
+ case SLJIT_NOT_EQUAL:
+ FAIL_IF(push_inst(compiler, SLTIU | SA(EQUAL_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
+ src_ar = dst_ar;
+ break;
+ case SLJIT_OVERFLOW:
+ case SLJIT_NOT_OVERFLOW:
+ if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {
+ src_ar = OTHER_FLAG;
+ break;
+ }
+ FAIL_IF(push_inst(compiler, SLTIU | SA(OTHER_FLAG) | TA(dst_ar) | IMM(1), dst_ar));
+ src_ar = dst_ar;
+ invert ^= 0x1;
+ break;
+ }
+ } else {
+ invert = 0;
+
+ switch (type) {
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_F_GREATER:
+ case SLJIT_UNORDERED_OR_NOT_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:
+ case SLJIT_ORDERED_GREATER_EQUAL:
+ case SLJIT_ORDERED_GREATER:
+ case SLJIT_UNORDERED_OR_GREATER:
+ case SLJIT_ORDERED:
+ invert = 1;
+ break;
+ }
+
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+ FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar));
+#else /* SLJIT_MIPS_REV < 6 */
+ FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));
+#endif /* SLJIT_MIPS_REV >= 6 */
+ FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar));
+ FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar));
+ src_ar = dst_ar;
+ }
+
+ if (invert) {
+ FAIL_IF(push_inst(compiler, XORI | SA(src_ar) | TA(dst_ar) | IMM(1), dst_ar));
+ src_ar = dst_ar;
+ }
+
+ if (op < SLJIT_ADD) {
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, mem_type, src_ar, dst, dstw);
+
+ if (src_ar != dst_ar)
+ return push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | DA(dst_ar), dst_ar);
+ return SLJIT_SUCCESS;
+ }
+
+ /* OTHER_FLAG cannot be specified as src2 argument at the moment. */
+ if (DR(TMP_REG2) != src_ar)
+ FAIL_IF(push_inst(compiler, ADDU_W | SA(src_ar) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
+
+ mem_type |= CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE;
+
+ if (dst & SLJIT_MEM)
+ return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
+ return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, TMP_REG2, 0);
+}
+
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
+
+static sljit_ins get_select_cc(sljit_s32 type, sljit_s32 is_float)
+{
+ switch (type) {
+ case SLJIT_EQUAL:
+ return (is_float ? MOVZ_S : MOVZ) | TA(EQUAL_FLAG);
+ case SLJIT_NOT_EQUAL:
+ return (is_float ? MOVN_S : MOVN) | TA(EQUAL_FLAG);
+ case SLJIT_LESS:
+ case SLJIT_GREATER:
+ case SLJIT_SIG_LESS:
+ case SLJIT_SIG_GREATER:
+ case SLJIT_OVERFLOW:
+ case SLJIT_CARRY:
+ return (is_float ? MOVN_S : MOVN) | TA(OTHER_FLAG);
+ case SLJIT_GREATER_EQUAL:
+ case SLJIT_LESS_EQUAL:
+ case SLJIT_SIG_GREATER_EQUAL:
+ case SLJIT_SIG_LESS_EQUAL:
+ case SLJIT_NOT_OVERFLOW:
+ case SLJIT_NOT_CARRY:
+ return (is_float ? MOVZ_S : MOVZ) | TA(OTHER_FLAG);
+ case SLJIT_F_EQUAL:
+ case SLJIT_F_LESS:
+ case SLJIT_F_LESS_EQUAL:
+ case SLJIT_ORDERED_EQUAL:
+ case SLJIT_UNORDERED_OR_EQUAL:
+ case SLJIT_ORDERED_LESS:
+ case SLJIT_UNORDERED_OR_LESS:
+ case SLJIT_UNORDERED_OR_LESS_EQUAL:
+ case SLJIT_ORDERED_LESS_EQUAL:
+ case SLJIT_UNORDERED:
+ return is_float ? MOVT_S : MOVT;
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_F_GREATER:
+ case SLJIT_UNORDERED_OR_NOT_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:
+ case SLJIT_ORDERED_GREATER_EQUAL:
+ case SLJIT_ORDERED_GREATER:
+ case SLJIT_UNORDERED_OR_GREATER:
+ case SLJIT_ORDERED:
+ return is_float ? MOVF_S : MOVF;
+ default:
+ SLJIT_UNREACHABLE();
+ return (is_float ? MOVZ_S : MOVZ) | TA(OTHER_FLAG);
+ }
+}
+
+#endif /* SLJIT_MIPS_REV >= 1 */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_reg)
+{
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
+ sljit_ins mov_ins = (type & SLJIT_32) ? ADDU : DADDU;
+#else /* !SLJIT_CONFIG_MIPS_64 */
+ sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
+ sljit_ins mov_ins = ADDU;
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+#endif /* !(SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (src1 == SLJIT_IMM && (type & SLJIT_32))
+ src1w = (sljit_s32)src1w;
+#endif
+
+ type &= ~SLJIT_32;
+
+ if (type & SLJIT_COMPARE_SELECT) {
+ type ^= SLJIT_COMPARE_SELECT;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG1), src1, src1w));
+ src1 = TMP_REG1;
+ } else if (src1 == SLJIT_IMM) {
+ if (src1w == 0) {
+ src1 = 0;
+ } else {
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
+ src1 = TMP_REG1;
+ }
+ }
+
+ src1w = 0;
+ FAIL_IF(emit_op(compiler, SLJIT_SUB | SLJIT_SET(type & ~0x1), IMM_OP, 0, 0, src1, 0, src2_reg, 0));
+ }
+
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG1), src1, src1w));
+ src1 = TMP_REG1;
+ } else if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
+ src1 = TMP_REG1;
+ }
+
+ if (dst_reg != src2_reg) {
+ if (dst_reg == src1) {
+ src1 = src2_reg;
+ type ^= 0x1;
+ } else
+ FAIL_IF(push_inst(compiler, mov_ins | S(src2_reg) | TA(0) | D(dst_reg), DR(dst_reg)));
+ }
+
+ return push_inst(compiler, get_select_cc(type, 0) | S(src1) | D(dst_reg), DR(dst_reg));
+
+#else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */
+ if (dst_reg != src2_reg) {
+ if (dst_reg == src1) {
+ src1 = src2_reg;
+ src1w = 0;
+ type ^= 0x1;
+ } else {
+ if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
+ FAIL_IF(push_inst(compiler, ADDU_W | S(dst_reg) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
+
+ if ((src1 & REG_MASK) == dst_reg)
+ src1 = (src1 & ~REG_MASK) | TMP_REG1;
+
+ if (OFFS_REG(src1) == dst_reg)
+ src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);
+ }
+
+ FAIL_IF(push_inst(compiler, mov_ins | S(src2_reg) | TA(0) | D(dst_reg), DR(dst_reg)));
+ }
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ jump = sljit_emit_jump(compiler, type ^ 0x1);
+ FAIL_IF(!jump);
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, DR(dst_reg), src1, src1w));
+ } else if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, DR(dst_reg), src1w));
+ } else
+ FAIL_IF(push_inst(compiler, mov_ins | S(src1) | TA(0) | D(dst_reg), DR(dst_reg)));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ FAIL_IF(!label);
+
+ sljit_set_label(jump, label);
+ return SLJIT_SUCCESS;
+#endif /* SLJIT_MIPS_REV >= 1 */
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_freg)
+{
+#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+#endif /* !(SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ if (dst_freg != src2_freg) {
+ if (dst_freg == src1) {
+ src1 = src2_freg;
+ src1w = 0;
+ type ^= 0x1;
+ } else
+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT(type)) | FS(src2_freg) | FD(dst_freg), MOVABLE_INS));
+ }
+
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, FR(TMP_FREG2), src1, src1w));
+ src1 = TMP_FREG2;
+ }
+
+ return push_inst(compiler, get_select_cc(type & ~SLJIT_32, 1) | FMT(type) | FS(src1) | FD(dst_freg), MOVABLE_INS);
+
+#else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */
+ SLJIT_SKIP_CHECKS(compiler);
+ jump = sljit_emit_jump(compiler, type ^ 0x1);
+ FAIL_IF(!jump);
+
+ if (src1 & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, FR(dst_freg), src1, src1w));
+ else
+ FAIL_IF(push_inst(compiler, MOV_fmt(FMT(type)) | FS(src1) | FD(dst_freg), MOVABLE_INS));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ FAIL_IF(!label);
+
+ sljit_set_label(jump, label);
+ return SLJIT_SUCCESS;
+#endif /* SLJIT_MIPS_REV >= 1 */
+}
+
+#undef FLOAT_DATA
+#undef FMT
+
+static sljit_s32 update_mem_addr(struct sljit_compiler *compiler, sljit_s32 *mem, sljit_sw *memw, sljit_s16 max_offset)
+{
+ sljit_s32 arg = *mem;
+ sljit_sw argw = *memw;
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ argw &= 0x3;
+
+ if (SLJIT_UNLIKELY(argw)) {
+ FAIL_IF(push_inst(compiler, SLL_W | T(OFFS_REG(arg)) | D(TMP_REG1) | SH_IMM(argw), DR(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1)));
+ } else
+ FAIL_IF(push_inst(compiler, ADDU_W | S(arg & REG_MASK) | T(OFFS_REG(arg)) | D(TMP_REG1), DR(TMP_REG1)));
+
+ *mem = TMP_REG1;
+ *memw = 0;
+
+ return SLJIT_SUCCESS;
+ }
+
+ if (argw <= max_offset && argw >= SIMM_MIN) {
+ *mem = arg & REG_MASK;
+ return SLJIT_SUCCESS;
+ }
+
+ *mem = TMP_REG1;
+
+ if ((sljit_s16)argw > max_offset) {
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), argw));
+ *memw = 0;
+ } else {
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), TO_ARGW_HI(argw)));
+ *memw = (sljit_s16)argw;
+ }
+
+ if ((arg & REG_MASK) == 0)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, ADDU_W | S(TMP_REG1) | T(arg & REG_MASK) | D(TMP_REG1), DR(TMP_REG1));
+}
+
+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
+#define IMM_LEFT(memw) IMM((memw) + SSIZE_OF(sw) - 1)
+#define IMM_RIGHT(memw) IMM(memw)
+#define IMM_32_LEFT(memw) IMM((memw) + SSIZE_OF(s32) - 1)
+#define IMM_32_RIGHT(memw) IMM(memw)
+#define IMM_F64_FIRST_LEFT(memw) IMM((memw) + SSIZE_OF(s32) - 1)
+#define IMM_F64_FIRST_RIGHT(memw) IMM(memw)
+#define IMM_F64_SECOND_LEFT(memw) IMM((memw) + SSIZE_OF(f64) - 1)
+#define IMM_F64_SECOND_RIGHT(memw) IMM((memw) + SSIZE_OF(s32))
+#define IMM_16_FIRST(memw) IMM((memw) + 1)
+#define IMM_16_SECOND(memw) IMM(memw)
+#else /* !SLJIT_LITTLE_ENDIAN */
+#define IMM_LEFT(memw) IMM(memw)
+#define IMM_RIGHT(memw) IMM((memw) + SSIZE_OF(sw) - 1)
+#define IMM_32_LEFT(memw) IMM(memw)
+#define IMM_32_RIGHT(memw) IMM((memw) + SSIZE_OF(s32) - 1)
+#define IMM_F64_FIRST_LEFT(memw) IMM((memw) + SSIZE_OF(s32))
+#define IMM_F64_FIRST_RIGHT(memw) IMM((memw) + SSIZE_OF(f64) - 1)
+#define IMM_F64_SECOND_LEFT(memw) IMM(memw)
+#define IMM_F64_SECOND_RIGHT(memw) IMM((memw) + SSIZE_OF(s32) - 1)
+#define IMM_16_FIRST(memw) IMM(memw)
+#define IMM_16_SECOND(memw) IMM((memw) + 1)
+#endif /* SLJIT_LITTLE_ENDIAN */
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16))
+#else /* !SLJIT_CONFIG_MIPS_32 */
+#define MEM_CHECK_UNALIGNED(type) ((type) & (SLJIT_MEM_UNALIGNED | SLJIT_MEM_ALIGNED_16 | SLJIT_MEM_ALIGNED_32))
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_s32 op = type & 0xff;
+ sljit_s32 flags = 0;
+ sljit_ins ins;
+#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+ sljit_ins ins_right;
+#endif /* !(SLJIT_MIPS_REV >= 6) */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
+
+ if (reg & REG_PAIR_MASK) {
+ ADJUST_LOCAL_OFFSET(mem, memw);
+
+#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+ if (MEM_CHECK_UNALIGNED(type)) {
+ FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (2 * SSIZE_OF(sw) - 1)));
+
+ if (!(type & SLJIT_MEM_STORE) && (mem == REG_PAIR_FIRST(reg) || mem == REG_PAIR_SECOND(reg))) {
+ FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
+ mem = TMP_REG1;
+ }
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ ins = ((type & SLJIT_MEM_STORE) ? SWL : LWL) | S(mem);
+ ins_right = ((type & SLJIT_MEM_STORE) ? SWR : LWR) | S(mem);
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ ins = ((type & SLJIT_MEM_STORE) ? SDL : LDL) | S(mem);
+ ins_right = ((type & SLJIT_MEM_STORE) ? SDR : LDR) | S(mem);
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+ FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM_LEFT(memw), DR(REG_PAIR_FIRST(reg))));
+ FAIL_IF(push_inst(compiler, ins_right | T(REG_PAIR_FIRST(reg)) | IMM_RIGHT(memw), DR(REG_PAIR_FIRST(reg))));
+ FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM_LEFT(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))));
+ return push_inst(compiler, ins_right | T(REG_PAIR_SECOND(reg)) | IMM_RIGHT(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)));
+ }
+#endif /* !(SLJIT_MIPS_REV >= 6) */
+
+ FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - SSIZE_OF(sw)));
+
+ ins = ((type & SLJIT_MEM_STORE) ? STORE_W : LOAD_W) | S(mem);
+
+ if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {
+ FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg))));
+ return push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg)));
+ }
+
+ FAIL_IF(push_inst(compiler, ins | T(REG_PAIR_FIRST(reg)) | IMM(memw), DR(REG_PAIR_FIRST(reg))));
+ return push_inst(compiler, ins | T(REG_PAIR_SECOND(reg)) | IMM(memw + SSIZE_OF(sw)), DR(REG_PAIR_SECOND(reg)));
+ }
+
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
+#else /* !(SLJIT_MIPS_REV >= 6) */
+ ADJUST_LOCAL_OFFSET(mem, memw);
+
+ switch (op) {
+ case SLJIT_MOV_U8:
+ case SLJIT_MOV_S8:
+ flags = BYTE_DATA;
+ if (!(type & SLJIT_MEM_STORE))
+ flags |= LOAD_DATA;
+
+ if (op == SLJIT_MOV_S8)
+ flags |= SIGNED_DATA;
+
+ return emit_op_mem(compiler, flags, DR(reg), mem, memw);
+
+ case SLJIT_MOV_U16:
+ case SLJIT_MOV_S16:
+ FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 1));
+ SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
+
+ if (type & SLJIT_MEM_STORE) {
+ FAIL_IF(push_inst(compiler, SRA_W | T(reg) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(TMP_REG2) | IMM_16_FIRST(memw), MOVABLE_INS));
+ return push_inst(compiler, data_transfer_insts[BYTE_DATA] | S(mem) | T(reg) | IMM_16_SECOND(memw), MOVABLE_INS);
+ }
+
+ flags = BYTE_DATA | LOAD_DATA;
+
+ if (op == SLJIT_MOV_S16)
+ flags |= SIGNED_DATA;
+
+ FAIL_IF(push_inst(compiler, data_transfer_insts[flags] | S(mem) | T(TMP_REG2) | IMM_16_FIRST(memw), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, data_transfer_insts[BYTE_DATA | LOAD_DATA] | S(mem) | T(reg) | IMM_16_SECOND(memw), DR(reg)));
+ FAIL_IF(push_inst(compiler, SLL_W | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(8), DR(TMP_REG2)));
+ return push_inst(compiler, OR | S(reg) | T(TMP_REG2) | D(reg), DR(reg));
+
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ if (type & SLJIT_MEM_ALIGNED_32) {
+ flags = WORD_DATA;
+ if (!(type & SLJIT_MEM_STORE))
+ flags |= LOAD_DATA;
+
+ return emit_op_mem(compiler, flags, DR(reg), mem, memw);
+ }
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 7));
+ SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
+
+ if (type & SLJIT_MEM_STORE) {
+ FAIL_IF(push_inst(compiler, SDL | S(mem) | T(reg) | IMM_LEFT(memw), MOVABLE_INS));
+ return push_inst(compiler, SDR | S(mem) | T(reg) | IMM_RIGHT(memw), MOVABLE_INS);
+ }
+
+ if (mem == reg) {
+ FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
+ mem = TMP_REG1;
+ }
+
+ FAIL_IF(push_inst(compiler, LDL | S(mem) | T(reg) | IMM_LEFT(memw), DR(reg)));
+ return push_inst(compiler, LDR | S(mem) | T(reg) | IMM_RIGHT(memw), DR(reg));
+#endif /* SLJIT_CONFIG_MIPS_32 */
+ }
+
+ FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - 3));
+ SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
+
+ if (type & SLJIT_MEM_STORE) {
+ FAIL_IF(push_inst(compiler, SWL | S(mem) | T(reg) | IMM_32_LEFT(memw), MOVABLE_INS));
+ return push_inst(compiler, SWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), MOVABLE_INS);
+ }
+
+ if (mem == reg) {
+ FAIL_IF(push_inst(compiler, ADDU_W | S(mem) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
+ mem = TMP_REG1;
+ }
+
+ FAIL_IF(push_inst(compiler, LWL | S(mem) | T(reg) | IMM_32_LEFT(memw), DR(reg)));
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ return push_inst(compiler, LWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), DR(reg));
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ FAIL_IF(push_inst(compiler, LWR | S(mem) | T(reg) | IMM_32_RIGHT(memw), DR(reg)));
+
+ if (op != SLJIT_MOV_U32)
+ return SLJIT_SUCCESS;
+
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
+ return push_inst(compiler, DINSU | T(reg) | SA(0) | (31 << 11), DR(reg));
+#else /* SLJIT_MIPS_REV < 2 */
+ FAIL_IF(push_inst(compiler, DSLL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg)));
+ return push_inst(compiler, DSRL32 | T(reg) | D(reg) | SH_IMM(0), DR(reg));
+#endif /* SLJIT_MIPS_REV >= 2 */
+#endif /* SLJIT_CONFIG_MIPS_32 */
+#endif /* SLJIT_MIPS_REV >= 6 */
+}
+
+#if !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 freg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
+
+ FAIL_IF(update_mem_addr(compiler, &mem, &memw, SIMM_MAX - (type & SLJIT_32) ? 3 : 7));
+ SLJIT_ASSERT(FAST_IS_REG(mem) && mem != TMP_REG2);
+
+ if (type & SLJIT_MEM_STORE) {
+ if (type & SLJIT_32) {
+ FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
+#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* MIPS III */
+ FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_32_LEFT(memw), MOVABLE_INS));
+ return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_32_RIGHT(memw), MOVABLE_INS);
+ }
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* MIPS III */
+ FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_LEFT(memw), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_RIGHT(memw), MOVABLE_INS));
+ switch (cpu_feature_list & CPU_FEATURE_FR) {
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+ case CPU_FEATURE_FR:
+ FAIL_IF(push_inst(compiler, MFHC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
+ break;
+#endif /* SLJIT_MIPS_REV >= 2 */
+ default:
+ FAIL_IF(push_inst(compiler, MFC1 | T(TMP_REG2) | FS(freg) | (1 << 11), DR(TMP_REG2)));
+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif
+ break;
+ }
+
+ FAIL_IF(push_inst(compiler, SWL | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_LEFT(memw), MOVABLE_INS));
+ return push_inst(compiler, SWR | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_RIGHT(memw), MOVABLE_INS);
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ FAIL_IF(push_inst(compiler, DMFC1 | T(TMP_REG2) | FS(freg), DR(TMP_REG2)));
+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* MIPS III */
+ FAIL_IF(push_inst(compiler, SDL | S(mem) | T(TMP_REG2) | IMM_LEFT(memw), MOVABLE_INS));
+ return push_inst(compiler, SDR | S(mem) | T(TMP_REG2) | IMM_RIGHT(memw), MOVABLE_INS);
+#endif /* SLJIT_CONFIG_MIPS_32 */
+ }
+
+ if (type & SLJIT_32) {
+ FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_32_LEFT(memw), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_32_RIGHT(memw), DR(TMP_REG2)));
+
+ FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));
+#if !defined(SLJIT_MIPS_REV) || (SLJIT_CONFIG_MIPS_32 && SLJIT_MIPS_REV <= 1)
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* MIPS III */
+ return SLJIT_SUCCESS;
+ }
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_LEFT(memw), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_F64_FIRST_RIGHT(memw), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));
+
+ FAIL_IF(push_inst(compiler, LWL | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_LEFT(memw), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, LWR | S(mem) | T(TMP_REG2) | IMM_F64_SECOND_RIGHT(memw), DR(TMP_REG2)));
+ switch (cpu_feature_list & CPU_FEATURE_FR) {
+#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
+ case CPU_FEATURE_FR:
+ return push_inst(compiler, MTHC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS);
+#endif /* SLJIT_MIPS_REV >= 2 */
+ default:
+ FAIL_IF(push_inst(compiler, MTC1 | T(TMP_REG2) | FS(freg) | (1 << 11), MOVABLE_INS));
+ break;
+ }
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ FAIL_IF(push_inst(compiler, LDL | S(mem) | T(TMP_REG2) | IMM_LEFT(memw), DR(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, LDR | S(mem) | T(TMP_REG2) | IMM_RIGHT(memw), DR(TMP_REG2)));
+
+ FAIL_IF(push_inst(compiler, DMTC1 | T(TMP_REG2) | FS(freg), MOVABLE_INS));
+#endif /* SLJIT_CONFIG_MIPS_32 */
+#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
+ FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+#endif /* MIPS III */
+ return SLJIT_SUCCESS;
+}
+
+#endif /* !SLJIT_MIPS_REV || SLJIT_MIPS_REV < 6 */
+
+#undef IMM_16_SECOND
+#undef IMM_16_FIRST
+#undef IMM_F64_SECOND_RIGHT
+#undef IMM_F64_SECOND_LEFT
+#undef IMM_F64_FIRST_RIGHT
+#undef IMM_F64_FIRST_LEFT
+#undef IMM_32_RIGHT
+#undef IMM_32_LEFT
+#undef IMM_RIGHT
+#undef IMM_LEFT
+#undef MEM_CHECK_UNALIGNED
+
+#undef TO_ARGW_HI
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 mem_reg)
+{
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));
+
+ if (op & SLJIT_ATOMIC_USE_CAS)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ ins = LLD;
+ break;
+#endif /* SLJIT_CONFIG_MIPS_64 */
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ ins = LL;
+ break;
+
+ default:
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, ins | T(dst_reg) | S(mem_reg), DR(dst_reg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src_reg,
+ sljit_s32 mem_reg,
+ sljit_s32 temp_reg)
+{
+ sljit_ins ins;
+
+ /* temp_reg == mem_reg is undefined so use another temp register */
+ SLJIT_UNUSED_ARG(temp_reg);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));
+
+ if (op & SLJIT_ATOMIC_USE_CAS)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ ins = SCD;
+ break;
+#endif /* SLJIT_CONFIG_MIPS_64 */
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ op |= SLJIT_32;
+ ins = SC;
+ break;
+
+ default:
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src_reg) | TA(0) | DA(OTHER_FLAG), OTHER_FLAG));
+ return push_inst(compiler, ins | TA(OTHER_FLAG) | S(mem_reg), OTHER_FLAG);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
+{
+ struct sljit_const *const_;
+ sljit_s32 dst_r;
+ sljit_s32 mem_flags = WORD_DATA;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+ PTR_FAIL_IF(!const_);
+ set_const(const_, compiler);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ if (init_value & 0x100)
+ init_value |= 0xff00;
+ else
+ init_value &= 0xff;
+
+ PTR_FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(dst_r) | IMM(init_value), DR(dst_r)));
+ mem_flags = BYTE_DATA;
+ break;
+
+#if (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64)
+ case SLJIT_MOV32:
+ mem_flags = INT_DATA;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_S32:
+ PTR_FAIL_IF(push_inst(compiler, LUI | T(dst_r) | IMM(init_value >> 16), DR(dst_r)));
+ PTR_FAIL_IF(push_inst(compiler, ORI | S(dst_r) | T(dst_r) | IMM(init_value), DR(dst_r)));
+ break;
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+ default:
+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, DR(TMP_REG2), dst, dstw));
+
+ return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_jump *jump;
+ sljit_s32 dst_r, target_r;
+ SLJIT_UNUSED_ARG(op);
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = TMP_REG1;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), dst, dstw));
+ }
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_mov_addr(jump, compiler, 0);
+
+ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)target_r, UNMOVABLE_INS));
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ compiler->size += 1;
+#else
+ compiler->size += 5;
+#endif
+
+ if (op == SLJIT_ADD_ABS_ADDR)
+ PTR_FAIL_IF(push_inst(compiler, ADDU_W | S(dst_r) | T(TMP_REG1) | D(dst_r), DR(dst_r)));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));
+
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
+{
+ sljit_ins *inst;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xfc000000) == ADDIU);
+
+ if (new_constant & 0x100)
+ new_constant |= 0xff00;
+ else
+ new_constant &= 0xff;
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_constant);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
+ return;
+
+#if (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64)
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_constant >> 16);
+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_constant);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ return;
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+ default:
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ return;
+ }
+}
diff --git a/deps/sljit/sljit_src/sljitNativePPC_32.c b/deps/sljit/sljit_src/sljitNativePPC_32.c
new file mode 100644
index 0000000..c07f4b4
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativePPC_32.c
@@ -0,0 +1,485 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* ppc 32-bit arch dependent functions. */
+
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
+{
+ if (imm <= SIMM_MAX && imm >= SIMM_MIN)
+ return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
+
+ if (!(imm & ~0xffff))
+ return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
+
+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
+ return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
+}
+
+/* Simplified mnemonics: clrlwi. */
+#define INS_CLEAR_LEFT(dst, src, from) \
+ (RLWINM | S(src) | A(dst) | RLWI_MBE(from, 31))
+
+static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+ sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
+{
+ sljit_u32 imm;
+
+ switch (op) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV_P:
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ if (dst != src2)
+ return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_U8:
+ case SLJIT_MOV_S8:
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (op == SLJIT_MOV_S8)
+ return push_inst(compiler, EXTSB | S(src2) | A(dst));
+ return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
+ }
+ else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)
+ return push_inst(compiler, EXTSB | S(src2) | A(dst));
+ else {
+ SLJIT_ASSERT(dst == src2);
+ }
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_U16:
+ case SLJIT_MOV_S16:
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (op == SLJIT_MOV_S16)
+ return push_inst(compiler, EXTSH | S(src2) | A(dst));
+ return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
+ }
+ else {
+ SLJIT_ASSERT(dst == src2);
+ }
+ return SLJIT_SUCCESS;
+
+ case SLJIT_CLZ:
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ return push_inst(compiler, CNTLZW | S(src2) | A(dst));
+
+ case SLJIT_CTZ:
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2)));
+ FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, CNTLZW | S(dst) | A(dst)));
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM(-32)));
+ /* The highest bits are set, if dst < 32, zero otherwise. */
+ FAIL_IF(push_inst(compiler, SRWI(27) | S(TMP_REG1) | A(TMP_REG1)));
+ return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1));
+
+ case SLJIT_ADD:
+ if (flags & ALT_FORM1) {
+ /* Setting XER SO is not enough, CR SO is also needed. */
+ return push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
+ }
+
+ if (flags & ALT_FORM2) {
+ /* Flags does not set: BIN_IMM_EXTS unnecessary. */
+ SLJIT_ASSERT(src2 == TMP_REG2);
+
+ if (flags & ALT_FORM3)
+ return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
+
+ imm = compiler->imm;
+
+ if (flags & ALT_FORM4) {
+ FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1))));
+ src1 = dst;
+ }
+
+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff));
+ }
+ if (flags & ALT_FORM3) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
+ }
+ SLJIT_ASSERT(!(flags & ALT_FORM4));
+ if (!(flags & ALT_SET_FLAGS))
+ return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
+ if (flags & ALT_FORM5)
+ return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
+ return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
+
+ case SLJIT_ADDC:
+ return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
+
+ case SLJIT_SUB:
+ if (flags & ALT_FORM1) {
+ if (flags & ALT_FORM2) {
+ FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm));
+ if (!(flags & ALT_FORM3))
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
+ }
+ FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2)));
+ if (!(flags & ALT_FORM3))
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
+ }
+
+ if (flags & ALT_FORM2) {
+ if (flags & ALT_FORM3) {
+ FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));
+ if (!(flags & ALT_FORM4))
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
+ }
+ FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));
+ if (!(flags & ALT_FORM4))
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
+ }
+
+ if (flags & ALT_FORM3) {
+ /* Setting XER SO is not enough, CR SO is also needed. */
+ if (src1 != TMP_ZERO)
+ return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+ return push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
+ }
+
+ if (flags & ALT_FORM4) {
+ /* Flags does not set: BIN_IMM_EXTS unnecessary. */
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
+ }
+
+ if (!(flags & ALT_SET_FLAGS)) {
+ SLJIT_ASSERT(src1 != TMP_ZERO);
+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
+ }
+
+ if (flags & ALT_FORM5)
+ return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+
+ if (src1 != TMP_ZERO)
+ return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+ return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
+
+ case SLJIT_SUBC:
+ return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
+
+ case SLJIT_MUL:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
+ }
+ return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
+
+ case SLJIT_AND:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
+ }
+ if (flags & ALT_FORM2) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
+ }
+ return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
+
+ case SLJIT_OR:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
+ }
+ if (flags & ALT_FORM2) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
+ }
+ if (flags & ALT_FORM3) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ imm = compiler->imm;
+
+ FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm)));
+ return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16));
+ }
+ return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
+
+ case SLJIT_XOR:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
+ }
+ if (flags & ALT_FORM2) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
+ }
+ if (flags & ALT_FORM3) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ imm = compiler->imm;
+
+ FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm)));
+ return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16));
+ }
+ if (flags & ALT_FORM4) {
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
+ }
+ return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
+
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ imm = compiler->imm & 0x1f;
+ return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst));
+ }
+
+ if (op == SLJIT_MSHL) {
+ FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
+ src2 = TMP_REG2;
+ }
+
+ return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2));
+
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ imm = compiler->imm & 0x1f;
+ /* Since imm can be 0, SRWI() cannot be used. */
+ return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31));
+ }
+
+ if (op == SLJIT_MLSHR) {
+ FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
+ src2 = TMP_REG2;
+ }
+
+ return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
+
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ imm = compiler->imm & 0x1f;
+ return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11));
+ }
+
+ if (op == SLJIT_MASHR) {
+ FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
+ src2 = TMP_REG2;
+ }
+
+ return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
+
+ case SLJIT_ROTL:
+ case SLJIT_ROTR:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ imm = compiler->imm;
+
+ if (op == SLJIT_ROTR)
+ imm = (sljit_u32)(-(sljit_s32)imm);
+
+ imm &= 0x1f;
+ return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31));
+ }
+
+ if (op == SLJIT_ROTR) {
+ FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0));
+ src2 = TMP_REG2;
+ }
+
+ return push_inst(compiler, RLWNM | S(src1) | A(dst) | B(src2) | RLWI_MBE(0, 31));
+ }
+
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
+{
+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));
+ return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+ sljit_s32 invert_sign = 1;
+
+ if (src == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ (sljit_sw)0x80000000));
+ src = TMP_REG1;
+ invert_sign = 0;
+ } else if (!FAST_IS_REG(src)) {
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
+ src = TMP_REG1;
+ }
+
+ /* First, a special double precision floating point value is constructed:
+ (2^53 + (src xor (2^31)))
+ The upper 32 bits of this number is a constant, and the lower 32 bits
+ is simply the value of the source argument. The xor 2^31 operation adds
+ 0x80000000 to the source argument, which moves it into the 0 - 0xffffffff
+ range. Finally we substract 2^53 + 2^31 to get the converted value. */
+ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
+ if (invert_sign)
+ FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));
+ FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
+ FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
+ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));
+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+
+ FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
+
+ if (op & SLJIT_32)
+ FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (src == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ src = TMP_REG1;
+ } else if (!FAST_IS_REG(src)) {
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
+ src = TMP_REG1;
+ }
+
+ /* First, a special double precision floating point value is constructed:
+ (2^53 + src)
+ The upper 32 bits of this number is a constant, and the lower 32 bits
+ is simply the value of the source argument. Finally we substract 2^53
+ to get the converted value. */
+ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
+ FAIL_IF(push_inst(compiler, STW | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
+ FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
+
+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ FAIL_IF(push_inst(compiler, STW | S(TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+
+ FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
+
+ if (op & SLJIT_32)
+ FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value)
+{
+ union {
+ sljit_s32 imm[2];
+ sljit_f64 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset64(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm[0] != 0)
+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0]));
+ if (u.imm[1] != 0)
+ FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1]));
+
+ /* Saved in the same endianness. */
+ FAIL_IF(push_inst(compiler, STW | S(u.imm[0] != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ FAIL_IF(push_inst(compiler, STW | S(u.imm[1] != 0 ? TMP_REG2 : TMP_ZERO) | A(SLJIT_SP) | (TMP_MEM_OFFSET + sizeof(sljit_s32))));
+ return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg)
+{
+ sljit_s32 reg2 = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
+
+ if (op & SLJIT_32) {
+ if (op == SLJIT_COPY32_TO_F32) {
+ FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ return push_inst(compiler, LFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
+ }
+
+ FAIL_IF(push_inst(compiler, STFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
+ }
+
+ if (reg & REG_PAIR_MASK) {
+ reg2 = REG_PAIR_SECOND(reg);
+ reg = REG_PAIR_FIRST(reg);
+ }
+
+ if (op == SLJIT_COPY_TO_F64) {
+ FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
+
+ if (reg2 != 0)
+ FAIL_IF(push_inst(compiler, STW | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
+ else
+ FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
+
+ return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
+ }
+
+ FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+
+ if (reg2 != 0)
+ FAIL_IF(push_inst(compiler, LWZ | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
+
+ return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
+{
+ sljit_ins *inst = (sljit_ins *)addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_target >> 16);
+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_target);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+}
diff --git a/deps/sljit/sljit_src/sljitNativePPC_64.c b/deps/sljit/sljit_src/sljitNativePPC_64.c
new file mode 100644
index 0000000..2b07fcb
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativePPC_64.c
@@ -0,0 +1,719 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* ppc 64-bit arch dependent functions. */
+
+#if defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)
+#define ASM_SLJIT_CLZ(src, dst) \
+ __asm__ volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )
+#elif defined(__xlc__)
+#error "Please enable GCC syntax for inline assembly statements"
+#else
+#error "Must implement count leading zeroes"
+#endif
+
+/* Computes SLDI(63 - shift). */
+#define PUSH_SLDI_NEG(reg, shift) \
+ push_inst(compiler, RLDICR | S(reg) | A(reg) | RLDI_SH(63 - shift) | RLDI_ME(shift))
+
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
+{
+ sljit_uw tmp;
+ sljit_uw shift;
+ sljit_uw tmp2;
+ sljit_uw shift2;
+
+ if (imm <= SIMM_MAX && imm >= SIMM_MIN)
+ return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
+
+ if (((sljit_uw)imm >> 16) == 0)
+ return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
+
+ if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
+ return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
+ }
+
+ if (((sljit_uw)imm >> 32) == 0) {
+ FAIL_IF(push_inst(compiler, ORIS | S(TMP_ZERO) | A(reg) | IMM(imm >> 16)));
+ return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
+ }
+
+ /* Count leading zeroes. */
+ tmp = (sljit_uw)((imm >= 0) ? imm : ~imm);
+ ASM_SLJIT_CLZ(tmp, shift);
+ SLJIT_ASSERT(shift > 0);
+ shift--;
+ tmp = ((sljit_uw)imm << shift);
+
+ if ((tmp & ~0xffff000000000000ul) == 0) {
+ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
+ shift += 15;
+ return PUSH_SLDI_NEG(reg, shift);
+ }
+
+ if ((tmp & ~0xffffffff00000000ul) == 0) {
+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
+ FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32)));
+ shift += 31;
+ return PUSH_SLDI_NEG(reg, shift);
+ }
+
+ /* Cut out the 16 bit from immediate. */
+ shift += 15;
+ tmp2 = (sljit_uw)imm & (((sljit_uw)1 << (63 - shift)) - 1);
+
+ if (tmp2 <= 0xffff) {
+ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
+ FAIL_IF(PUSH_SLDI_NEG(reg, shift));
+ return push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)tmp2);
+ }
+
+ if (tmp2 <= 0xffffffff) {
+ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
+ FAIL_IF(PUSH_SLDI_NEG(reg, shift));
+ FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 16)));
+ return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS;
+ }
+
+ ASM_SLJIT_CLZ(tmp2, shift2);
+ tmp2 <<= shift2;
+
+ if ((tmp2 & ~0xffff000000000000ul) == 0) {
+ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
+ shift2 += 15;
+ shift += (63 - shift2);
+ FAIL_IF(PUSH_SLDI_NEG(reg, shift));
+ FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 48)));
+ return PUSH_SLDI_NEG(reg, shift2);
+ }
+
+ /* The general version. */
+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)((sljit_uw)imm >> 48)));
+ FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32)));
+ FAIL_IF(PUSH_SLDI_NEG(reg, 31));
+ FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16)));
+ return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm));
+}
+
+#undef PUSH_SLDI_NEG
+
+#define CLRLDI(dst, src, n) \
+ (RLDICL | S(src) | A(dst) | RLDI_SH(0) | RLDI_MB(n))
+
+/* Sign extension for integer operations. */
+#define UN_EXTS() \
+ if ((flags & (ALT_SIGN_EXT | REG2_SOURCE)) == (ALT_SIGN_EXT | REG2_SOURCE)) { \
+ FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
+ src2 = TMP_REG2; \
+ }
+
+#define BIN_EXTS() \
+ if (flags & ALT_SIGN_EXT) { \
+ if (flags & REG1_SOURCE) { \
+ FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
+ src1 = TMP_REG1; \
+ } \
+ if (flags & REG2_SOURCE) { \
+ FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
+ src2 = TMP_REG2; \
+ } \
+ }
+
+#define BIN_IMM_EXTS() \
+ if ((flags & (ALT_SIGN_EXT | REG1_SOURCE)) == (ALT_SIGN_EXT | REG1_SOURCE)) { \
+ FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
+ src1 = TMP_REG1; \
+ }
+
+static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+ sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
+{
+ sljit_u32 imm;
+
+ switch (op) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ if (dst != src2)
+ return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (op == SLJIT_MOV_S32)
+ return push_inst(compiler, EXTSW | S(src2) | A(dst));
+ return push_inst(compiler, CLRLDI(dst, src2, 32));
+ }
+ else {
+ SLJIT_ASSERT(dst == src2);
+ }
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_U8:
+ case SLJIT_MOV_S8:
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (op == SLJIT_MOV_S8)
+ return push_inst(compiler, EXTSB | S(src2) | A(dst));
+ return push_inst(compiler, CLRLDI(dst, src2, 56));
+ }
+ else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)
+ return push_inst(compiler, EXTSB | S(src2) | A(dst));
+ else {
+ SLJIT_ASSERT(dst == src2);
+ }
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_U16:
+ case SLJIT_MOV_S16:
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (op == SLJIT_MOV_S16)
+ return push_inst(compiler, EXTSH | S(src2) | A(dst));
+ return push_inst(compiler, CLRLDI(dst, src2, 48));
+ }
+ else {
+ SLJIT_ASSERT(dst == src2);
+ }
+ return SLJIT_SUCCESS;
+
+ case SLJIT_CLZ:
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ return push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(src2) | A(dst));
+
+ case SLJIT_CTZ:
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2)));
+ FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(dst) | A(dst)));
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM((flags & ALT_FORM1) ? -32 : -64)));
+ /* The highest bits are set, if dst < bit width, zero otherwise. */
+ FAIL_IF(push_inst(compiler, ((flags & ALT_FORM1) ? SRWI(27) : SRDI(58)) | S(TMP_REG1) | A(TMP_REG1)));
+ return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1));
+
+ case SLJIT_ADD:
+ if (flags & ALT_FORM1) {
+ if (flags & ALT_SIGN_EXT) {
+ FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1)));
+ src1 = TMP_REG1;
+ FAIL_IF(push_inst(compiler, SLDI(32) | S(src2) | A(TMP_REG2)));
+ src2 = TMP_REG2;
+ }
+ /* Setting XER SO is not enough, CR SO is also needed. */
+ FAIL_IF(push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)));
+ if (flags & ALT_SIGN_EXT)
+ return push_inst(compiler, SRDI(32) | S(dst) | A(dst));
+ return SLJIT_SUCCESS;
+ }
+
+ if (flags & ALT_FORM2) {
+ /* Flags does not set: BIN_IMM_EXTS unnecessary. */
+ SLJIT_ASSERT(src2 == TMP_REG2);
+
+ if (flags & ALT_FORM3)
+ return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
+
+ imm = compiler->imm;
+
+ if (flags & ALT_FORM4) {
+ FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1))));
+ src1 = dst;
+ }
+
+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff));
+ }
+ if (flags & ALT_FORM3) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ BIN_IMM_EXTS();
+ return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
+ }
+ if (flags & ALT_FORM4) {
+ if (flags & ALT_FORM5)
+ FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm));
+ else
+ FAIL_IF(push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)));
+ return push_inst(compiler, CMPI | A(dst) | 0);
+ }
+ if (!(flags & ALT_SET_FLAGS))
+ return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
+ BIN_EXTS();
+ if (flags & ALT_FORM5)
+ return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
+ return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
+
+ case SLJIT_ADDC:
+ BIN_EXTS();
+ return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
+
+ case SLJIT_SUB:
+ if (flags & ALT_FORM1) {
+ if (flags & ALT_FORM2) {
+ FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
+ if (!(flags & ALT_FORM3))
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
+ }
+ FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
+ if (!(flags & ALT_FORM3))
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
+ }
+
+ if (flags & ALT_FORM2) {
+ if (flags & ALT_FORM3) {
+ FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
+ if (!(flags & ALT_FORM4))
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
+ }
+ FAIL_IF(push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
+ if (!(flags & ALT_FORM4))
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
+ }
+
+ if (flags & ALT_FORM3) {
+ if (flags & ALT_SIGN_EXT) {
+ if (src1 != TMP_ZERO) {
+ FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1)));
+ src1 = TMP_REG1;
+ }
+ if (src2 != TMP_ZERO) {
+ FAIL_IF(push_inst(compiler, SLDI(32) | S(src2) | A(TMP_REG2)));
+ src2 = TMP_REG2;
+ }
+ }
+
+ /* Setting XER SO is not enough, CR SO is also needed. */
+ if (src1 != TMP_ZERO)
+ FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)));
+ else
+ FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2)));
+
+ if (flags & ALT_SIGN_EXT)
+ return push_inst(compiler, SRDI(32) | S(dst) | A(dst));
+ return SLJIT_SUCCESS;
+ }
+
+ if (flags & ALT_FORM4) {
+ /* Flags does not set: BIN_IMM_EXTS unnecessary. */
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
+ }
+
+ if (!(flags & ALT_SET_FLAGS)) {
+ SLJIT_ASSERT(src1 != TMP_ZERO);
+ return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
+ }
+
+ BIN_EXTS();
+ if (flags & ALT_FORM5)
+ return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+
+ if (src1 != TMP_ZERO)
+ return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+ return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
+
+ case SLJIT_SUBC:
+ BIN_EXTS();
+ return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
+
+ case SLJIT_MUL:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
+ }
+ BIN_EXTS();
+ if (flags & ALT_FORM2)
+ return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
+ return push_inst(compiler, MULLD | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
+
+ case SLJIT_AND:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
+ }
+ if (flags & ALT_FORM2) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
+ }
+ return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
+
+ case SLJIT_OR:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
+ }
+ if (flags & ALT_FORM2) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
+ }
+ if (flags & ALT_FORM3) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ imm = compiler->imm;
+
+ FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm)));
+ return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16));
+ }
+ return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
+
+ case SLJIT_XOR:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
+ }
+ if (flags & ALT_FORM2) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
+ }
+ if (flags & ALT_FORM3) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ imm = compiler->imm;
+
+ FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm)));
+ return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16));
+ }
+ if (flags & ALT_FORM4) {
+ SLJIT_ASSERT(src1 == TMP_REG1);
+ UN_EXTS();
+ return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
+ }
+ return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
+
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ imm = compiler->imm;
+
+ if (flags & ALT_FORM2) {
+ imm &= 0x1f;
+ return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst));
+ }
+
+ imm &= 0x3f;
+ return push_inst(compiler, SLDI(imm) | RC(flags) | S(src1) | A(dst));
+ }
+
+ if (op == SLJIT_MSHL) {
+ FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));
+ src2 = TMP_REG2;
+ }
+
+ return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2));
+
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ imm = compiler->imm;
+
+ if (flags & ALT_FORM2) {
+ imm &= 0x1f;
+ /* Since imm can be 0, SRWI() cannot be used. */
+ return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31));
+ }
+
+ imm &= 0x3f;
+ /* Since imm can be 0, SRDI() cannot be used. */
+ return push_inst(compiler, RLDICL | RC(flags) | S(src1) | A(dst) | RLDI_SH((64 - imm) & 0x3f) | RLDI_MB(imm));
+ }
+
+ if (op == SLJIT_MLSHR) {
+ FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));
+ src2 = TMP_REG2;
+ }
+
+ return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2));
+
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ imm = compiler->imm;
+
+ if (flags & ALT_FORM2) {
+ imm &= 0x1f;
+ return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11));
+ }
+
+ imm &= 0x3f;
+ return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | RLDI_SH(imm));
+ }
+
+ if (op == SLJIT_MASHR) {
+ FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));
+ src2 = TMP_REG2;
+ }
+
+ return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2));
+
+ case SLJIT_ROTL:
+ case SLJIT_ROTR:
+ if (flags & ALT_FORM1) {
+ SLJIT_ASSERT(src2 == TMP_REG2);
+ imm = compiler->imm;
+
+ if (op == SLJIT_ROTR)
+ imm = (sljit_u32)(-(sljit_s32)imm);
+
+ if (flags & ALT_FORM2) {
+ imm &= 0x1f;
+ return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31));
+ }
+
+ imm &= 0x3f;
+ return push_inst(compiler, RLDICL | S(src1) | A(dst) | RLDI_SH(imm));
+ }
+
+ if (op == SLJIT_ROTR) {
+ FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0));
+ src2 = TMP_REG2;
+ }
+
+ return push_inst(compiler, ((flags & ALT_FORM2) ? (RLWNM | RLWI_MBE(0, 31)) : (RLDCL | RLDI_MB(0))) | S(src1) | A(dst) | B(src2));
+ }
+
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)
+{
+ sljit_s32 arg_count = 0;
+ sljit_s32 word_arg_count = 0;
+ sljit_s32 types = 0;
+ sljit_s32 reg = 0;
+
+ if (src)
+ reg = *src & REG_MASK;
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ while (arg_types) {
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
+
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ case SLJIT_ARG_TYPE_F32:
+ arg_count++;
+ break;
+ default:
+ arg_count++;
+ word_arg_count++;
+
+ if (arg_count != word_arg_count && arg_count == reg) {
+ FAIL_IF(push_inst(compiler, OR | S(reg) | A(TMP_CALL_REG) | B(reg)));
+ *src = TMP_CALL_REG;
+ }
+ break;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ while (types) {
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ case SLJIT_ARG_TYPE_F32:
+ arg_count--;
+ break;
+ default:
+ if (arg_count != word_arg_count)
+ FAIL_IF(push_inst(compiler, OR | S(word_arg_count) | A(arg_count) | B(word_arg_count)));
+
+ arg_count--;
+ word_arg_count--;
+ break;
+ }
+
+ types >>= SLJIT_ARG_SHIFT;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
+{
+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));
+ FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));
+ FAIL_IF(push_inst(compiler, SLDI(32) | S(reg) | A(reg)));
+ FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(init_value >> 16)));
+ return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (src == SLJIT_IMM) {
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
+ srcw = (sljit_s32)srcw;
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ src = TMP_REG1;
+ } else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) {
+ if (FAST_IS_REG(src))
+ FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));
+ else
+ FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
+ src = TMP_REG1;
+ }
+
+ if (FAST_IS_REG(src)) {
+ FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ } else
+ FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
+
+ FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
+
+ if (op & SLJIT_32)
+ FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {
+ if (src == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_u32)srcw));
+ src = TMP_REG1;
+ } else {
+ if (FAST_IS_REG(src))
+ FAIL_IF(push_inst(compiler, CLRLDI(TMP_REG1, src, 32)));
+ else
+ FAIL_IF(emit_op_mem(compiler, INT_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
+ src = TMP_REG1;
+ }
+
+ FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
+ } else {
+ if (src == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ src = TMP_REG1;
+ } else if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
+ src = TMP_REG1;
+ }
+
+ FAIL_IF(push_inst(compiler, CMPI | CRD(0 | 1) | A(src) | 0));
+ FAIL_IF(push_inst(compiler, BCx | (12 << 21) | (0 << 16) | 20));
+ FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
+ FAIL_IF(push_inst(compiler, Bx | ((op & SLJIT_32) ? 36 : 32)));
+
+ if (op & SLJIT_32)
+ FAIL_IF(push_inst(compiler, RLWINM | S(src) | A(TMP_REG2) | RLWI_SH(10) | RLWI_MBE(10, 21)));
+ else
+ FAIL_IF(push_inst(compiler, ANDI | S(src) | A(TMP_REG2) | 0x1));
+
+ /* Shift right. */
+ FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(63) | RLDI_MB(1)));
+
+ if (op & SLJIT_32)
+ FAIL_IF(push_inst(compiler, RLDICR | S(TMP_REG1) | A(TMP_REG1) | RLDI_SH(0) | RLDI_ME(53)));
+
+ FAIL_IF(push_inst(compiler, OR | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));
+
+ FAIL_IF(push_inst(compiler, STD | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
+ FAIL_IF(push_inst(compiler, FADD | FD(dst_r) | FA(dst_r) | FB(dst_r)));
+ }
+
+ if (op & SLJIT_32)
+ FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value)
+{
+ union {
+ sljit_sw imm;
+ sljit_f64 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset64(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm != 0)
+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));
+
+ FAIL_IF(push_inst(compiler, STD | S(u.imm != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
+
+ if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) {
+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STW : STD) | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ return push_inst(compiler, ((op & SLJIT_32) ? LFS : LFD) | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
+ }
+
+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STFS : STFD) | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ return push_inst(compiler, ((op & SLJIT_32) ? LWZ : LD) | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
+{
+ sljit_ins *inst = (sljit_ins*)addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);
+ inst[0] = (inst[0] & 0xffff0000u) | IMM(new_target >> 48);
+ inst[1] = (inst[1] & 0xffff0000u) | IMM(new_target >> 32);
+ inst[3] = (inst[3] & 0xffff0000u) | IMM(new_target >> 16);
+ inst[4] = (inst[4] & 0xffff0000u) | IMM(new_target);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 5);
+}
diff --git a/deps/sljit/sljit_src/sljitNativePPC_common.c b/deps/sljit/sljit_src/sljitNativePPC_common.c
new file mode 100644
index 0000000..ea0597b
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativePPC_common.c
@@ -0,0 +1,3514 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
+{
+ return "PowerPC" SLJIT_CPUINFO;
+}
+
+/* Length of an instruction word.
+ Both for ppc-32 and ppc-64. */
+typedef sljit_u32 sljit_ins;
+
+#if ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && (defined _AIX)) \
+ || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#define SLJIT_PPC_STACK_FRAME_V2 1
+#endif
+
+#ifdef _AIX
+#include
+#endif
+
+#if (defined _CALL_ELF && _CALL_ELF == 2)
+#define SLJIT_PASS_ENTRY_ADDR_TO_CALL 1
+#endif
+
+#if (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL)
+
+static void ppc_cache_flush(sljit_ins *from, sljit_ins *to)
+{
+#ifdef _AIX
+ _sync_cache_range((caddr_t)from, (int)((size_t)to - (size_t)from));
+#elif defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)
+# if defined(_ARCH_PWR) || defined(_ARCH_PWR2)
+ /* Cache flush for POWER architecture. */
+ while (from < to) {
+ __asm__ volatile (
+ "clf 0, %0\n"
+ "dcs\n"
+ : : "r"(from)
+ );
+ from++;
+ }
+ __asm__ volatile ( "ics" );
+# elif defined(_ARCH_COM) && !defined(_ARCH_PPC)
+# error "Cache flush is not implemented for PowerPC/POWER common mode."
+# else
+ /* Cache flush for PowerPC architecture. */
+ while (from < to) {
+ __asm__ volatile (
+ "dcbf 0, %0\n"
+ "sync\n"
+ "icbi 0, %0\n"
+ : : "r"(from)
+ );
+ from++;
+ }
+ __asm__ volatile ( "isync" );
+# endif
+# ifdef __xlc__
+# warning "This file may fail to compile if -qfuncsect is used"
+# endif
+#elif defined(__xlc__)
+#error "Please enable GCC syntax for inline assembly statements with -qasm=gcc"
+#else
+#error "This platform requires a cache flush implementation."
+#endif /* _AIX */
+}
+
+#endif /* (defined SLJIT_CACHE_FLUSH_OWN_IMPL && SLJIT_CACHE_FLUSH_OWN_IMPL) */
+
+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
+#define TMP_ZERO (SLJIT_NUMBER_OF_REGISTERS + 4)
+
+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
+#define TMP_CALL_REG (SLJIT_NUMBER_OF_REGISTERS + 5)
+#else
+#define TMP_CALL_REG TMP_REG1
+#endif
+
+#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
+
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
+ 0, 3, 4, 5, 6, 7, 8, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1, 9, 10, 31, 12
+};
+
+static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 0, 13
+};
+
+/* --------------------------------------------------------------------- */
+/* Instruction forms */
+/* --------------------------------------------------------------------- */
+#define D(d) ((sljit_ins)reg_map[d] << 21)
+#define S(s) ((sljit_ins)reg_map[s] << 21)
+#define A(a) ((sljit_ins)reg_map[a] << 16)
+#define B(b) ((sljit_ins)reg_map[b] << 11)
+#define C(c) ((sljit_ins)reg_map[c] << 6)
+#define FD(fd) ((sljit_ins)freg_map[fd] << 21)
+#define FS(fs) ((sljit_ins)freg_map[fs] << 21)
+#define FA(fa) ((sljit_ins)freg_map[fa] << 16)
+#define FB(fb) ((sljit_ins)freg_map[fb] << 11)
+#define FC(fc) ((sljit_ins)freg_map[fc] << 6)
+#define IMM(imm) ((sljit_ins)(imm) & 0xffff)
+#define CRD(d) ((sljit_ins)(d) << 21)
+
+/* Instruction bit sections.
+ OE and Rc flag (see ALT_SET_FLAGS). */
+#define OE(flags) ((flags) & ALT_SET_FLAGS)
+/* Rc flag (see ALT_SET_FLAGS). */
+#define RC(flags) ((sljit_ins)((flags) & ALT_SET_FLAGS) >> 10)
+#define HI(opcode) ((sljit_ins)(opcode) << 26)
+#define LO(opcode) ((sljit_ins)(opcode) << 1)
+
+#define ADD (HI(31) | LO(266))
+#define ADDC (HI(31) | LO(10))
+#define ADDE (HI(31) | LO(138))
+#define ADDI (HI(14))
+#define ADDIC (HI(13))
+#define ADDIS (HI(15))
+#define ADDME (HI(31) | LO(234))
+#define AND (HI(31) | LO(28))
+#define ANDI (HI(28))
+#define ANDIS (HI(29))
+#define Bx (HI(18))
+#define BCx (HI(16))
+#define BCCTR (HI(19) | LO(528) | (3 << 11))
+#define BLR (HI(19) | LO(16) | (0x14 << 21))
+#if defined(_ARCH_PWR10) && _ARCH_PWR10
+#define BRD (HI(31) | LO(187))
+#endif /* POWER10 */
+#define CNTLZD (HI(31) | LO(58))
+#define CNTLZW (HI(31) | LO(26))
+#define CMP (HI(31) | LO(0))
+#define CMPI (HI(11))
+#define CMPL (HI(31) | LO(32))
+#define CMPLI (HI(10))
+#define CROR (HI(19) | LO(449))
+#define DCBT (HI(31) | LO(278))
+#define DIVD (HI(31) | LO(489))
+#define DIVDU (HI(31) | LO(457))
+#define DIVW (HI(31) | LO(491))
+#define DIVWU (HI(31) | LO(459))
+#define EXTSB (HI(31) | LO(954))
+#define EXTSH (HI(31) | LO(922))
+#define EXTSW (HI(31) | LO(986))
+#define FABS (HI(63) | LO(264))
+#define FADD (HI(63) | LO(21))
+#define FADDS (HI(59) | LO(21))
+#define FCFID (HI(63) | LO(846))
+#define FCMPU (HI(63) | LO(0))
+#define FCTIDZ (HI(63) | LO(815))
+#define FCTIWZ (HI(63) | LO(15))
+#define FDIV (HI(63) | LO(18))
+#define FDIVS (HI(59) | LO(18))
+#define FMR (HI(63) | LO(72))
+#define FMUL (HI(63) | LO(25))
+#define FMULS (HI(59) | LO(25))
+#define FNEG (HI(63) | LO(40))
+#define FRSP (HI(63) | LO(12))
+#define FSUB (HI(63) | LO(20))
+#define FSUBS (HI(59) | LO(20))
+#define LD (HI(58) | 0)
+#define LFD (HI(50))
+#define LFS (HI(48))
+#define LDARX (HI(31) | LO(84))
+#if defined(_ARCH_PWR7) && _ARCH_PWR7
+#define LDBRX (HI(31) | LO(532))
+#endif /* POWER7 */
+#define LHBRX (HI(31) | LO(790))
+#define LWARX (HI(31) | LO(20))
+#define LWBRX (HI(31) | LO(534))
+#define LWZ (HI(32))
+#define MFCR (HI(31) | LO(19))
+#define MFLR (HI(31) | LO(339) | 0x80000)
+#define MFXER (HI(31) | LO(339) | 0x10000)
+#define MTCTR (HI(31) | LO(467) | 0x90000)
+#define MTLR (HI(31) | LO(467) | 0x80000)
+#define MTXER (HI(31) | LO(467) | 0x10000)
+#define MULHD (HI(31) | LO(73))
+#define MULHDU (HI(31) | LO(9))
+#define MULHW (HI(31) | LO(75))
+#define MULHWU (HI(31) | LO(11))
+#define MULLD (HI(31) | LO(233))
+#define MULLI (HI(7))
+#define MULLW (HI(31) | LO(235))
+#define NEG (HI(31) | LO(104))
+#define NOP (HI(24))
+#define NOR (HI(31) | LO(124))
+#define OR (HI(31) | LO(444))
+#define ORI (HI(24))
+#define ORIS (HI(25))
+#define RLDCL (HI(30) | LO(8))
+#define RLDICL (HI(30) | LO(0 << 1))
+#define RLDICR (HI(30) | LO(1 << 1))
+#define RLDIMI (HI(30) | LO(3 << 1))
+#define RLWIMI (HI(20))
+#define RLWINM (HI(21))
+#define RLWNM (HI(23))
+#define SLD (HI(31) | LO(27))
+#define SLW (HI(31) | LO(24))
+#define SRAD (HI(31) | LO(794))
+#define SRADI (HI(31) | LO(413 << 1))
+#define SRAW (HI(31) | LO(792))
+#define SRAWI (HI(31) | LO(824))
+#define SRD (HI(31) | LO(539))
+#define SRW (HI(31) | LO(536))
+#define STD (HI(62) | 0)
+#if defined(_ARCH_PWR7) && _ARCH_PWR7
+#define STDBRX (HI(31) | LO(660))
+#endif /* POWER7 */
+#define STDCX (HI(31) | LO(214))
+#define STDU (HI(62) | 1)
+#define STDUX (HI(31) | LO(181))
+#define STFD (HI(54))
+#define STFIWX (HI(31) | LO(983))
+#define STFS (HI(52))
+#define STHBRX (HI(31) | LO(918))
+#define STW (HI(36))
+#define STWBRX (HI(31) | LO(662))
+#define STWCX (HI(31) | LO(150))
+#define STWU (HI(37))
+#define STWUX (HI(31) | LO(183))
+#define SUBF (HI(31) | LO(40))
+#define SUBFC (HI(31) | LO(8))
+#define SUBFE (HI(31) | LO(136))
+#define SUBFIC (HI(8))
+#define SYNC (HI(31) | LO(598))
+#define XOR (HI(31) | LO(316))
+#define XORI (HI(26))
+#define XORIS (HI(27))
+
+#define SIMM_MAX (0x7fff)
+#define SIMM_MIN (-0x8000)
+#define UIMM_MAX (0xffff)
+
+/* Shift helpers. */
+#define RLWI_SH(sh) ((sljit_ins)(sh) << 11)
+#define RLWI_MBE(mb, me) (((sljit_ins)(mb) << 6) | ((sljit_ins)(me) << 1))
+#define RLDI_SH(sh) ((((sljit_ins)(sh) & 0x1f) << 11) | (((sljit_ins)(sh) & 0x20) >> 4))
+#define RLDI_MB(mb) ((((sljit_ins)(mb) & 0x1f) << 6) | ((sljit_ins)(mb) & 0x20))
+#define RLDI_ME(me) RLDI_MB(me)
+
+#define SLWI(shift) (RLWINM | RLWI_SH(shift) | RLWI_MBE(0, 31 - (shift)))
+#define SLDI(shift) (RLDICR | RLDI_SH(shift) | RLDI_ME(63 - (shift)))
+/* shift > 0 */
+#define SRWI(shift) (RLWINM | RLWI_SH(32 - (shift)) | RLWI_MBE((shift), 31))
+#define SRDI(shift) (RLDICL | RLDI_SH(64 - (shift)) | RLDI_MB(shift))
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+#define SLWI_W(shift) SLWI(shift)
+#define TMP_MEM_OFFSET (2 * sizeof(sljit_sw))
+#else /* !SLJIT_CONFIG_PPC_32 */
+#define SLWI_W(shift) SLDI(shift)
+#define TMP_MEM_OFFSET (6 * sizeof(sljit_sw))
+#endif /* SLJIT_CONFIG_PPC_32 */
+
+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
+#define TMP_MEM_OFFSET_LO (TMP_MEM_OFFSET)
+#define TMP_MEM_OFFSET_HI (TMP_MEM_OFFSET + sizeof(sljit_s32))
+#define LWBRX_FIRST_REG S(TMP_REG1)
+#define LWBRX_SECOND_REG S(dst)
+#else /* !SLJIT_LITTLE_ENDIAN */
+#define TMP_MEM_OFFSET_LO (TMP_MEM_OFFSET + sizeof(sljit_s32))
+#define TMP_MEM_OFFSET_HI (TMP_MEM_OFFSET)
+#define LWBRX_FIRST_REG S(dst)
+#define LWBRX_SECOND_REG S(TMP_REG1)
+#endif /* SLJIT_LITTLE_ENDIAN */
+
+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_uw addr, void (*func)(void))
+{
+ sljit_uw* ptrs;
+
+ if (func_ptr)
+ *func_ptr = (void*)context;
+
+ ptrs = (sljit_uw*)(sljit_uw)func;
+ context->addr = addr ? addr : ptrs[0];
+ context->r2 = ptrs[1];
+ context->r11 = ptrs[2];
+}
+#endif
+
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
+{
+ sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ *ptr = ins;
+ compiler->size++;
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
+{
+ sljit_sw diff;
+ sljit_uw target_addr;
+ sljit_uw jump_addr = (sljit_uw)code_ptr;
+ sljit_uw orig_addr = jump->addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ jump->addr = jump_addr;
+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
+ goto exit;
+#else
+ if (jump->flags & SLJIT_REWRITABLE_JUMP)
+ goto exit;
+#endif
+
+ if (jump->flags & JUMP_ADDR)
+ target_addr = jump->u.target;
+ else {
+ SLJIT_ASSERT(jump->u.label != NULL);
+ target_addr = (sljit_uw)(code + jump->u.label->size) + (sljit_uw)executable_offset;
+
+ if (jump->u.label->size > orig_addr)
+ jump_addr = (sljit_uw)(code + orig_addr);
+ }
+
+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (jump->flags & IS_CALL)
+ goto keep_address;
+#endif
+
+ diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);
+
+ if (jump->flags & IS_COND) {
+ if (diff <= 0x7fff && diff >= -0x8000) {
+ jump->flags |= PATCH_B;
+ return code_ptr;
+ }
+ if (target_addr <= 0xffff) {
+ jump->flags |= PATCH_B | PATCH_ABS_B;
+ return code_ptr;
+ }
+
+ diff -= SSIZE_OF(ins);
+ }
+
+ if (diff <= 0x01ffffff && diff >= -0x02000000) {
+ jump->flags |= PATCH_B;
+ } else if (target_addr <= 0x01ffffff) {
+ jump->flags |= PATCH_B | PATCH_ABS_B;
+ }
+
+ if (jump->flags & PATCH_B) {
+ if (!(jump->flags & IS_COND))
+ return code_ptr;
+
+ code_ptr[0] = BCx | (2 << 2) | ((code_ptr[0] ^ (8 << 21)) & 0x03ff0001);
+ code_ptr[1] = Bx;
+ jump->addr += sizeof(sljit_ins);
+ jump->flags -= IS_COND;
+ return code_ptr + 1;
+ }
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
+keep_address:
+#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
+ if (target_addr < 0x80000000l) {
+ jump->flags |= PATCH_ABS32;
+ code_ptr[2] = MTCTR | S(TMP_CALL_REG);
+ code_ptr[3] = code_ptr[0];
+ return code_ptr + 3;
+ }
+
+ if (target_addr < 0x800000000000l) {
+ jump->flags |= PATCH_ABS48;
+ code_ptr[4] = MTCTR | S(TMP_CALL_REG);
+ code_ptr[5] = code_ptr[0];
+ return code_ptr + 5;
+ }
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+exit:
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ code_ptr[2] = MTCTR | S(TMP_CALL_REG);
+ code_ptr[3] = code_ptr[0];
+#else /* !SLJIT_CONFIG_PPC_32 */
+ code_ptr[5] = MTCTR | S(TMP_CALL_REG);
+ code_ptr[6] = code_ptr[0];
+#endif /* SLJIT_CONFIG_PPC_32 */
+ return code_ptr + JUMP_MAX_SIZE - 1;
+}
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+
+static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code, sljit_sw executable_offset)
+{
+ sljit_uw addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_ASSERT(jump->flags < ((sljit_uw)5 << JUMP_SIZE_SHIFT));
+ if (jump->flags & JUMP_ADDR)
+ addr = jump->u.target;
+ else
+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
+
+ if (addr < 0x80000000l) {
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
+ jump->flags |= PATCH_ABS32;
+ return 1;
+ }
+
+ if (addr < 0x800000000000l) {
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));
+ jump->flags |= PATCH_ABS48;
+ return 3;
+ }
+
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)4 << JUMP_SIZE_SHIFT));
+ return 4;
+}
+
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+static void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset)
+{
+ sljit_uw flags = jump->flags;
+ sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
+ sljit_ins *ins = (sljit_ins*)jump->addr;
+ sljit_s32 reg;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ if (flags & PATCH_B) {
+ if (flags & IS_COND) {
+ if (!(flags & PATCH_ABS_B)) {
+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);
+ SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);
+ ins[0] = BCx | ((sljit_ins)addr & 0xfffc) | (ins[0] & 0x03ff0001);
+ } else {
+ SLJIT_ASSERT(addr <= 0xffff);
+ ins[0] = BCx | ((sljit_ins)addr & 0xfffc) | 0x2 | ((*ins) & 0x03ff0001);
+ }
+ return;
+ }
+
+ if (!(flags & PATCH_ABS_B)) {
+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);
+ SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);
+ ins[0] = Bx | ((sljit_ins)addr & 0x03fffffc) | (ins[0] & 0x1);
+ } else {
+ SLJIT_ASSERT(addr <= 0x03ffffff);
+ ins[0] = Bx | ((sljit_ins)addr & 0x03fffffc) | 0x2 | (ins[0] & 0x1);
+ }
+ return;
+ }
+
+ reg = (flags & JUMP_MOV_ADDR) ? (sljit_s32)ins[0] : TMP_CALL_REG;
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 16);
+ ins[1] = ORI | S(reg) | A(reg) | IMM(addr);
+#else /* !SLJIT_CONFIG_PPC_32 */
+
+ /* The TMP_ZERO cannot be used because it is restored for tail calls. */
+ if (flags & PATCH_ABS32) {
+ SLJIT_ASSERT(addr < 0x80000000l);
+ ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 16);
+ ins[1] = ORI | S(reg) | A(reg) | IMM(addr);
+ return;
+ }
+
+ if (flags & PATCH_ABS48) {
+ SLJIT_ASSERT(addr < 0x800000000000l);
+ ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 32);
+ ins[1] = ORI | S(reg) | A(reg) | IMM(addr >> 16);
+ ins[2] = SLDI(16) | S(reg) | A(reg);
+ ins[3] = ORI | S(reg) | A(reg) | IMM(addr);
+ return;
+ }
+
+ ins[0] = ADDIS | D(reg) | A(0) | IMM(addr >> 48);
+ ins[1] = ORI | S(reg) | A(reg) | IMM(addr >> 32);
+ ins[2] = SLDI(32) | S(reg) | A(reg);
+ ins[3] = ORIS | S(reg) | A(reg) | IMM(addr >> 16);
+ ins[4] = ORI | S(reg) | A(reg) | IMM(addr);
+#endif /* SLJIT_CONFIG_PPC_32 */
+}
+
+static SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
+static void reduce_code_size(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+ SLJIT_NEXT_DEFINE_TYPES;
+ sljit_uw total_size;
+ sljit_uw size_reduce = 0;
+ sljit_sw diff;
+
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ SLJIT_NEXT_INIT_TYPES();
+
+ while (1) {
+ SLJIT_GET_NEXT_MIN();
+
+ if (next_min_addr == SLJIT_MAX_ADDRESS)
+ break;
+
+ if (next_min_addr == next_label_size) {
+ label->size -= size_reduce;
+
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ if (next_min_addr == next_const_addr) {
+ const_->addr -= size_reduce;
+ const_ = const_->next;
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+ continue;
+ }
+
+ if (next_min_addr != next_jump_addr)
+ continue;
+
+ jump->addr -= size_reduce;
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+ total_size = JUMP_MAX_SIZE - 1;
+
+ if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {
+ if (jump->flags & JUMP_ADDR) {
+ if (jump->u.target <= 0x01ffffff)
+ total_size = 1 - 1;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ else if (jump->u.target < 0x80000000l)
+ total_size = 4 - 1;
+ else if (jump->u.target < 0x800000000000l)
+ total_size = 6 - 1;
+#endif /* SLJIT_CONFIG_PPC_64 */
+ } else {
+ /* Unit size: instruction. */
+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
+ if (jump->u.label->size > jump->addr) {
+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);
+ diff -= (sljit_sw)size_reduce;
+ }
+
+ if (jump->flags & IS_COND) {
+ if (diff <= (0x7fff / SSIZE_OF(ins)) && diff >= (-0x8000 / SSIZE_OF(ins)))
+ total_size = 1 - 1;
+ else if ((diff - 1) <= (0x01ffffff / SSIZE_OF(ins)) && (diff - 1) >= (-0x02000000 / SSIZE_OF(ins)))
+ total_size = 2 - 1;
+ } else if (diff <= (0x01ffffff / SSIZE_OF(ins)) && diff >= (-0x02000000 / SSIZE_OF(ins)))
+ total_size = 1 - 1;
+ }
+ }
+
+ size_reduce += (JUMP_MAX_SIZE - 1) - total_size;
+ jump->flags |= total_size << JUMP_SIZE_SHIFT;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ } else {
+ total_size = (sljit_uw)4 << JUMP_SIZE_SHIFT;
+
+ if (jump->flags & JUMP_ADDR) {
+ if (jump->u.target < 0x80000000l) {
+ total_size = (sljit_uw)1 << JUMP_SIZE_SHIFT;
+ size_reduce += 3;
+ } else if (jump->u.target < 0x800000000000l) {
+ total_size = (sljit_uw)3 << JUMP_SIZE_SHIFT;
+ size_reduce += 1;
+ }
+ }
+ jump->flags |= total_size;
+#endif /* SLJIT_CONFIG_PPC_64 */
+ }
+
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ }
+
+ compiler->size -= size_reduce;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
+{
+ struct sljit_memory_fragment *buf;
+ sljit_ins *code;
+ sljit_ins *code_ptr;
+ sljit_ins *buf_ptr;
+ sljit_ins *buf_end;
+ sljit_uw word_count;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ sljit_uw jump_addr;
+#endif
+ SLJIT_NEXT_DEFINE_TYPES;
+ sljit_sw executable_offset;
+
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
+
+ reduce_code_size(compiler);
+
+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+ if (!(options & SLJIT_GENERATE_CODE_NO_CONTEXT)) {
+ /* add to compiler->size additional instruction space to hold the trampoline and padding */
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
+#else /* !SLJIT_CONFIG_PPC_64 */
+ compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
+#endif /* SLJIT_CONFIG_PPC_64 */
+ }
+#endif /* SLJIT_INDIRECT_CALL */
+ code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
+ PTR_FAIL_WITH_EXEC_IF(code);
+
+ reverse_buf(compiler);
+ buf = compiler->buf;
+
+ code_ptr = code;
+ word_count = 0;
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ SLJIT_NEXT_INIT_TYPES();
+ SLJIT_GET_NEXT_MIN();
+
+ do {
+ buf_ptr = (sljit_ins*)buf->memory;
+ buf_end = buf_ptr + (buf->used_size >> 2);
+ do {
+ *code_ptr = *buf_ptr++;
+ if (next_min_addr == word_count) {
+ SLJIT_ASSERT(!label || label->size >= word_count);
+ SLJIT_ASSERT(!jump || jump->addr >= word_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+
+ /* These structures are ordered by their address. */
+ if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+ *code_ptr = buf_ptr[-1];
+ }
+
+ /* Just recording the address. */
+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ if (next_min_addr == next_jump_addr) {
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+ word_count += jump->flags >> JUMP_SIZE_SHIFT;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ jump_addr = (sljit_uw)code_ptr;
+#endif
+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
+ SLJIT_ASSERT(((sljit_uw)code_ptr - jump_addr <= (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));
+ } else {
+ jump->addr = (sljit_uw)code_ptr;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ word_count += jump->flags >> JUMP_SIZE_SHIFT;
+ code_ptr += mov_addr_get_length(jump, code, executable_offset);
+#else /* !SLJIT_CONFIG_PPC_64 */
+ word_count++;
+ code_ptr++;
+#endif /* SLJIT_CONFIG_PPC_64 */
+ }
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ } else if (next_min_addr == next_const_addr) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+ }
+
+ SLJIT_GET_NEXT_MIN();
+ }
+ code_ptr++;
+ word_count++;
+ } while (buf_ptr < buf_end);
+
+ buf = buf->next;
+ } while (buf);
+
+ if (label && label->size == word_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ }
+
+ SLJIT_ASSERT(!label);
+ SLJIT_ASSERT(!jump);
+ SLJIT_ASSERT(!const_);
+
+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)(compiler->size -
+ ((options & SLJIT_GENERATE_CODE_NO_CONTEXT) ? 0 : (sizeof(struct sljit_function_context) / sizeof(sljit_ins)))));
+#else
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
+#endif
+
+ jump = compiler->jumps;
+ while (jump) {
+ generate_jump_or_mov_addr(jump, executable_offset);
+ jump = jump->next;
+ }
+
+ compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
+
+ code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+
+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+ if (!(options & SLJIT_GENERATE_CODE_NO_CONTEXT)) {
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (((sljit_sw)code_ptr) & 0x4)
+ code_ptr++;
+#endif /* SLJIT_CONFIG_PPC_64 */
+ sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_uw)code, (void (*)(void))sljit_generate_code);
+ }
+#endif /* SLJIT_INDIRECT_CALL */
+
+ code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
+ SLJIT_CACHE_FLUSH(code, code_ptr);
+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
+
+#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+ if (!(options & SLJIT_GENERATE_CODE_NO_CONTEXT)) {
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins) + sizeof(struct sljit_function_context);
+ return code_ptr;
+ }
+#endif /* SLJIT_INDIRECT_CALL */
+
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
+ return code;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type) {
+ case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return (SLJIT_IS_FPU_AVAILABLE) != 0;
+#else
+ /* Available by default. */
+ return 1;
+#endif
+ case SLJIT_HAS_REV:
+#if defined(_ARCH_PWR10) && _ARCH_PWR10
+ return 1;
+#else /* !POWER10 */
+ return 2;
+#endif /* POWER10 */
+ /* A saved register is set to a zero value. */
+ case SLJIT_HAS_ZERO_REGISTER:
+ case SLJIT_HAS_CLZ:
+ case SLJIT_HAS_ROT:
+ case SLJIT_HAS_PREFETCH:
+ case SLJIT_HAS_ATOMIC:
+ case SLJIT_HAS_MEMORY_BARRIER:
+ return 1;
+
+ case SLJIT_HAS_CTZ:
+ return 2;
+
+ default:
+ return 0;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
+{
+ switch (type) {
+ case SLJIT_UNORDERED_OR_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_LESS:
+ case SLJIT_ORDERED_GREATER_EQUAL:
+ case SLJIT_UNORDERED_OR_GREATER:
+ case SLJIT_ORDERED_LESS_EQUAL:
+ return 1;
+ }
+
+ return 0;
+}
+
+/* --------------------------------------------------------------------- */
+/* Entry, exit */
+/* --------------------------------------------------------------------- */
+
+/* inp_flags: */
+
+/* Creates an index in data_transfer_insts array. */
+#define LOAD_DATA 0x01
+#define INDEXED 0x02
+#define SIGNED_DATA 0x04
+
+#define WORD_DATA 0x00
+#define BYTE_DATA 0x08
+#define HALF_DATA 0x10
+#define INT_DATA 0x18
+/* Separates integer and floating point registers */
+#define GPR_REG 0x1f
+#define DOUBLE_DATA 0x20
+
+#define MEM_MASK 0x7f
+
+#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 6))
+
+/* Other inp_flags. */
+
+/* Integer opertion and set flags -> requires exts on 64 bit systems. */
+#define ALT_SIGN_EXT 0x000100
+/* This flag affects the RC() and OERC() macros. */
+#define ALT_SET_FLAGS 0x000400
+#define ALT_FORM1 0x001000
+#define ALT_FORM2 0x002000
+#define ALT_FORM3 0x004000
+#define ALT_FORM4 0x008000
+#define ALT_FORM5 0x010000
+
+/* Source and destination is register. */
+#define REG_DEST 0x000001
+#define REG1_SOURCE 0x000002
+#define REG2_SOURCE 0x000004
+/*
+ALT_SIGN_EXT 0x000100
+ALT_SET_FLAGS 0x000200
+ALT_FORM1 0x001000
+...
+ALT_FORM5 0x010000 */
+
+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,
+ sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg);
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+#include "sljitNativePPC_32.c"
+#else
+#include "sljitNativePPC_64.c"
+#endif
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+#define STACK_STORE STW
+#define STACK_LOAD LWZ
+#else
+#define STACK_STORE STD
+#define STACK_LOAD LD
+#endif
+
+#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
+#define LR_SAVE_OFFSET (2 * SSIZE_OF(sw))
+#else
+#define LR_SAVE_OFFSET SSIZE_OF(sw)
+#endif
+
+#define STACK_MAX_DISTANCE (0x8000 - SSIZE_OF(sw) - LR_SAVE_OFFSET)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);
+ sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);
+ sljit_s32 i, tmp, base, offset;
+ sljit_s32 word_arg_count = 0;
+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ sljit_s32 arg_count = 0;
+#endif
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 0)
+ + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+
+ if (!(options & SLJIT_ENTER_REG_ARG))
+ local_size += SSIZE_OF(sw);
+
+ local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
+ compiler->local_size = local_size;
+
+ FAIL_IF(push_inst(compiler, MFLR | D(0)));
+
+ base = SLJIT_SP;
+ offset = local_size;
+
+ if (local_size <= STACK_MAX_DISTANCE) {
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
+#else
+ FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
+#endif
+ } else {
+ base = TMP_REG1;
+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_SP) | A(TMP_REG1) | B(SLJIT_SP)));
+ FAIL_IF(load_immediate(compiler, TMP_REG2, -local_size));
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));
+#else
+ FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));
+#endif
+ local_size = 0;
+ offset = 0;
+ }
+
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
+ }
+
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
+ }
+
+ if (!(options & SLJIT_ENTER_REG_ARG)) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));
+ }
+
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));
+ }
+
+ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));
+ }
+
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(base) | IMM(local_size + LR_SAVE_OFFSET)));
+
+ if (options & SLJIT_ENTER_REG_ARG)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ saved_arg_count = 0;
+
+ while (arg_types > 0) {
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ do {
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ tmp = SLJIT_S0 - saved_arg_count;
+ saved_arg_count++;
+ } else if (arg_count != word_arg_count)
+ tmp = SLJIT_R0 + word_arg_count;
+ else
+ break;
+
+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + arg_count) | A(tmp) | B(SLJIT_R0 + arg_count)));
+ } while (0);
+#else
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + word_arg_count) | A(SLJIT_S0 - saved_arg_count) | B(SLJIT_R0 + word_arg_count)));
+ saved_arg_count++;
+ }
+#endif
+ word_arg_count++;
+ }
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ arg_count++;
+#endif
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);
+ sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 0)
+ + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+
+ if (!(options & SLJIT_ENTER_REG_ARG))
+ local_size += SSIZE_OF(sw);
+
+ compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)
+{
+ sljit_s32 i, tmp, base, offset;
+ sljit_s32 local_size = compiler->local_size;
+
+ SLJIT_ASSERT(TMP_CALL_REG != TMP_REG2);
+
+ base = SLJIT_SP;
+ if (local_size > STACK_MAX_DISTANCE) {
+ base = TMP_REG2;
+ if (local_size > 2 * STACK_MAX_DISTANCE + LR_SAVE_OFFSET) {
+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(base) | A(SLJIT_SP) | IMM(0)));
+ local_size = 0;
+ } else {
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(SLJIT_SP) | IMM(local_size - STACK_MAX_DISTANCE)));
+ local_size = STACK_MAX_DISTANCE;
+ }
+ }
+
+ offset = local_size;
+ if (!is_return_to)
+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET)));
+
+ tmp = SLJIT_FS0 - compiler->fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
+ }
+
+ for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
+ }
+
+ if (!(compiler->options & SLJIT_ENTER_REG_ARG)) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));
+ }
+
+ tmp = SLJIT_S0 - compiler->saveds;
+ for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));
+ }
+
+ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));
+ }
+
+ if (!is_return_to)
+ push_inst(compiler, MTLR | S(0));
+
+ if (local_size > 0)
+ return push_inst(compiler, ADDI | D(SLJIT_SP) | A(base) | IMM(local_size));
+
+ SLJIT_ASSERT(base == TMP_REG2);
+ return push_inst(compiler, OR | S(base) | A(SLJIT_SP) | B(base));
+}
+
+#undef STACK_STORE
+#undef STACK_LOAD
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ FAIL_IF(emit_stack_frame_release(compiler, 0));
+ return push_inst(compiler, BLR);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));
+ src = TMP_CALL_REG;
+ srcw = 0;
+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
+ src = TMP_CALL_REG;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 1));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
+}
+
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
+/* s/l - store/load (1 bit)
+ i/x - immediate/indexed form
+ u/s - signed/unsigned (1 bit)
+ w/b/h/i - word/byte/half/int allowed (2 bit)
+
+ Some opcodes are repeated (e.g. store signed / unsigned byte is the same instruction). */
+
+/* 64 bit only: [reg+imm] must be aligned to 4 bytes. */
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#define INT_ALIGNED 0x10000
+#endif
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+#define ARCH_32_64(a, b) a
+#define INST_CODE_AND_DST(inst, flags, reg) \
+ ((sljit_ins)(inst) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
+#else
+#define ARCH_32_64(a, b) b
+#define INST_CODE_AND_DST(inst, flags, reg) \
+ (((sljit_ins)(inst) & ~(sljit_ins)INT_ALIGNED) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
+#endif
+
+static const sljit_ins data_transfer_insts[64 + 16] = {
+
+/* -------- Integer -------- */
+
+/* Word. */
+
+/* w u i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
+/* w u i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
+/* w u x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
+/* w u x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
+
+/* w s i s */ ARCH_32_64(HI(36) /* stw */, HI(62) | INT_ALIGNED | 0x0 /* std */),
+/* w s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x0 /* ld */),
+/* w s x s */ ARCH_32_64(HI(31) | LO(151) /* stwx */, HI(31) | LO(149) /* stdx */),
+/* w s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(21) /* ldx */),
+
+/* Byte. */
+
+/* b u i s */ HI(38) /* stb */,
+/* b u i l */ HI(34) /* lbz */,
+/* b u x s */ HI(31) | LO(215) /* stbx */,
+/* b u x l */ HI(31) | LO(87) /* lbzx */,
+
+/* b s i s */ HI(38) /* stb */,
+/* b s i l */ HI(34) /* lbz */ /* EXTS_REQ */,
+/* b s x s */ HI(31) | LO(215) /* stbx */,
+/* b s x l */ HI(31) | LO(87) /* lbzx */ /* EXTS_REQ */,
+
+/* Half. */
+
+/* h u i s */ HI(44) /* sth */,
+/* h u i l */ HI(40) /* lhz */,
+/* h u x s */ HI(31) | LO(407) /* sthx */,
+/* h u x l */ HI(31) | LO(279) /* lhzx */,
+
+/* h s i s */ HI(44) /* sth */,
+/* h s i l */ HI(42) /* lha */,
+/* h s x s */ HI(31) | LO(407) /* sthx */,
+/* h s x l */ HI(31) | LO(343) /* lhax */,
+
+/* Int. */
+
+/* i u i s */ HI(36) /* stw */,
+/* i u i l */ HI(32) /* lwz */,
+/* i u x s */ HI(31) | LO(151) /* stwx */,
+/* i u x l */ HI(31) | LO(23) /* lwzx */,
+
+/* i s i s */ HI(36) /* stw */,
+/* i s i l */ ARCH_32_64(HI(32) /* lwz */, HI(58) | INT_ALIGNED | 0x2 /* lwa */),
+/* i s x s */ HI(31) | LO(151) /* stwx */,
+/* i s x l */ ARCH_32_64(HI(31) | LO(23) /* lwzx */, HI(31) | LO(341) /* lwax */),
+
+/* -------- Floating point -------- */
+
+/* d i s */ HI(54) /* stfd */,
+/* d i l */ HI(50) /* lfd */,
+/* d x s */ HI(31) | LO(727) /* stfdx */,
+/* d x l */ HI(31) | LO(599) /* lfdx */,
+
+/* s i s */ HI(52) /* stfs */,
+/* s i l */ HI(48) /* lfs */,
+/* s x s */ HI(31) | LO(663) /* stfsx */,
+/* s x l */ HI(31) | LO(535) /* lfsx */,
+};
+
+static const sljit_ins updated_data_transfer_insts[64] = {
+
+/* -------- Integer -------- */
+
+/* Word. */
+
+/* w u i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
+/* w u i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
+/* w u x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
+/* w u x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
+
+/* w s i s */ ARCH_32_64(HI(37) /* stwu */, HI(62) | INT_ALIGNED | 0x1 /* stdu */),
+/* w s i l */ ARCH_32_64(HI(33) /* lwzu */, HI(58) | INT_ALIGNED | 0x1 /* ldu */),
+/* w s x s */ ARCH_32_64(HI(31) | LO(183) /* stwux */, HI(31) | LO(181) /* stdux */),
+/* w s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(53) /* ldux */),
+
+/* Byte. */
+
+/* b u i s */ HI(39) /* stbu */,
+/* b u i l */ HI(35) /* lbzu */,
+/* b u x s */ HI(31) | LO(247) /* stbux */,
+/* b u x l */ HI(31) | LO(119) /* lbzux */,
+
+/* b s i s */ HI(39) /* stbu */,
+/* b s i l */ 0 /* no such instruction */,
+/* b s x s */ HI(31) | LO(247) /* stbux */,
+/* b s x l */ 0 /* no such instruction */,
+
+/* Half. */
+
+/* h u i s */ HI(45) /* sthu */,
+/* h u i l */ HI(41) /* lhzu */,
+/* h u x s */ HI(31) | LO(439) /* sthux */,
+/* h u x l */ HI(31) | LO(311) /* lhzux */,
+
+/* h s i s */ HI(45) /* sthu */,
+/* h s i l */ HI(43) /* lhau */,
+/* h s x s */ HI(31) | LO(439) /* sthux */,
+/* h s x l */ HI(31) | LO(375) /* lhaux */,
+
+/* Int. */
+
+/* i u i s */ HI(37) /* stwu */,
+/* i u i l */ HI(33) /* lwzu */,
+/* i u x s */ HI(31) | LO(183) /* stwux */,
+/* i u x l */ HI(31) | LO(55) /* lwzux */,
+
+/* i s i s */ HI(37) /* stwu */,
+/* i s i l */ ARCH_32_64(HI(33) /* lwzu */, 0 /* no such instruction */),
+/* i s x s */ HI(31) | LO(183) /* stwux */,
+/* i s x l */ ARCH_32_64(HI(31) | LO(55) /* lwzux */, HI(31) | LO(373) /* lwaux */),
+
+/* -------- Floating point -------- */
+
+/* d i s */ HI(55) /* stfdu */,
+/* d i l */ HI(51) /* lfdu */,
+/* d x s */ HI(31) | LO(759) /* stfdux */,
+/* d x l */ HI(31) | LO(631) /* lfdux */,
+
+/* s i s */ HI(53) /* stfsu */,
+/* s i l */ HI(49) /* lfsu */,
+/* s x s */ HI(31) | LO(695) /* stfsux */,
+/* s x l */ HI(31) | LO(567) /* lfsux */,
+};
+
+#undef ARCH_32_64
+
+/* Simple cases, (no caching is required). */
+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flags, sljit_s32 reg,
+ sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
+{
+ sljit_ins inst;
+ sljit_s32 offs_reg;
+
+ /* Should work when (arg & REG_MASK) == 0. */
+ SLJIT_ASSERT(A(0) == 0);
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ argw &= 0x3;
+ offs_reg = OFFS_REG(arg);
+
+ if (argw != 0) {
+ FAIL_IF(push_inst(compiler, SLWI_W(argw) | S(OFFS_REG(arg)) | A(tmp_reg)));
+ offs_reg = tmp_reg;
+ }
+
+ inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ SLJIT_ASSERT(!(inst & INT_ALIGNED));
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg & REG_MASK) | B(offs_reg));
+ }
+
+ inst = data_transfer_insts[inp_flags & MEM_MASK];
+ arg &= REG_MASK;
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if ((inst & INT_ALIGNED) && (argw & 0x3) != 0) {
+ FAIL_IF(load_immediate(compiler, tmp_reg, argw));
+
+ inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));
+ }
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ if (argw <= SIMM_MAX && argw >= SIMM_MIN)
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | IMM(argw));
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (argw <= 0x7fff7fffl && argw >= -0x80000000l) {
+#endif /* SLJIT_CONFIG_PPC_64 */
+ FAIL_IF(push_inst(compiler, ADDIS | D(tmp_reg) | A(arg) | IMM((argw + 0x8000) >> 16)));
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(tmp_reg) | IMM(argw));
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ }
+
+ FAIL_IF(load_immediate(compiler, tmp_reg, argw));
+
+ inst = data_transfer_insts[(inp_flags | INDEXED) & MEM_MASK];
+ return push_inst(compiler, INST_CODE_AND_DST(inst, inp_flags, reg) | A(arg) | B(tmp_reg));
+#endif /* SLJIT_CONFIG_PPC_64 */
+}
+
+static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 input_flags,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ /* arg1 goes to TMP_REG1 or src reg
+ arg2 goes to TMP_REG2, imm or src reg
+ result goes to TMP_REG2, so put result can use TMP_REG1. */
+ sljit_s32 dst_r = TMP_REG2;
+ sljit_s32 src1_r;
+ sljit_s32 src2_r;
+ sljit_s32 src2_tmp_reg = (!(input_flags & ALT_SIGN_EXT) && GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;
+ sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);
+
+ /* Destination check. */
+ if (FAST_IS_REG(dst)) {
+ dst_r = dst;
+ /* The REG_DEST is only used by SLJIT_MOV operations, although
+ * it is set for op2 operations with unset destination. */
+ flags |= REG_DEST;
+
+ if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
+ src2_tmp_reg = dst_r;
+ }
+
+ /* Source 2. */
+ if (FAST_IS_REG(src2)) {
+ src2_r = src2;
+ flags |= REG2_SOURCE;
+
+ if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)
+ dst_r = src2_r;
+ } else if (src2 == SLJIT_IMM) {
+ src2_r = TMP_ZERO;
+ if (src2w != 0) {
+ FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w));
+ src2_r = src2_tmp_reg;
+ }
+ } else {
+ FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, src2_tmp_reg, src2, src2w, TMP_REG1));
+ src2_r = src2_tmp_reg;
+ }
+
+ /* Source 1. */
+ if (FAST_IS_REG(src1)) {
+ src1_r = src1;
+ flags |= REG1_SOURCE;
+ } else if (src1 == SLJIT_IMM) {
+ src1_r = TMP_ZERO;
+ if (src1w != 0) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+ src1_r = TMP_REG1;
+ }
+ } else {
+ FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
+ src1_r = TMP_REG1;
+ }
+
+ FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
+
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+
+ return emit_op_mem(compiler, input_flags, dst_r, dst, dstw, TMP_REG1);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
+{
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ sljit_s32 int_op = op & SLJIT_32;
+#endif
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op0(compiler, op));
+
+ op = GET_OPCODE(op);
+ switch (op) {
+ case SLJIT_BREAKPOINT:
+ return push_inst(compiler, 0x7fe00008);
+ case SLJIT_NOP:
+ return push_inst(compiler, NOP);
+ case SLJIT_LMUL_UW:
+ case SLJIT_LMUL_SW:
+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
+ return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHDU : MULHD) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
+#else
+ FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1)));
+ return push_inst(compiler, (op == SLJIT_LMUL_UW ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1));
+#endif
+ case SLJIT_DIVMOD_UW:
+ case SLJIT_DIVMOD_SW:
+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0)));
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ FAIL_IF(push_inst(compiler, (int_op ? (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) : (op == SLJIT_DIVMOD_UW ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
+ FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
+#else
+ FAIL_IF(push_inst(compiler, (op == SLJIT_DIVMOD_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)));
+ FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1)));
+#endif
+ return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1));
+ case SLJIT_DIV_UW:
+ case SLJIT_DIV_SW:
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ return push_inst(compiler, (int_op ? (op == SLJIT_DIV_UW ? DIVWU : DIVW) : (op == SLJIT_DIV_UW ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
+#else
+ return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
+#endif
+ case SLJIT_MEMORY_BARRIER:
+ return push_inst(compiler, SYNC);
+ case SLJIT_ENDBR:
+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
+ return SLJIT_SUCCESS;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 mem, offs_reg, inp_flags;
+ sljit_sw memw;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ sljit_s32 is_32 = op & SLJIT_32;
+
+ op = GET_OPCODE(op);
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ if (!((dst | src) & SLJIT_MEM)) {
+ /* Both are registers. */
+ if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {
+ if (src == dst) {
+ FAIL_IF(push_inst(compiler, RLWIMI | S(dst) | A(dst) | RLWI_SH(16) | RLWI_MBE(8, 15)));
+ FAIL_IF(push_inst(compiler, RLWINM | S(dst) | A(dst) | RLWI_SH(24) | RLWI_MBE(16, 31)));
+ } else {
+ FAIL_IF(push_inst(compiler, RLWINM | S(src) | A(dst) | RLWI_SH(8) | RLWI_MBE(16, 23)));
+ FAIL_IF(push_inst(compiler, RLWIMI | S(src) | A(dst) | RLWI_SH(24) | RLWI_MBE(24, 31)));
+ }
+
+ if (op == SLJIT_REV_U16)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, EXTSH | S(dst) | A(dst));
+ }
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (!is_32) {
+#if defined(_ARCH_PWR10) && _ARCH_PWR10
+ return push_inst(compiler, BRD | S(src) | A(dst));
+#else /* !POWER10 */
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_HI)));
+ FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));
+ FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(SLJIT_SP) | B(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET_LO)));
+ FAIL_IF(push_inst(compiler, STWBRX | S(TMP_REG1) | A(SLJIT_SP) | B(TMP_REG2)));
+ return push_inst(compiler, LD | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);
+#endif /* POWER10 */
+ }
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(0) | IMM(TMP_MEM_OFFSET)));
+ FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(SLJIT_SP) | B(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, LWZ | D(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (op == SLJIT_REV_S32)
+ return push_inst(compiler, EXTSW | S(dst) | A(dst));
+#endif /* SLJIT_CONFIG_PPC_64 */
+ return SLJIT_SUCCESS;
+ }
+
+ mem = src;
+ memw = srcw;
+
+ if (dst & SLJIT_MEM) {
+ mem = dst;
+ memw = dstw;
+
+ if (src & SLJIT_MEM) {
+ inp_flags = HALF_DATA | LOAD_DATA;
+
+ if (op != SLJIT_REV_U16 && op != SLJIT_REV_S16) {
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ inp_flags = (is_32 ? INT_DATA : WORD_DATA) | LOAD_DATA;
+#else /* !SLJIT_CONFIG_PPC_64 */
+ inp_flags = WORD_DATA | LOAD_DATA;
+#endif /* SLJIT_CONFIG_PPC_64 */
+ }
+
+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src, srcw, TMP_REG2));
+ src = TMP_REG1;
+ }
+ }
+
+ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
+ offs_reg = OFFS_REG(mem);
+ mem &= REG_MASK;
+ memw &= 0x3;
+
+ if (memw != 0) {
+ FAIL_IF(push_inst(compiler, SLWI_W(memw) | S(offs_reg) | A(TMP_REG2)));
+ offs_reg = TMP_REG2;
+ }
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ } else if (memw > 0x7fff7fffl || memw < -0x80000000l) {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, memw));
+ offs_reg = TMP_REG2;
+ mem &= REG_MASK;
+#endif /* SLJIT_CONFIG_PPC_64 */
+ } else {
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(mem & REG_MASK) | IMM(memw)));
+ if (memw > SIMM_MAX || memw < SIMM_MIN)
+ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(TMP_REG2) | IMM((memw + 0x8000) >> 16)));
+
+ mem = 0;
+ offs_reg = TMP_REG2;
+ }
+
+ if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {
+ if (dst & SLJIT_MEM)
+ return push_inst(compiler, STHBRX | S(src) | A(mem) | B(offs_reg));
+
+ FAIL_IF(push_inst(compiler, LHBRX | S(dst) | A(mem) | B(offs_reg)));
+
+ if (op == SLJIT_REV_U16)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, EXTSH | S(dst) | A(dst));
+ }
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (!is_32) {
+ if (dst & SLJIT_MEM) {
+#if defined(_ARCH_PWR7) && _ARCH_PWR7
+ return push_inst(compiler, STDBRX | S(src) | A(mem) | B(offs_reg));
+#else /* !POWER7 */
+#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN
+ FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));
+ FAIL_IF(push_inst(compiler, STWBRX | S(TMP_REG1) | A(mem) | B(offs_reg)));
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));
+ return push_inst(compiler, STWBRX | S(src) | A(mem) | B(TMP_REG2));
+#else /* !SLJIT_LITTLE_ENDIAN */
+ FAIL_IF(push_inst(compiler, STWBRX | S(src) | A(mem) | B(offs_reg)));
+ FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(32) | RLDI_MB(32)));
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));
+ return push_inst(compiler, STWBRX | S(TMP_REG1) | A(mem) | B(TMP_REG2));
+#endif /* SLJIT_LITTLE_ENDIAN */
+#endif /* POWER7 */
+ }
+#if defined(_ARCH_PWR7) && _ARCH_PWR7
+ return push_inst(compiler, LDBRX | S(dst) | A(mem) | B(offs_reg));
+#else /* !POWER7 */
+ FAIL_IF(push_inst(compiler, LWBRX | LWBRX_FIRST_REG | A(mem) | B(offs_reg)));
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG2) | A(offs_reg) | IMM(SSIZE_OF(s32))));
+ FAIL_IF(push_inst(compiler, LWBRX | LWBRX_SECOND_REG | A(mem) | B(TMP_REG2)));
+ return push_inst(compiler, RLDIMI | S(TMP_REG1) | A(dst) | RLDI_SH(32) | RLDI_MB(0));
+#endif /* POWER7 */
+ }
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ if (dst & SLJIT_MEM)
+ return push_inst(compiler, STWBRX | S(src) | A(mem) | B(offs_reg));
+
+ FAIL_IF(push_inst(compiler, LWBRX | S(dst) | A(mem) | B(offs_reg)));
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (op == SLJIT_REV_S32)
+ return push_inst(compiler, EXTSW | S(dst) | A(dst));
+#endif /* SLJIT_CONFIG_PPC_64 */
+ return SLJIT_SUCCESS;
+}
+
+#define EMIT_MOV(type, type_flags, type_cast) \
+ emit_op(compiler, (src == SLJIT_IMM) ? SLJIT_MOV : type, flags | (type_flags), dst, dstw, TMP_REG1, 0, src, (src == SLJIT_IMM) ? type_cast srcw : srcw)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
+ sljit_s32 op_flags = GET_ALL_FLAGS(op);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ op = GET_OPCODE(op);
+
+ if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)
+ FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
+
+ if (op <= SLJIT_MOV_P && FAST_IS_REG(src) && src == dst) {
+ if (!TYPE_CAST_NEEDED(op))
+ return SLJIT_SUCCESS;
+ }
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (op_flags & SLJIT_32) {
+ if (op <= SLJIT_MOV_P) {
+ if (src & SLJIT_MEM) {
+ if (op == SLJIT_MOV_S32)
+ op = SLJIT_MOV_U32;
+ }
+ else if (src == SLJIT_IMM) {
+ if (op == SLJIT_MOV_U32)
+ op = SLJIT_MOV_S32;
+ }
+ }
+ else {
+ /* Most operations expect sign extended arguments. */
+ flags |= INT_DATA | SIGNED_DATA;
+ if (HAS_FLAGS(op_flags))
+ flags |= ALT_SIGN_EXT;
+ }
+ }
+#endif
+
+ switch (op) {
+ case SLJIT_MOV:
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+#endif
+ case SLJIT_MOV_P:
+ return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ case SLJIT_MOV_U32:
+ return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));
+
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));
+#endif
+
+ case SLJIT_MOV_U8:
+ return EMIT_MOV(SLJIT_MOV_U8, BYTE_DATA, (sljit_u8));
+
+ case SLJIT_MOV_S8:
+ return EMIT_MOV(SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, (sljit_s8));
+
+ case SLJIT_MOV_U16:
+ return EMIT_MOV(SLJIT_MOV_U16, HALF_DATA, (sljit_u16));
+
+ case SLJIT_MOV_S16:
+ return EMIT_MOV(SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, (sljit_s16));
+
+ case SLJIT_CLZ:
+ case SLJIT_CTZ:
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (op_flags & SLJIT_32)
+ flags |= ALT_FORM1;
+#endif /* SLJIT_CONFIG_PPC_64 */
+ return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ op |= SLJIT_32;
+#endif /* SLJIT_CONFIG_PPC_64 */
+ SLJIT_FALLTHROUGH
+ case SLJIT_REV:
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ op |= (op_flags & SLJIT_32);
+#endif /* SLJIT_CONFIG_PPC_64 */
+ return emit_rev(compiler, op, dst, dstw, src, srcw);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+#undef EMIT_MOV
+
+/* Macros for checking different operand types / values. */
+#define TEST_SL_IMM(src, srcw) \
+ ((src) == SLJIT_IMM && (srcw) <= SIMM_MAX && (srcw) >= SIMM_MIN)
+#define TEST_UL_IMM(src, srcw) \
+ ((src) == SLJIT_IMM && !((srcw) & ~0xffff))
+#define TEST_UH_IMM(src, srcw) \
+ ((src) == SLJIT_IMM && !((srcw) & ~(sljit_sw)0xffff0000))
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+#define TEST_SH_IMM(src, srcw) \
+ ((src) == SLJIT_IMM && !((srcw) & 0xffff) && (srcw) <= 0x7fffffffl && (srcw) >= -0x80000000l)
+#define TEST_ADD_IMM(src, srcw) \
+ ((src) == SLJIT_IMM && (srcw) <= 0x7fff7fffl && (srcw) >= -0x80000000l)
+#define TEST_UI_IMM(src, srcw) \
+ ((src) == SLJIT_IMM && !((srcw) & ~(sljit_sw)0xffffffff))
+
+#define TEST_ADD_FORM1(op) \
+ (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
+ || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z | SLJIT_SET_CARRY))
+#define TEST_SUB_FORM2(op) \
+ ((GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) \
+ || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z))
+#define TEST_SUB_FORM3(op) \
+ (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
+ || (op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z))
+
+#else /* !SLJIT_CONFIG_PPC_64 */
+#define TEST_SH_IMM(src, srcw) \
+ ((src) == SLJIT_IMM && !((srcw) & 0xffff))
+#define TEST_ADD_IMM(src, srcw) \
+ ((src) == SLJIT_IMM)
+#define TEST_UI_IMM(src, srcw) \
+ ((src) == SLJIT_IMM)
+
+#define TEST_ADD_FORM1(op) \
+ (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
+#define TEST_SUB_FORM2(op) \
+ (GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL)
+#define TEST_SUB_FORM3(op) \
+ (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (op & SLJIT_32) {
+ /* Most operations expect sign extended arguments. */
+ flags |= INT_DATA | SIGNED_DATA;
+ if (src1 == SLJIT_IMM)
+ src1w = (sljit_s32)(src1w);
+ if (src2 == SLJIT_IMM)
+ src2w = (sljit_s32)(src2w);
+ if (HAS_FLAGS(op))
+ flags |= ALT_SIGN_EXT;
+ }
+#endif
+ if (GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
+ FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+
+ if (TEST_ADD_FORM1(op))
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
+
+ if (!HAS_FLAGS(op) && (src1 == SLJIT_IMM || src2 == SLJIT_IMM)) {
+ if (TEST_SL_IMM(src2, src2w)) {
+ compiler->imm = (sljit_ins)src2w & 0xffff;
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ if (TEST_SL_IMM(src1, src1w)) {
+ compiler->imm = (sljit_ins)src1w & 0xffff;
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
+ }
+ if (TEST_SH_IMM(src2, src2w)) {
+ compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ if (TEST_SH_IMM(src1, src1w)) {
+ compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
+ }
+ /* Range between -1 and -32768 is covered above. */
+ if (TEST_ADD_IMM(src2, src2w)) {
+ compiler->imm = (sljit_ins)src2w & 0xffffffff;
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ if (TEST_ADD_IMM(src1, src1w)) {
+ compiler->imm = (sljit_ins)src1w & 0xffffffff;
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
+ }
+ }
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if ((op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z)) {
+ if (TEST_SL_IMM(src2, src2w)) {
+ compiler->imm = (sljit_ins)src2w & 0xffff;
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ if (TEST_SL_IMM(src1, src1w)) {
+ compiler->imm = (sljit_ins)src1w & 0xffff;
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src2, src2w, TMP_REG2, 0);
+ }
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
+ }
+#endif
+ if (HAS_FLAGS(op)) {
+ if (TEST_SL_IMM(src2, src2w)) {
+ compiler->imm = (sljit_ins)src2w & 0xffff;
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ if (TEST_SL_IMM(src1, src1w)) {
+ compiler->imm = (sljit_ins)src1w & 0xffff;
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
+ }
+ }
+ return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == SLJIT_CARRY) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_ADDC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_SUB:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+
+ if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {
+ if (dst == TMP_REG1) {
+ if (TEST_UL_IMM(src2, src2w)) {
+ compiler->imm = (sljit_ins)src2w & 0xffff;
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src2 == SLJIT_IMM && src2w >= 0 && src2w <= (SIMM_MAX + 1)) {
+ compiler->imm = (sljit_ins)src2w;
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (dst == TMP_REG1 && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
+ if (TEST_SL_IMM(src2, src2w)) {
+ compiler->imm = (sljit_ins)src2w & 0xffff;
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (TEST_SUB_FORM2(op)) {
+ if (src2 == SLJIT_IMM && src2w >= -SIMM_MAX && src2w <= SIMM_MAX) {
+ compiler->imm = (sljit_ins)src2w & 0xffff;
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (TEST_SUB_FORM3(op))
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
+
+ if (TEST_SL_IMM(src2, -src2w)) {
+ compiler->imm = (sljit_ins)(-src2w) & 0xffff;
+ return emit_op(compiler, SLJIT_ADD, flags | (!HAS_FLAGS(op) ? ALT_FORM2 : ALT_FORM3), dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+
+ if (TEST_SL_IMM(src1, src1w) && !(op & SLJIT_SET_Z)) {
+ compiler->imm = (sljit_ins)src1w & 0xffff;
+ return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
+ }
+
+ if (!HAS_FLAGS(op)) {
+ if (TEST_SH_IMM(src2, -src2w)) {
+ compiler->imm = (sljit_ins)((-src2w) >> 16) & 0xffff;
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ /* Range between -1 and -32768 is covered above. */
+ if (TEST_ADD_IMM(src2, -src2w)) {
+ compiler->imm = (sljit_ins)-src2w;
+ return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ }
+
+ /* We know ALT_SIGN_EXT is set if it is an SLJIT_32 on 64 bit systems. */
+ return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == SLJIT_CARRY) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_SUBC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_MUL:
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (op & SLJIT_32)
+ flags |= ALT_FORM2;
+#endif
+ if (!HAS_FLAGS(op)) {
+ if (TEST_SL_IMM(src2, src2w)) {
+ compiler->imm = (sljit_ins)src2w & 0xffff;
+ return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ if (TEST_SL_IMM(src1, src1w)) {
+ compiler->imm = (sljit_ins)src1w & 0xffff;
+ return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
+ }
+ }
+ else
+ FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
+ return emit_op(compiler, SLJIT_MUL, flags, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_XOR:
+ if (src2 == SLJIT_IMM && src2w == -1) {
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src1, src1w);
+ }
+ if (src1 == SLJIT_IMM && src1w == -1) {
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src2, src2w);
+ }
+ SLJIT_FALLTHROUGH
+ case SLJIT_AND:
+ case SLJIT_OR:
+ /* Commutative unsigned operations. */
+ if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
+ if (TEST_UL_IMM(src2, src2w)) {
+ compiler->imm = (sljit_ins)src2w;
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ if (TEST_UL_IMM(src1, src1w)) {
+ compiler->imm = (sljit_ins)src1w;
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
+ }
+ if (TEST_UH_IMM(src2, src2w)) {
+ compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ if (TEST_UH_IMM(src1, src1w)) {
+ compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
+ }
+ }
+ if (!HAS_FLAGS(op) && GET_OPCODE(op) != SLJIT_AND) {
+ /* Unlike or and xor, the and resets unwanted bits as well. */
+ if (TEST_UI_IMM(src2, src2w)) {
+ compiler->imm = (sljit_ins)src2w;
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ if (TEST_UI_IMM(src1, src1w)) {
+ compiler->imm = (sljit_ins)src1w;
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
+ }
+ }
+ return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ case SLJIT_ROTL:
+ case SLJIT_ROTR:
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (op & SLJIT_32)
+ flags |= ALT_FORM2;
+#endif
+ if (src2 == SLJIT_IMM) {
+ compiler->imm = (sljit_ins)src2w;
+ return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
+ }
+ return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
+}
+
+#undef TEST_ADD_FORM1
+#undef TEST_SUB_FORM2
+#undef TEST_SUB_FORM3
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MULADD:
+ SLJIT_SKIP_CHECKS(compiler);
+ FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));
+ return push_inst(compiler, ADD | D(dst_reg) | A(dst_reg) | B(TMP_REG2));
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1_reg,
+ sljit_s32 src2_reg,
+ sljit_s32 src3, sljit_sw src3w)
+{
+ sljit_s32 is_right;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
+ sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;
+#else /* !SLJIT_CONFIG_PPC_64 */
+ sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
+ sljit_sw bit_length = 32;
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
+
+ is_right = (GET_OPCODE(op) == SLJIT_LSHR || GET_OPCODE(op) == SLJIT_MLSHR);
+
+ if (src1_reg == src2_reg) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, (is_right ? SLJIT_ROTR : SLJIT_ROTL) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);
+ }
+
+ ADJUST_LOCAL_OFFSET(src3, src3w);
+
+ if (src3 == SLJIT_IMM) {
+ src3w &= bit_length - 1;
+
+ if (src3w == 0)
+ return SLJIT_SUCCESS;
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (!(op & SLJIT_32)) {
+ if (is_right) {
+ FAIL_IF(push_inst(compiler, SRDI(src3w) | S(src1_reg) | A(dst_reg)));
+ return push_inst(compiler, RLDIMI | S(src2_reg) | A(dst_reg) | RLDI_SH(64 - src3w) | RLDI_MB(0));
+ }
+
+ FAIL_IF(push_inst(compiler, SLDI(src3w) | S(src1_reg) | A(dst_reg)));
+ /* Computes SRDI(64 - src2w). */
+ FAIL_IF(push_inst(compiler, RLDICL | S(src2_reg) | A(TMP_REG1) | RLDI_SH(src3w) | RLDI_MB(64 - src3w)));
+ return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));
+ }
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ if (is_right) {
+ FAIL_IF(push_inst(compiler, SRWI(src3w) | S(src1_reg) | A(dst_reg)));
+ return push_inst(compiler, RLWIMI | S(src2_reg) | A(dst_reg) | RLWI_SH(32 - src3w) | RLWI_MBE(0, src3w - 1));
+ }
+
+ FAIL_IF(push_inst(compiler, SLWI(src3w) | S(src1_reg) | A(dst_reg)));
+ return push_inst(compiler, RLWIMI | S(src2_reg) | A(dst_reg) | RLWI_SH(src3w) | RLWI_MBE(32 - src3w, 31));
+ }
+
+ if (src3 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w, TMP_REG2));
+ src3 = TMP_REG2;
+ }
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (!(op & SLJIT_32)) {
+ if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR || dst_reg == src3) {
+ FAIL_IF(push_inst(compiler, ANDI | S(src3) | A(TMP_REG2) | 0x3f));
+ src3 = TMP_REG2;
+ }
+
+ FAIL_IF(push_inst(compiler, (is_right ? SRD : SLD) | S(src1_reg) | A(dst_reg) | B(src3)));
+ FAIL_IF(push_inst(compiler, (is_right ? SLDI(1) : SRDI(1)) | S(src2_reg) | A(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, XORI | S(src3) | A(TMP_REG2) | 0x3f));
+ FAIL_IF(push_inst(compiler, (is_right ? SLD : SRD) | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));
+ return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));
+ }
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR || dst_reg == src3) {
+ FAIL_IF(push_inst(compiler, ANDI | S(src3) | A(TMP_REG2) | 0x1f));
+ src3 = TMP_REG2;
+ }
+
+ FAIL_IF(push_inst(compiler, (is_right ? SRW : SLW) | S(src1_reg) | A(dst_reg) | B(src3)));
+ FAIL_IF(push_inst(compiler, (is_right ? SLWI(1) : SRWI(1)) | S(src2_reg) | A(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, XORI | S(src3) | A(TMP_REG2) | 0x1f));
+ FAIL_IF(push_inst(compiler, (is_right ? SLW : SRW) | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));
+ return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r, tmp_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);
+
+ if (src2 == SLJIT_IMM) {
+ src2w = (sljit_sw)((sljit_uw)src2w << shift_arg);
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+ src1 = TMP_REG1;
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
+ src1 = TMP_REG1;
+ }
+
+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, tmp_r, src2, src2w, tmp_r));
+ src2 = tmp_r;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ FAIL_IF(push_inst(compiler, SLWI_W(shift_arg) | S(src2) | A(tmp_r)));
+ FAIL_IF(push_inst(compiler, ADD | D(dst_r) | A(src1) | B(tmp_r)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_DATA, dst_r, dst, dstw, TMP_REG1);
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+ if (!(src & OFFS_REG_MASK)) {
+ if (srcw == 0 && (src & REG_MASK))
+ return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK));
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ /* Works with SLJIT_MEM0() case as well. */
+ return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
+ }
+
+ srcw &= 0x3;
+
+ if (srcw == 0)
+ return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src)));
+
+ FAIL_IF(push_inst(compiler, SLWI_W(srcw) | S(OFFS_REG(src)) | A(TMP_REG1)));
+ return push_inst(compiler, DCBT | A(src & REG_MASK) | B(TMP_REG1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ switch (op) {
+ case SLJIT_FAST_RETURN:
+ if (FAST_IS_REG(src))
+ FAIL_IF(push_inst(compiler, MTLR | S(src)));
+ else {
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG2));
+ FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));
+ }
+
+ return push_inst(compiler, BLR);
+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
+ return SLJIT_SUCCESS;
+ case SLJIT_PREFETCH_L1:
+ case SLJIT_PREFETCH_L2:
+ case SLJIT_PREFETCH_L3:
+ case SLJIT_PREFETCH_ONCE:
+ return emit_prefetch(compiler, src, srcw);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ switch (op) {
+ case SLJIT_FAST_ENTER:
+ if (FAST_IS_REG(dst))
+ return push_inst(compiler, MFLR | D(dst));
+
+ FAIL_IF(push_inst(compiler, MFLR | D(TMP_REG1)));
+ break;
+ case SLJIT_GET_RETURN_ADDRESS:
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + LR_SAVE_OFFSET, TMP_REG2));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_DATA, TMP_REG1, dst, dstw, TMP_REG2);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
+{
+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
+
+ if (type == SLJIT_GP_REGISTER)
+ return reg_map[reg];
+
+ if (type != SLJIT_FLOAT_REGISTER)
+ return -1;
+
+ return freg_map[reg];
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_u32 size)
+{
+ SLJIT_UNUSED_ARG(size);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
+
+ return push_inst(compiler, *(sljit_ins*)instruction);
+}
+
+/* --------------------------------------------------------------------- */
+/* Floating point operators */
+/* --------------------------------------------------------------------- */
+
+#define SELECT_FOP(op, single, double) ((sljit_ins)((op & SLJIT_32) ? single : double))
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ if (src & SLJIT_MEM) {
+ /* We can ignore the temporary data store on the stack from caching point of view. */
+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
+ src = TMP_FREG1;
+ }
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ op = GET_OPCODE(op);
+ FAIL_IF(push_inst(compiler, (op == SLJIT_CONV_S32_FROM_F64 ? FCTIWZ : FCTIDZ) | FD(TMP_FREG1) | FB(src)));
+
+ if (op == SLJIT_CONV_SW_FROM_F64) {
+ if (FAST_IS_REG(dst)) {
+ FAIL_IF(push_inst(compiler, STFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ return push_inst(compiler, LD | S(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);
+ }
+ return emit_op_mem(compiler, DOUBLE_DATA, TMP_FREG1, dst, dstw, TMP_REG1);
+ }
+#else /* !SLJIT_CONFIG_PPC_64 */
+ FAIL_IF(push_inst(compiler, FCTIWZ | FD(TMP_FREG1) | FB(src)));
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ if (FAST_IS_REG(dst)) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, TMP_MEM_OFFSET));
+ FAIL_IF(push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(SLJIT_SP) | B(TMP_REG1)));
+ return push_inst(compiler, LWZ | S(dst) | A(SLJIT_SP) | TMP_MEM_OFFSET);
+ }
+
+ SLJIT_ASSERT(dst & SLJIT_MEM);
+
+ if (dst & OFFS_REG_MASK) {
+ dstw &= 0x3;
+ if (dstw) {
+ FAIL_IF(push_inst(compiler, SLWI_W(dstw) | S(OFFS_REG(dst)) | A(TMP_REG1)));
+ dstw = TMP_REG1;
+ } else
+ dstw = OFFS_REG(dst);
+ }
+ else {
+ if ((dst & REG_MASK) && !dstw) {
+ dstw = dst & REG_MASK;
+ dst = 0;
+ } else {
+ /* This works regardless we have SLJIT_MEM1 or SLJIT_MEM0. */
+ FAIL_IF(load_immediate(compiler, TMP_REG1, dstw));
+ dstw = TMP_REG1;
+ }
+ }
+
+ return push_inst(compiler, STFIWX | FS(TMP_FREG1) | A(dst & REG_MASK) | B(dstw));
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));
+ src1 = TMP_FREG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG2));
+ src2 = TMP_FREG2;
+ }
+
+ FAIL_IF(push_inst(compiler, FCMPU | CRD(4) | FA(src1) | FB(src2)));
+
+ switch (GET_FLAG_TYPE(op)) {
+ case SLJIT_UNORDERED_OR_EQUAL:
+ return push_inst(compiler, CROR | ((4 + 2) << 21) | ((4 + 2) << 16) | ((4 + 3) << 11));
+ case SLJIT_UNORDERED_OR_LESS:
+ return push_inst(compiler, CROR | ((4 + 0) << 21) | ((4 + 0) << 16) | ((4 + 3) << 11));
+ case SLJIT_UNORDERED_OR_GREATER:
+ return push_inst(compiler, CROR | ((4 + 1) << 21) | ((4 + 1) << 16) | ((4 + 3) << 11));
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+
+ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
+
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
+ op ^= SLJIT_32;
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, TMP_REG1));
+ src = dst_r;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_CONV_F64_FROM_F32:
+ op ^= SLJIT_32;
+ if (op & SLJIT_32) {
+ FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));
+ break;
+ }
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_F64:
+ if (src != dst_r) {
+ if (!(dst & SLJIT_MEM))
+ FAIL_IF(push_inst(compiler, FMR | FD(dst_r) | FB(src)));
+ else
+ dst_r = src;
+ }
+ break;
+ case SLJIT_NEG_F64:
+ FAIL_IF(push_inst(compiler, FNEG | FD(dst_r) | FB(src)));
+ break;
+ case SLJIT_ABS_F64:
+ FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src)));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), dst_r, dst, dstw, TMP_REG1));
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, TMP_REG1));
+ src1 = TMP_FREG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, TMP_REG1));
+ src2 = TMP_FREG2;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD_F64:
+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FADDS, FADD) | FD(dst_r) | FA(src1) | FB(src2)));
+ break;
+ case SLJIT_SUB_F64:
+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSUBS, FSUB) | FD(dst_r) | FA(src1) | FB(src2)));
+ break;
+ case SLJIT_MUL_F64:
+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FMULS, FMUL) | FD(dst_r) | FA(src1) | FC(src2) /* FMUL use FC as src2 */));
+ break;
+ case SLJIT_DIV_F64:
+ FAIL_IF(push_inst(compiler, SELECT_FOP(op, FDIVS, FDIV) | FD(dst_r) | FA(src1) | FB(src2)));
+ break;
+ case SLJIT_COPYSIGN_F64:
+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STFS : STFD) | FS(src2) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ FAIL_IF(push_inst(compiler, LWZ | S(TMP_REG1) | A(SLJIT_SP) | ((op & SLJIT_32) ? TMP_MEM_OFFSET : TMP_MEM_OFFSET_HI)));
+#else /* !SLJIT_CONFIG_PPC_32 */
+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? LWZ : LD) | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+#endif /* SLJIT_CONFIG_PPC_32 */
+ FAIL_IF(push_inst(compiler, FABS | FD(dst_r) | FB(src1)));
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(TMP_REG1) | 0));
+#else /* !SLJIT_CONFIG_PPC_32 */
+ FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((op & SLJIT_32) ? 0 : 1)) | A(TMP_REG1) | 0));
+#endif /* SLJIT_CONFIG_PPC_32 */
+ FAIL_IF(push_inst(compiler, BCx | (4 << 21) | (0 << 16) | 8));
+ return push_inst(compiler, FNEG | FD(dst_r) | FB(dst_r));
+ }
+
+ if (dst & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, TMP_REG1));
+
+ return SLJIT_SUCCESS;
+}
+
+#undef SELECT_FOP
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f32 value)
+{
+ union {
+ sljit_s32 imm;
+ sljit_f32 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset32(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm != 0)
+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));
+
+ FAIL_IF(push_inst(compiler, STW | S(u.imm != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));
+ return push_inst(compiler, LFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
+}
+
+/* --------------------------------------------------------------------- */
+/* Conditional instructions */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_label(compiler));
+
+ if (compiler->last_label && compiler->last_label->size == compiler->size)
+ return compiler->last_label;
+
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+ PTR_FAIL_IF(!label);
+ set_label(label, compiler);
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, i;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (alignment <= SLJIT_LABEL_ALIGN_4) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);
+
+ for (i = (mask >> 2); i != 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ for (i = (buffers->size + 3) >> 2; i > 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
+static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type)
+{
+ switch (type) {
+ case SLJIT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
+ return (4 << 21) | (2 << 16);
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_EQUAL:
+ case SLJIT_ATOMIC_STORED:
+ return (12 << 21) | (2 << 16);
+
+ case SLJIT_NOT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
+ return (12 << 21) | (2 << 16);
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_NOT_EQUAL:
+ case SLJIT_ATOMIC_NOT_STORED:
+ return (4 << 21) | (2 << 16);
+
+ case SLJIT_LESS:
+ case SLJIT_SIG_LESS:
+ return (12 << 21) | (0 << 16);
+
+ case SLJIT_GREATER_EQUAL:
+ case SLJIT_SIG_GREATER_EQUAL:
+ return (4 << 21) | (0 << 16);
+
+ case SLJIT_GREATER:
+ case SLJIT_SIG_GREATER:
+ return (12 << 21) | (1 << 16);
+
+ case SLJIT_LESS_EQUAL:
+ case SLJIT_SIG_LESS_EQUAL:
+ return (4 << 21) | (1 << 16);
+
+ case SLJIT_OVERFLOW:
+ return (12 << 21) | (3 << 16);
+
+ case SLJIT_NOT_OVERFLOW:
+ return (4 << 21) | (3 << 16);
+
+ case SLJIT_F_LESS:
+ case SLJIT_ORDERED_LESS:
+ case SLJIT_UNORDERED_OR_LESS:
+ return (12 << 21) | ((4 + 0) << 16);
+
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_ORDERED_GREATER_EQUAL:
+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:
+ return (4 << 21) | ((4 + 0) << 16);
+
+ case SLJIT_F_GREATER:
+ case SLJIT_ORDERED_GREATER:
+ case SLJIT_UNORDERED_OR_GREATER:
+ return (12 << 21) | ((4 + 1) << 16);
+
+ case SLJIT_F_LESS_EQUAL:
+ case SLJIT_ORDERED_LESS_EQUAL:
+ case SLJIT_UNORDERED_OR_LESS_EQUAL:
+ return (4 << 21) | ((4 + 1) << 16);
+
+ case SLJIT_F_EQUAL:
+ case SLJIT_ORDERED_EQUAL:
+ case SLJIT_UNORDERED_OR_EQUAL:
+ return (12 << 21) | ((4 + 2) << 16);
+
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_NOT_EQUAL:
+ return (4 << 21) | ((4 + 2) << 16);
+
+ case SLJIT_UNORDERED:
+ return (12 << 21) | ((4 + 3) << 16);
+
+ case SLJIT_ORDERED:
+ return (4 << 21) | ((4 + 3) << 16);
+
+ default:
+ SLJIT_ASSERT(type >= SLJIT_JUMP && type <= SLJIT_CALL_REG_ARG);
+ return (20 << 21);
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
+{
+ struct sljit_jump *jump;
+ sljit_ins bo_bi_flags;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_jump(compiler, type));
+
+ bo_bi_flags = get_bo_bi_flags(compiler, type & 0xff);
+ if (!bo_bi_flags)
+ return NULL;
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, (sljit_u32)type & SLJIT_REWRITABLE_JUMP);
+ type &= 0xff;
+
+ if ((type | 0x1) == SLJIT_NOT_CARRY)
+ PTR_FAIL_IF(push_inst(compiler, ADDME | RC(ALT_SET_FLAGS) | D(TMP_REG2) | A(TMP_ZERO)));
+
+ /* In PPC, we don't need to touch the arguments. */
+ if (type < SLJIT_JUMP)
+ jump->flags |= IS_COND;
+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
+ if (type >= SLJIT_CALL)
+ jump->flags |= IS_CALL;
+#endif
+
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(push_inst(compiler, BCCTR | bo_bi_flags | (type >= SLJIT_FAST_CALL ? 1 : 0)));
+
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += JUMP_MAX_SIZE - 1;
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types)
+{
+ SLJIT_UNUSED_ARG(arg_types);
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)
+ PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
+#endif
+
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_jump(compiler, type);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
+{
+ struct sljit_jump *jump = NULL;
+ sljit_s32 src_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
+
+ if (src == SLJIT_IMM) {
+ /* These jumps are converted to jump/call instructions when possible. */
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF(!jump);
+ set_jump(jump, compiler, JUMP_ADDR);
+ jump->u.target = (sljit_uw)srcw;
+
+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
+ if (type >= SLJIT_CALL)
+ jump->flags |= IS_CALL;
+#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
+
+ jump->addr = compiler->size;
+ FAIL_IF(push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0)));
+
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += JUMP_MAX_SIZE - 1;
+ return SLJIT_SUCCESS;
+ }
+
+ if (FAST_IS_REG(src)) {
+#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
+ if (type >= SLJIT_CALL && src != TMP_CALL_REG) {
+ FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
+ src_r = TMP_CALL_REG;
+ } else
+ src_r = src;
+#else /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
+ src_r = src;
+#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
+ } else {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));
+ src_r = TMP_CALL_REG;
+ }
+
+ FAIL_IF(push_inst(compiler, MTCTR | S(src_r)));
+ return push_inst(compiler, BCCTR | (20 << 21) | (type >= SLJIT_FAST_CALL ? 1 : 0));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types,
+ sljit_s32 src, sljit_sw srcw)
+{
+ SLJIT_UNUSED_ARG(arg_types);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_CALL_REG, src, srcw, TMP_CALL_REG));
+ src = TMP_CALL_REG;
+ }
+
+ if (type & SLJIT_CALL_RETURN) {
+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
+ src = TMP_CALL_REG;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 0));
+ type = SLJIT_JUMP;
+ }
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)
+ FAIL_IF(call_with_args(compiler, arg_types, &src));
+#endif
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, type, src, srcw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 type)
+{
+ sljit_s32 reg, invert;
+ sljit_u32 bit, from_xer;
+ sljit_s32 saved_op = op;
+ sljit_sw saved_dstw = dstw;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ sljit_s32 input_flags = ((op & SLJIT_32) || op == SLJIT_MOV32) ? INT_DATA : WORD_DATA;
+#else
+ sljit_s32 input_flags = WORD_DATA;
+#endif
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ op = GET_OPCODE(op);
+ reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
+
+ if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
+ FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG1));
+
+ invert = 0;
+ bit = 0;
+ from_xer = 0;
+
+ switch (type) {
+ case SLJIT_LESS:
+ case SLJIT_SIG_LESS:
+ break;
+
+ case SLJIT_GREATER_EQUAL:
+ case SLJIT_SIG_GREATER_EQUAL:
+ invert = 1;
+ break;
+
+ case SLJIT_GREATER:
+ case SLJIT_SIG_GREATER:
+ bit = 1;
+ break;
+
+ case SLJIT_LESS_EQUAL:
+ case SLJIT_SIG_LESS_EQUAL:
+ bit = 1;
+ invert = 1;
+ break;
+
+ case SLJIT_EQUAL:
+ case SLJIT_ATOMIC_STORED:
+ bit = 2;
+ break;
+
+ case SLJIT_NOT_EQUAL:
+ case SLJIT_ATOMIC_NOT_STORED:
+ bit = 2;
+ invert = 1;
+ break;
+
+ case SLJIT_OVERFLOW:
+ from_xer = 1;
+ bit = 1;
+ break;
+
+ case SLJIT_NOT_OVERFLOW:
+ from_xer = 1;
+ bit = 1;
+ invert = 1;
+ break;
+
+ case SLJIT_CARRY:
+ from_xer = 1;
+ bit = 2;
+ invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB) != 0;
+ break;
+
+ case SLJIT_NOT_CARRY:
+ from_xer = 1;
+ bit = 2;
+ invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD) != 0;
+ break;
+
+ case SLJIT_F_LESS:
+ case SLJIT_ORDERED_LESS:
+ case SLJIT_UNORDERED_OR_LESS:
+ bit = 4 + 0;
+ break;
+
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_ORDERED_GREATER_EQUAL:
+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:
+ bit = 4 + 0;
+ invert = 1;
+ break;
+
+ case SLJIT_F_GREATER:
+ case SLJIT_ORDERED_GREATER:
+ case SLJIT_UNORDERED_OR_GREATER:
+ bit = 4 + 1;
+ break;
+
+ case SLJIT_F_LESS_EQUAL:
+ case SLJIT_ORDERED_LESS_EQUAL:
+ case SLJIT_UNORDERED_OR_LESS_EQUAL:
+ bit = 4 + 1;
+ invert = 1;
+ break;
+
+ case SLJIT_F_EQUAL:
+ case SLJIT_ORDERED_EQUAL:
+ case SLJIT_UNORDERED_OR_EQUAL:
+ bit = 4 + 2;
+ break;
+
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_NOT_EQUAL:
+ bit = 4 + 2;
+ invert = 1;
+ break;
+
+ case SLJIT_UNORDERED:
+ bit = 4 + 3;
+ break;
+
+ case SLJIT_ORDERED:
+ bit = 4 + 3;
+ invert = 1;
+ break;
+
+ default:
+ SLJIT_UNREACHABLE();
+ break;
+ }
+
+ FAIL_IF(push_inst(compiler, (from_xer ? MFXER : MFCR) | D(reg)));
+ /* Simplified mnemonics: extrwi. */
+ FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | RLWI_SH(1 + bit) | RLWI_MBE(31, 31)));
+
+ if (invert)
+ FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));
+
+ if (op < SLJIT_ADD) {
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+ return emit_op_mem(compiler, input_flags, reg, dst, dstw, TMP_REG1);
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+
+ if (dst & SLJIT_MEM)
+ return sljit_emit_op2(compiler, saved_op, dst, saved_dstw, TMP_REG1, 0, TMP_REG2, 0);
+ return sljit_emit_op2(compiler, saved_op, dst, 0, dst, 0, TMP_REG2, 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_reg)
+{
+ sljit_ins *ptr;
+ sljit_uw size;
+ sljit_s32 is_compare = (type & SLJIT_COMPARE_SELECT);
+ sljit_ins ins;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
+#else /* !SLJIT_CONFIG_PPC_64 */
+ sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (src1 == SLJIT_IMM && (type & SLJIT_32))
+ src1w = (sljit_s32)src1w;
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);
+
+ if (is_compare) {
+ ins = 0;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src1, src1w, TMP_REG1));
+ src1 = TMP_REG1;
+ src1w = 0;
+ }
+
+ if (src1 == SLJIT_IMM) {
+ if (type >= SLJIT_LESS && type <= SLJIT_LESS_EQUAL && src1w >= 0 && src1w <= UIMM_MAX)
+ ins = CMPLI | CRD(0) | IMM(src1w);
+ else if (type >= SLJIT_SIG_LESS && type <= SLJIT_SIG_LESS_EQUAL && src1w >= SIMM_MIN && src1w <= SIMM_MAX)
+ ins = CMPI | CRD(0) | IMM(src1w);
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+ src1 = TMP_REG1;
+ src1w = 0;
+ }
+ }
+
+ if (ins == 0)
+ ins = ((type >= SLJIT_LESS && type <= SLJIT_LESS_EQUAL) ? CMPL : CMP) | CRD(0) | B(src1);
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (inp_flags == (WORD_DATA | LOAD_DATA))
+ ins |= CRD(1);
+#endif /* SLJIT_CONFIG_PPC_64 */
+ FAIL_IF(push_inst(compiler, ins | A(src2_reg)));
+ type ^= 0x1;
+ }
+
+ if (dst_reg != src2_reg) {
+ if (dst_reg == src1) {
+ src1 = src2_reg;
+ src1w = 0;
+ type ^= 0x1;
+ } else {
+ if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
+ FAIL_IF(push_inst(compiler, OR | S(dst_reg) | A(TMP_REG1) | B(dst_reg)));
+
+ if ((src1 & REG_MASK) == dst_reg)
+ src1 = (src1 & ~REG_MASK) | TMP_REG1;
+
+ if (OFFS_REG(src1) == dst_reg)
+ src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);
+ }
+
+ FAIL_IF(push_inst(compiler, OR | S(src2_reg) | A(dst_reg) | B(src2_reg)));
+ }
+ }
+
+ if ((type | 0x1) == SLJIT_NOT_CARRY)
+ FAIL_IF(push_inst(compiler, ADDME | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO)));
+
+ size = compiler->size;
+
+ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ compiler->size++;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w, TMP_REG1));
+ } else if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, dst_reg, src1w));
+ } else
+ FAIL_IF(push_inst(compiler, OR | S(src1) | A(dst_reg) | B(src1)));
+
+ *ptr = BCx | get_bo_bi_flags(compiler, type ^ 0x1) | (sljit_ins)((compiler->size - size) << 2);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_freg)
+{
+ sljit_ins *ptr;
+ sljit_uw size;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ if (dst_freg != src2_freg) {
+ if (dst_freg == src1) {
+ src1 = src2_freg;
+ src1w = 0;
+ type ^= 0x1;
+ } else
+ FAIL_IF(push_inst(compiler, FMR | FD(dst_freg) | FB(src2_freg)));
+ }
+
+ if (((type & ~SLJIT_32) | 0x1) == SLJIT_NOT_CARRY)
+ FAIL_IF(push_inst(compiler, ADDME | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO)));
+
+ size = compiler->size;
+
+ ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ compiler->size++;
+
+ if (src1 & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, dst_freg, src1, src1w, TMP_REG1));
+ else
+ FAIL_IF(push_inst(compiler, FMR | FD(dst_freg) | FB(src1)));
+
+ *ptr = BCx | get_bo_bi_flags(compiler, (type ^ 0x1) & ~SLJIT_32) | (sljit_ins)((compiler->size - size) << 2);
+ return SLJIT_SUCCESS;
+}
+
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+
+#define EMIT_MEM_LOAD_IMM(inst, mem, memw) \
+ ((sljit_s16)(memw) > SIMM_MAX - SSIZE_OF(sw))
+
+#else /* !SLJIT_CONFIG_PPC_32 */
+
+#define EMIT_MEM_LOAD_IMM(inst, mem, memw) \
+ ((((inst) & INT_ALIGNED) && ((memw) & 0x3) != 0) \
+ || ((sljit_s16)(memw) > SIMM_MAX - SSIZE_OF(sw)) \
+ || ((memw) > 0x7fff7fffl || (memw) < -0x80000000l)) \
+
+#endif /* SLJIT_CONFIG_PPC_32 */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_ins inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
+
+ if (!(reg & REG_PAIR_MASK))
+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
+
+ ADJUST_LOCAL_OFFSET(mem, memw);
+
+ inst = data_transfer_insts[WORD_DATA | ((type & SLJIT_MEM_STORE) ? 0 : LOAD_DATA)];
+
+ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
+ memw &= 0x3;
+
+ if (memw != 0) {
+ FAIL_IF(push_inst(compiler, SLWI_W(memw) | S(OFFS_REG(mem)) | A(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, ADD | D(TMP_REG1) | A(TMP_REG1) | B(mem & REG_MASK)));
+ } else
+ FAIL_IF(push_inst(compiler, ADD | D(TMP_REG1) | A(mem & REG_MASK) | B(OFFS_REG(mem))));
+
+ mem = TMP_REG1;
+ memw = 0;
+ } else {
+ if (EMIT_MEM_LOAD_IMM(inst, mem, memw)) {
+ if ((mem & REG_MASK) != 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ FAIL_IF(sljit_emit_op2(compiler, SLJIT_ADD, TMP_REG1, 0, mem & REG_MASK, 0, SLJIT_IMM, memw));
+ } else
+ FAIL_IF(load_immediate(compiler, TMP_REG1, memw));
+
+ memw = 0;
+ mem = TMP_REG1;
+ } else if (memw > SIMM_MAX || memw < SIMM_MIN) {
+ FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(mem & REG_MASK) | IMM((memw + 0x8000) >> 16)));
+
+ memw &= 0xffff;
+ mem = TMP_REG1;
+ } else {
+ memw &= 0xffff;
+ mem &= REG_MASK;
+ }
+ }
+
+ SLJIT_ASSERT((memw >= 0 && memw <= SIMM_MAX - SSIZE_OF(sw)) || (memw >= 0x8000 && memw <= 0xffff));
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ inst &= (sljit_ins)~INT_ALIGNED;
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {
+ FAIL_IF(push_inst(compiler, inst | D(REG_PAIR_SECOND(reg)) | A(mem) | IMM(memw + SSIZE_OF(sw))));
+ return push_inst(compiler, inst | D(REG_PAIR_FIRST(reg)) | A(mem) | IMM(memw));
+ }
+
+ FAIL_IF(push_inst(compiler, inst | D(REG_PAIR_FIRST(reg)) | A(mem) | IMM(memw)));
+ return push_inst(compiler, inst | D(REG_PAIR_SECOND(reg)) | A(mem) | IMM(memw + SSIZE_OF(sw)));
+}
+
+#undef EMIT_MEM_LOAD_IMM
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_s32 mem_flags;
+ sljit_ins inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem_update(compiler, type, reg, mem, memw));
+
+ if (type & SLJIT_MEM_POST)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (type & 0xff) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+#endif
+ mem_flags = WORD_DATA;
+ break;
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV32:
+ mem_flags = INT_DATA;
+ break;
+
+ case SLJIT_MOV_S32:
+ mem_flags = INT_DATA;
+
+ if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_32)) {
+ if (mem & OFFS_REG_MASK)
+ mem_flags |= SIGNED_DATA;
+ else
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+ break;
+#endif
+
+ case SLJIT_MOV_U8:
+ case SLJIT_MOV_S8:
+ mem_flags = BYTE_DATA;
+ break;
+
+ case SLJIT_MOV_U16:
+ mem_flags = HALF_DATA;
+ break;
+
+ case SLJIT_MOV_S16:
+ mem_flags = HALF_DATA | SIGNED_DATA;
+ break;
+
+ default:
+ SLJIT_UNREACHABLE();
+ mem_flags = WORD_DATA;
+ break;
+ }
+
+ if (!(type & SLJIT_MEM_STORE))
+ mem_flags |= LOAD_DATA;
+
+ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
+ if (memw != 0)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_MEM_SUPP)
+ return SLJIT_SUCCESS;
+
+ inst = updated_data_transfer_insts[mem_flags | INDEXED];
+ FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | B(OFFS_REG(mem))));
+ }
+ else {
+ if (memw > SIMM_MAX || memw < SIMM_MIN)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ inst = updated_data_transfer_insts[mem_flags];
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if ((inst & INT_ALIGNED) && (memw & 0x3) != 0)
+ return SLJIT_ERR_UNSUPPORTED;
+#endif
+
+ if (type & SLJIT_MEM_SUPP)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst(compiler, INST_CODE_AND_DST(inst, 0, reg) | A(mem & REG_MASK) | IMM(memw)));
+ }
+
+ if ((mem_flags & LOAD_DATA) && (type & 0xff) == SLJIT_MOV_S8)
+ return push_inst(compiler, EXTSB | S(reg) | A(reg));
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem_update(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 freg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_s32 mem_flags;
+ sljit_ins inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fmem_update(compiler, type, freg, mem, memw));
+
+ if (type & SLJIT_MEM_POST)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
+ if (memw != 0)
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+ else {
+ if (memw > SIMM_MAX || memw < SIMM_MIN)
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+
+ if (type & SLJIT_MEM_SUPP)
+ return SLJIT_SUCCESS;
+
+ mem_flags = FLOAT_DATA(type);
+
+ if (!(type & SLJIT_MEM_STORE))
+ mem_flags |= LOAD_DATA;
+
+ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
+ inst = updated_data_transfer_insts[mem_flags | INDEXED];
+ return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | B(OFFS_REG(mem)));
+ }
+
+ inst = updated_data_transfer_insts[mem_flags];
+ return push_inst(compiler, INST_CODE_AND_DST(inst, DOUBLE_DATA, freg) | A(mem & REG_MASK) | IMM(memw));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 mem_reg)
+{
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));
+
+ if (op & SLJIT_ATOMIC_USE_CAS)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ ins = LDARX;
+ break;
+#endif /* SLJIT_CONFIG_PPC_64 */
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV32:
+ ins = LWARX;
+ break;
+
+ default:
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, ins | D(dst_reg) | B(mem_reg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src_reg,
+ sljit_s32 mem_reg,
+ sljit_s32 temp_reg)
+{
+ sljit_ins ins;
+
+ /* temp_reg == mem_reg is undefined so use another temp register */
+ SLJIT_UNUSED_ARG(temp_reg);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));
+
+ if (op & SLJIT_ATOMIC_USE_CAS)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ ins = STDCX | 0x1;
+ break;
+#endif /* SLJIT_CONFIG_PPC_64 */
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV32:
+ ins = STWCX | 0x1;
+ break;
+
+ default:
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, ins | D(src_reg) | B(mem_reg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
+{
+ struct sljit_const *const_;
+ sljit_s32 dst_r;
+ sljit_s32 mem_flags = WORD_DATA;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+ PTR_FAIL_IF(!const_);
+ set_const(const_, compiler);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ if (init_value & 0x100)
+ init_value |= 0xff00;
+ else
+ init_value &= 0xff;
+
+ PTR_FAIL_IF(push_inst(compiler, ADDI | D(dst_r) | A(0) | IMM(init_value)));
+ mem_flags = BYTE_DATA;
+ break;
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ case SLJIT_MOV32:
+ mem_flags = INT_DATA;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_S32:
+ PTR_FAIL_IF(push_inst(compiler, ADDIS | D(dst_r) | A(0) | IMM(init_value >> 16)));
+ PTR_FAIL_IF(push_inst(compiler, ORI | S(dst_r) | A(dst_r) | IMM(init_value)));
+ break;
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ default:
+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, dst, dstw, TMP_REG1));
+
+ return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_jump *jump;
+ sljit_s32 dst_r, target_r;
+ SLJIT_UNUSED_ARG(op);
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = TMP_REG1;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, dst, dstw, TMP_REG1));
+ }
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_mov_addr(jump, compiler, 0);
+
+ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)target_r));
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ compiler->size++;
+#else
+ compiler->size += 4;
+#endif
+
+ if (op == SLJIT_ADD_ABS_ADDR)
+ PTR_FAIL_IF(push_inst(compiler, ADD | D(dst_r) | A(dst_r) | B(TMP_REG1)));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_r, dst, dstw, TMP_REG1));
+
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
+{
+ sljit_ins *inst;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDI);
+
+ if (new_constant & 0x100)
+ new_constant |= 0xff00;
+ else
+ new_constant &= 0xff;
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_constant);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
+ return;
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_constant >> 16);
+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_constant);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ return;
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ default:
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ return;
+ }
+}
diff --git a/deps/sljit/sljit_src/sljitNativeRISCV_32.c b/deps/sljit/sljit_src/sljitNativeRISCV_32.c
new file mode 100644
index 0000000..e2dfb01
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativeRISCV_32.c
@@ -0,0 +1,154 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r)
+{
+ SLJIT_UNUSED_ARG(tmp_r);
+
+ if (RISCV_HAS_COMPRESSED(200) && imm <= SIMM16_MAX && imm >= SIMM16_MIN)
+ return push_inst16(compiler, C_LI | C_RD(dst_r) | C_IMM_I(imm));
+
+ if (imm <= SIMM_MAX && imm >= SIMM_MIN)
+ return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm));
+
+ if (imm & 0x800)
+ imm += 0x1000;
+
+ if (RISCV_HAS_COMPRESSED(200) && imm <= 0x1ffff && imm >= -0x20000)
+ FAIL_IF(push_inst16(compiler, C_LUI | C_RD(dst_r) | ((sljit_u16)(((imm) & 0x1f000) >> 10) | ((imm) & 0x20000) >> 5)));
+ else
+ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~(sljit_sw)0xfff)));
+
+ imm &= 0xfff;
+
+ if (imm == 0)
+ return SLJIT_SUCCESS;
+
+ if (RISCV_HAS_COMPRESSED(200) && (imm <= 0x1f || imm >= 0xfe0))
+ return push_inst16(compiler, C_ADDI | C_RD(dst_r) | C_IMM_I(imm));
+
+ return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value)
+{
+ union {
+ sljit_s32 imm[2];
+ sljit_f64 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset64(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm[0] != 0)
+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0], TMP_REG3));
+ if (u.imm[1] != 0)
+ FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1], TMP_REG3));
+
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-16)));
+ FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(u.imm[0] != 0 ? TMP_REG1 : TMP_ZERO) | (8 << 7)));
+ FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(u.imm[1] != 0 ? TMP_REG2 : TMP_ZERO) | (12 << 7)));
+ FAIL_IF(push_inst(compiler, FLD | FRD(freg) | RS1(SLJIT_SP) | IMM_I(8)));
+ return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(16));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg)
+{
+ sljit_ins inst;
+ sljit_s32 reg2 = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
+
+ if (op & SLJIT_32) {
+ if (op == SLJIT_COPY32_TO_F32)
+ inst = FMV_W_X | RS1(reg) | FRD(freg);
+ else
+ inst = FMV_X_W | FRS1(freg) | RD(reg);
+
+ return push_inst(compiler, inst);
+ }
+
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-16)));
+
+ if (reg & REG_PAIR_MASK) {
+ reg2 = REG_PAIR_SECOND(reg);
+ reg = REG_PAIR_FIRST(reg);
+ }
+
+ if (op == SLJIT_COPY_TO_F64) {
+ if (reg2 != 0)
+ FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(reg2) | (8 << 7)));
+ else
+ FAIL_IF(push_inst(compiler, FSW | RS1(SLJIT_SP) | FRS2(freg) | (8 << 7)));
+
+ FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(reg) | (12 << 7)));
+ FAIL_IF(push_inst(compiler, FLD | FRD(freg) | RS1(SLJIT_SP) | IMM_I(8)));
+ } else {
+ FAIL_IF(push_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(freg) | (8 << 7)));
+
+ if (reg2 != 0)
+ FAIL_IF(push_inst(compiler, FMV_X_W | FRS1(freg) | RD(reg2)));
+
+ FAIL_IF(push_inst(compiler, LW | RD(reg) | RS1(SLJIT_SP) | IMM_I(12)));
+ }
+
+ return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(16));
+}
+
+static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins)
+{
+ if ((init_value & 0x800) != 0)
+ init_value += 0x1000;
+
+ FAIL_IF(push_inst(compiler, LUI | RD(dst) | (sljit_ins)(init_value & ~0xfff)));
+ return push_inst(compiler, last_ins | RS1(dst) | IMM_I(init_value));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
+{
+ sljit_u16 *inst = (sljit_u16*)addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ if ((new_target & 0x800) != 0)
+ new_target += 0x1000;
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);
+
+ SLJIT_ASSERT((inst[0] & 0x7f) == LUI);
+ inst[0] = (sljit_u16)((inst[0] & 0xfff) | (new_target & 0xf000));
+ inst[1] = (sljit_u16)(new_target >> 16);
+ SLJIT_ASSERT((inst[2] & 0x707f) == ADDI || (inst[2] & 0x707f) == JALR);
+ inst[3] = (sljit_u16)((inst[3] & 0xf) | (new_target << 4));
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);
+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 4);
+}
diff --git a/deps/sljit/sljit_src/sljitNativeRISCV_64.c b/deps/sljit/sljit_src/sljitNativeRISCV_64.c
new file mode 100644
index 0000000..0b8ccab
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativeRISCV_64.c
@@ -0,0 +1,296 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+static sljit_s32 load_immediate32(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm)
+{
+ SLJIT_ASSERT((imm <= 0x7fffffffl && imm > SIMM_MAX) || (imm >= S32_MIN && imm < SIMM_MIN));
+
+ if (imm > S32_MAX) {
+ SLJIT_ASSERT((imm & 0x800) != 0);
+ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u));
+ return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
+ }
+
+ if (RISCV_HAS_COMPRESSED(200) && imm <= 0x1ffff && imm >= -0x20000) {
+ if (imm > 0x1f7ff) {
+ SLJIT_ASSERT((imm & 0x800) != 0);
+ FAIL_IF(push_inst16(compiler, C_LUI | C_RD(dst_r) | (sljit_u16)0x1000));
+ return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
+ }
+
+ if ((imm & 0x800) != 0)
+ imm += 0x1000;
+
+ FAIL_IF(push_inst16(compiler, C_LUI | C_RD(dst_r) | ((sljit_u16)(((imm) & 0x1f000) >> 10) | ((imm) & 0x20000) >> 5)));
+ } else {
+ if ((imm & 0x800) != 0)
+ imm += 0x1000;
+
+ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~(sljit_sw)0xfff)));
+ }
+
+ imm &= 0xfff;
+
+ if (imm == 0)
+ return SLJIT_SUCCESS;
+
+ if (RISCV_HAS_COMPRESSED(200) && (imm <= 0x1f || imm >= 0xfe0))
+ return push_inst16(compiler, C_ADDI | C_RD(dst_r) | C_IMM_I(imm));
+
+ return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
+}
+
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r)
+{
+ sljit_sw high, shift;
+
+ if (RISCV_HAS_COMPRESSED(200) && imm <= SIMM16_MAX && imm >= SIMM16_MIN)
+ return push_inst16(compiler, C_LI | C_RD(dst_r) | C_IMM_I(imm));
+
+ if (imm <= SIMM_MAX && imm >= SIMM_MIN)
+ return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm));
+
+ if (imm <= 0x7fffffffl && imm >= S32_MIN)
+ return load_immediate32(compiler, dst_r, imm);
+
+ if (RISCV_HAS_BITMANIP_A(93) && (sljit_uw)imm <= 0xffffffff) {
+ FAIL_IF(load_immediate(compiler, dst_r, (sljit_s32)imm, tmp_r));
+ return push_inst(compiler, ADD_UW | RD(dst_r) | RS1(dst_r) | RS2(TMP_ZERO));
+ }
+
+ /* Shifted small immediates. */
+
+ high = imm;
+ shift = 0;
+ while ((high & 0xff) == 0) {
+ high >>= 8;
+ shift += 8;
+ }
+
+ if ((high & 0xf) == 0) {
+ high >>= 4;
+ shift += 4;
+ }
+
+ if ((high & 0x3) == 0) {
+ high >>= 2;
+ shift += 2;
+ }
+
+ if ((high & 0x1) == 0) {
+ high >>= 1;
+ shift += 1;
+ }
+
+ if (high <= 0x7fffffffl && high >= S32_MIN) {
+ load_immediate(compiler, dst_r, high, tmp_r);
+
+ if (RISCV_HAS_COMPRESSED(200))
+ return push_inst16(compiler, C_SLLI | C_RD(dst_r) | C_IMM_I(shift));
+ return push_inst(compiler, SLLI | RD(dst_r) | RS1(dst_r) | IMM_I(shift));
+ }
+
+ /* Trailing zeroes could be used to produce shifted immediates. */
+
+ if (imm <= 0x7ffffffffffl && imm >= -0x80000000000l) {
+ high = imm >> 12;
+
+ if (imm & 0x800)
+ high = ~high;
+
+ FAIL_IF(load_immediate32(compiler, dst_r, high));
+
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_SLLI | C_RD(dst_r) | (sljit_u16)(12 << 2)));
+ else
+ FAIL_IF(push_inst(compiler, SLLI | RD(dst_r) | RS1(dst_r) | IMM_I(12)));
+
+ SLJIT_ASSERT((imm & 0xfff) != 0);
+ return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
+ }
+
+ SLJIT_ASSERT(dst_r != tmp_r);
+
+ high = imm >> 32;
+ imm = (sljit_s32)imm;
+
+ if ((imm & 0x80000000l) != 0)
+ high = ~high;
+
+ if (high <= 0x7ffff && high >= -0x80000) {
+ FAIL_IF(push_inst(compiler, LUI | RD(tmp_r) | (sljit_ins)(high << 12)));
+ high = 0x1000;
+ } else {
+ if ((high & 0x800) != 0)
+ high += 0x1000;
+
+ FAIL_IF(push_inst(compiler, LUI | RD(tmp_r) | (sljit_ins)(high & ~0xfff)));
+ high &= 0xfff;
+ }
+
+ if (imm <= SIMM_MAX && imm >= SIMM_MIN) {
+ if (RISCV_HAS_COMPRESSED(200) && imm <= 0x1f && imm >= -0x20)
+ FAIL_IF(push_inst16(compiler, C_LI | C_RD(dst_r) | C_IMM_I(imm)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm)));
+ imm = 0;
+ } else if (imm > S32_MAX) {
+ SLJIT_ASSERT((imm & 0x800) != 0);
+
+ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u));
+ imm = 0x1000 | (imm & 0xfff);
+ } else {
+ if ((imm & 0x800) != 0)
+ imm += 0x1000;
+
+ if (RISCV_HAS_COMPRESSED(200) && imm <= 0x1ffff && imm >= -0x20000)
+ FAIL_IF(push_inst16(compiler, C_LUI | C_RD(dst_r) | ((sljit_u16)(((imm) & 0x1f000) >> 10) | ((imm) & 0x20000) >> 5)));
+ else
+ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));
+ imm &= 0xfff;
+ }
+
+ if ((high & 0xfff) != 0) {
+ SLJIT_ASSERT(high <= 0xfff);
+ if (RISCV_HAS_COMPRESSED(200) && (high <= 0x1f || high >= 0xfe0))
+ FAIL_IF(push_inst16(compiler, C_ADDI | C_RD(tmp_r) | C_IMM_I(high)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(tmp_r) | RS1(tmp_r) | IMM_I(high)));
+ }
+
+ if (imm & 0x1000)
+ FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)));
+ else if (imm != 0) {
+ SLJIT_ASSERT(imm <= 0xfff);
+ if (RISCV_HAS_COMPRESSED(200) && (imm <= 0x1f || imm >= 0xfe0))
+ FAIL_IF(push_inst16(compiler, C_ADDI | C_RD(dst_r) | C_IMM_I(imm)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)));
+ }
+
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_SLLI | C_RD(tmp_r) | (sljit_u16)((high & 0x1000) ? (20 << 2) : (1 << 12))));
+ else
+ FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(tmp_r) | IMM_I((high & 0x1000) ? 20 : 32)));
+ return push_inst(compiler, XOR | RD(dst_r) | RS1(dst_r) | RS2(tmp_r));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value)
+{
+ union {
+ sljit_sw imm;
+ sljit_f64 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset64(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm == 0)
+ return push_inst(compiler, FMV_W_X | (1 << 25) | RS1(TMP_ZERO) | FRD(freg));
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm, TMP_REG3));
+ return push_inst(compiler, FMV_W_X | (1 << 25) | RS1(TMP_REG1) | FRD(freg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg)
+{
+ sljit_ins inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
+
+ if (GET_OPCODE(op) == SLJIT_COPY_TO_F64)
+ inst = FMV_W_X | RS1(reg) | FRD(freg);
+ else
+ inst = FMV_X_W | FRS1(freg) | RD(reg);
+
+ if (!(op & SLJIT_32))
+ inst |= (sljit_ins)1 << 25;
+
+ return push_inst(compiler, inst);
+}
+
+static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins)
+{
+ sljit_sw high;
+
+ if ((init_value & 0x800) != 0)
+ init_value += 0x1000;
+
+ high = init_value >> 32;
+
+ if ((init_value & 0x80000000l) != 0)
+ high = ~high;
+
+ if ((high & 0x800) != 0)
+ high += 0x1000;
+
+ FAIL_IF(push_inst(compiler, LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff)));
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high)));
+ FAIL_IF(push_inst(compiler, LUI | RD(dst) | (sljit_ins)(init_value & ~0xfff)));
+ FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(32)));
+ FAIL_IF(push_inst(compiler, XOR | RD(dst) | RS1(dst) | RS2(TMP_REG3)));
+ return push_inst(compiler, last_ins | RS1(dst) | IMM_I(init_value));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
+{
+ sljit_u16 *inst = (sljit_u16*)addr;
+ sljit_sw high;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ if ((new_target & 0x800) != 0)
+ new_target += 0x1000;
+
+ high = (sljit_sw)new_target >> 32;
+
+ if ((new_target & 0x80000000l) != 0)
+ high = ~high;
+
+ if ((high & 0x800) != 0)
+ high += 0x1000;
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 12, 0);
+
+ SLJIT_ASSERT((inst[0] & 0x7f) == LUI);
+ inst[0] = (sljit_u16)((inst[0] & 0xfff) | (high & 0xf000));
+ inst[1] = (sljit_u16)(high >> 16);
+ SLJIT_ASSERT((inst[2] & 0x707f) == ADDI);
+ inst[3] = (sljit_u16)((inst[3] & 0xf) | (high << 4));
+ SLJIT_ASSERT((inst[4] & 0x7f) == LUI);
+ inst[4] = (sljit_u16)((inst[4] & 0xfff) | (new_target & 0xf000));
+ inst[5] = (sljit_u16)(new_target >> 16);
+ SLJIT_ASSERT((inst[10] & 0x707f) == ADDI || (inst[10] & 0x707f) == JALR);
+ inst[11] = (sljit_u16)((inst[11] & 0xf) | (new_target << 4));
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 12, 1);
+
+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 12);
+}
diff --git a/deps/sljit/sljit_src/sljitNativeRISCV_common.c b/deps/sljit/sljit_src/sljitNativeRISCV_common.c
new file mode 100644
index 0000000..1089bdd
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativeRISCV_common.c
@@ -0,0 +1,4868 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if !(defined SLJIT_CONFIG_RISCV_ATOMIC) && defined(__riscv_atomic)
+/* Auto detect atomic instruction support. */
+#define SLJIT_CONFIG_RISCV_ATOMIC 200
+#endif /* !SLJIT_CONFIG_RISCV_ATOMIC && __riscv_atomic */
+
+/* SLJIT_CONFIG_RISCV_ATOMIC enables/disables atomic instruction
+ support. Non-zero values represents the highest version of the feature
+ that is supported by the CPU.
+ Allowed values: 0 - disabled, 200 - 2.00 */
+#if (defined SLJIT_CONFIG_RISCV_ATOMIC && SLJIT_CONFIG_RISCV_ATOMIC != 0)
+#if SLJIT_CONFIG_RISCV_ATOMIC != 200
+#error "Unsupported value for SLJIT_CONFIG_RISCV_ATOMIC"
+#endif
+#define RISCV_HAS_ATOMIC(x) ((SLJIT_CONFIG_RISCV_ATOMIC) >= (x))
+#define RISCV_ATOMIC_INFO "a"
+#else /* !SLJIT_CONFIG_RISCV_ATOMIC || SLJIT_CONFIG_RISCV_ATOMIC == 0 */
+#define RISCV_HAS_ATOMIC(x) 0
+#define RISCV_ATOMIC_INFO ""
+#endif /* SLJIT_CONFIG_RISCV_ATOMIC && SLJIT_CONFIG_RISCV_ATOMIC != 0 */
+
+#if !(defined SLJIT_CONFIG_RISCV_COMPRESSED) && defined(__riscv_compressed)
+/* Auto detect compressed instruction support. */
+#define SLJIT_CONFIG_RISCV_COMPRESSED 200
+#endif /* !SLJIT_CONFIG_RISCV_COMPRESSED && __riscv_compressed */
+
+/* SLJIT_CONFIG_RISCV_COMPRESSED enables/disables compressed instruction
+ support. Non-zero values represents the highest version of the feature
+ that is supported by the CPU.
+ Allowed values: 0 - disabled, 200 - 2.00 */
+#if (defined SLJIT_CONFIG_RISCV_COMPRESSED && SLJIT_CONFIG_RISCV_COMPRESSED != 0)
+#if SLJIT_CONFIG_RISCV_COMPRESSED != 200
+#error "Unsupported value for SLJIT_CONFIG_RISCV_COMPRESSED"
+#endif
+#define RISCV_HAS_COMPRESSED(x) ((SLJIT_CONFIG_RISCV_COMPRESSED) >= (x))
+#define RISCV_COMPRESSED_CHECK(x) (x)
+#define RISCV_COMPRESSED_INFO "c"
+#else /* !SLJIT_CONFIG_RISCV_COMPRESSED || SLJIT_CONFIG_RISCV_COMPRESSED == 0 */
+#define RISCV_HAS_COMPRESSED(x) 0
+#define RISCV_COMPRESSED_CHECK(x) 0
+#define RISCV_COMPRESSED_INFO ""
+#endif /* SLJIT_CONFIG_RISCV_COMPRESSED && SLJIT_CONFIG_RISCV_COMPRESSED != 0 */
+
+#if !(defined SLJIT_CONFIG_RISCV_VECTOR) && defined(__riscv_vector)
+/* Auto detect vector instruction support. */
+#define SLJIT_CONFIG_RISCV_VECTOR 100
+#endif /* !SLJIT_CONFIG_RISCV_VECTOR && __riscv_vector */
+
+/* SLJIT_CONFIG_RISCV_VECTOR enables/disables vector instruction
+ support. Non-zero values represents the highest version of the feature
+ that is supported by the CPU.
+ Allowed values: 0 - disabled, 100 - 1.00 */
+#if (defined SLJIT_CONFIG_RISCV_VECTOR && SLJIT_CONFIG_RISCV_VECTOR != 0)
+#if SLJIT_CONFIG_RISCV_VECTOR != 100
+#error "Unsupported value for SLJIT_CONFIG_RISCV_VECTOR"
+#endif
+#define RISCV_HAS_VECTOR(x) ((SLJIT_CONFIG_RISCV_VECTOR) >= (x))
+#define RISCV_VECTOR_INFO "v"
+#else /* !SLJIT_CONFIG_RISCV_VECTOR || SLJIT_CONFIG_RISCV_VECTOR == 0 */
+#define RISCV_HAS_VECTOR(x) 0
+#define RISCV_VECTOR_INFO ""
+#endif /* SLJIT_CONFIG_RISCV_VECTOR && SLJIT_CONFIG_RISCV_VECTOR != 0 */
+
+#if !(defined SLJIT_CONFIG_RISCV_BITMANIP_A) && defined(__riscv_zba)
+/* Auto detect bit manipulation extension A instruction support. */
+#define SLJIT_CONFIG_RISCV_BITMANIP_A 93
+#endif /* !SLJIT_CONFIG_RISCV_BITMANIP_A && __riscv_zba */
+
+/* SLJIT_CONFIG_RISCV_BITMANIP_A enables/disables bit manipulation extension A
+ instruction support. Non-zero values represents the highest version of the
+ feature that is supported by the CPU.
+ Allowed values: 0 - disabled, 93 - 0.93 */
+#if (defined SLJIT_CONFIG_RISCV_BITMANIP_A && SLJIT_CONFIG_RISCV_BITMANIP_A != 0)
+#if SLJIT_CONFIG_RISCV_BITMANIP_A != 93
+#error "Unsupported value for SLJIT_CONFIG_RISCV_BITMANIP_A"
+#endif
+#define RISCV_HAS_BITMANIP_A(x) ((SLJIT_CONFIG_RISCV_BITMANIP_A) >= (x))
+#define RISCV_BITMANIP_A_INFO "_zba"
+#else /* !SLJIT_CONFIG_RISCV_BITMANIP_A || SLJIT_CONFIG_RISCV_BITMANIP_A == 0 */
+#define RISCV_HAS_BITMANIP_A(x) 0
+#define RISCV_BITMANIP_A_INFO ""
+#endif /* SLJIT_CONFIG_RISCV_BITMANIP_A && SLJIT_CONFIG_RISCV_BITMANIP_A != 0 */
+
+#if !(defined SLJIT_CONFIG_RISCV_BITMANIP_B) && defined(__riscv_zbb)
+/* Auto detect bit manipulation extension B instruction support. */
+#define SLJIT_CONFIG_RISCV_BITMANIP_B 93
+#endif /* !SLJIT_CONFIG_RISCV_BITMANIP_B && __riscv_zbb */
+
+/* SLJIT_CONFIG_RISCV_BITMANIP_B enables/disables bit manipulation extension B
+ instruction support. Non-zero values represents the highest version of the
+ feature that is supported by the CPU.
+ Allowed values: 0 - disabled, 93 - 0.93 */
+#if (defined SLJIT_CONFIG_RISCV_BITMANIP_B && SLJIT_CONFIG_RISCV_BITMANIP_B != 0)
+#if SLJIT_CONFIG_RISCV_BITMANIP_B != 93
+#error "Unsupported value for SLJIT_CONFIG_RISCV_BITMANIP_B"
+#endif
+#define RISCV_HAS_BITMANIP_B(x) ((SLJIT_CONFIG_RISCV_BITMANIP_B) >= (x))
+#define RISCV_BITMANIP_B_INFO "_zbb"
+#else /* !SLJIT_CONFIG_RISCV_BITMANIP_B || SLJIT_CONFIG_RISCV_BITMANIP_B == 0 */
+#define RISCV_HAS_BITMANIP_B(x) 0
+#define RISCV_BITMANIP_B_INFO ""
+#endif /* SLJIT_CONFIG_RISCV_BITMANIP_B && SLJIT_CONFIG_RISCV_BITMANIP_B != 0 */
+
+#if !(defined SLJIT_CONFIG_RISCV_ICOND) && defined(__riscv_zicond)
+/* Auto detect integer conditional instruction support. */
+#define SLJIT_CONFIG_RISCV_ICOND 100
+#endif /* !SLJIT_CONFIG_RISCV_ICOND && __riscv_zicond */
+
+/* SLJIT_CONFIG_RISCV_ICOND enables/disables integer conditional
+ instruction support. Non-zero values represents the highest version of the
+ feature that is supported by the CPU.
+ Allowed values: 0 - disabled, 100 - 1.00 */
+#if (defined SLJIT_CONFIG_RISCV_ICOND && SLJIT_CONFIG_RISCV_ICOND != 0)
+#if SLJIT_CONFIG_RISCV_ICOND != 100
+#error "Unsupported value for SLJIT_CONFIG_RISCV_ICOND"
+#endif
+#define RISCV_HAS_ICOND(x) ((SLJIT_CONFIG_RISCV_ICOND) >= (x))
+#define RISCV_ICOND_INFO "_zicond"
+#else /* !SLJIT_CONFIG_RISCV_ICOND || SLJIT_CONFIG_RISCV_ICOND == 0 */
+#define RISCV_HAS_ICOND(x) 0
+#define RISCV_ICOND_INFO ""
+#endif /* SLJIT_CONFIG_RISCV_ICOND && SLJIT_CONFIG_RISCV_ICOND != 0 */
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+#define RISCV_CHECK_COMPRESSED_JUMP(jump, diff, unit) \
+ (!((jump)->flags & IS_CALL) && (diff) >= (JUMP16_MIN / SSIZE_OF(unit)) && (diff) <= (JUMP16_MAX / SSIZE_OF(unit)))
+#else /* !SLJIT_CONFIG_RISCV_64 */
+#define RISCV_CHECK_COMPRESSED_JUMP(jump, diff, unit) \
+ ((diff) >= (JUMP16_MIN / SSIZE_OF(unit)) && (diff) <= (JUMP16_MAX / SSIZE_OF(unit)))
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
+{
+ /* The arch string is not entirely correct since 'g' contains 'a'. */
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ return "RISCV (rv32g" RISCV_ATOMIC_INFO RISCV_COMPRESSED_INFO RISCV_VECTOR_INFO RISCV_BITMANIP_A_INFO RISCV_BITMANIP_B_INFO RISCV_ICOND_INFO ")" SLJIT_CPUINFO;
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ return "RISCV (rv64g" RISCV_ATOMIC_INFO RISCV_COMPRESSED_INFO RISCV_VECTOR_INFO RISCV_BITMANIP_A_INFO RISCV_BITMANIP_B_INFO RISCV_ICOND_INFO ")" SLJIT_CPUINFO;
+#endif /* SLJIT_CONFIG_RISCV_32 */
+}
+
+/* Most instructions are 32 bit long on RISCV.
+ Code is processed as 16 bit units. */
+typedef sljit_u32 sljit_ins;
+
+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
+#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4)
+#define TMP_ZERO 0
+
+/* Flags are kept in volatile registers. */
+#define EQUAL_FLAG (SLJIT_NUMBER_OF_REGISTERS + 5)
+#define RETURN_ADDR_REG TMP_REG2
+#define OTHER_FLAG (SLJIT_NUMBER_OF_REGISTERS + 6)
+
+#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
+#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
+
+#define TMP_VREG1 (SLJIT_NUMBER_OF_VECTOR_REGISTERS + 1)
+#define TMP_VREG2 (SLJIT_NUMBER_OF_VECTOR_REGISTERS + 2)
+
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
+ 0, 10, 11, 12, 13, 14, 15, 16, 17, 29, 30, 31, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 9, 8, 2, 6, 1, 7, 5, 28
+};
+
+static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
+ 0, 10, 11, 12, 13, 14, 15, 16, 17, 2, 3, 4, 5, 6, 7, 28, 29, 30, 31, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 9, 8, 0, 1,
+};
+
+static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = {
+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+};
+
+/* --------------------------------------------------------------------- */
+/* Instruction forms */
+/* --------------------------------------------------------------------- */
+
+#define RD(rd) ((sljit_ins)reg_map[rd] << 7)
+#define RS1(rs1) ((sljit_ins)reg_map[rs1] << 15)
+#define RS2(rs2) ((sljit_ins)reg_map[rs2] << 20)
+#define FRD(rd) ((sljit_ins)freg_map[rd] << 7)
+#define FRS1(rs1) ((sljit_ins)freg_map[rs1] << 15)
+#define FRS2(rs2) ((sljit_ins)freg_map[rs2] << 20)
+#define VRD(rd) ((sljit_ins)vreg_map[rd] << 7)
+#define VRS1(rs1) ((sljit_ins)vreg_map[rs1] << 15)
+#define VRS2(rs2) ((sljit_ins)vreg_map[rs2] << 20)
+#define IMM_I(imm) ((sljit_ins)(imm) << 20)
+#define IMM_S(imm) ((((sljit_ins)(imm) & 0xfe0) << 20) | (((sljit_ins)(imm) & 0x1f) << 7))
+#define C_RD(rd) ((sljit_u16)((sljit_u16)reg_map[rd] << 7))
+#define C_RS2(rd) ((sljit_u16)((sljit_u16)reg_map[rd] << 2))
+#define C_FRD(rd) ((sljit_u16)((sljit_u16)freg_map[rd] << 7))
+#define C_FRS2(rd) ((sljit_u16)((sljit_u16)freg_map[rd] << 2))
+#define C_RS1_R3(rs1) ((sljit_u16)((sljit_u16)(reg_map[rs1] & 0x7) << 7))
+#define C_RS2_R3(rs2) ((sljit_u16)((sljit_u16)(reg_map[rs2] & 0x7) << 2))
+#define C_FRS2_R3(rs2) ((sljit_u16)((sljit_u16)(freg_map[rs2] & 0x7) << 2))
+#define C_IS_R3(r) ((reg_map[r] & 0x18) == 0x08)
+#define C_IS_FR3(r) ((freg_map[r] & 0x18) == 0x08)
+#define C_IMM_I(imm) ((sljit_u16)((((imm) & 0x1f) << 2) | (((imm) & 0x20) << 7)))
+#define C_LD32_SP(imm) ((sljit_u16)((((imm) & 0x1c) << 2) | (((imm) & 0x20) << 7) | (((imm) & 0xc0) >> 4)))
+#define C_ST32_SP(imm) ((sljit_u16)((((imm) & 0x3c) << 7) | (((imm) & 0xc0) << 1)))
+#define C_LD64_SP(imm) ((sljit_u16)((((imm) & 0x18) << 2) | (((imm) & 0x20) << 7) | (((imm) & 0x1c0) >> 4)))
+#define C_ST64_SP(imm) ((sljit_u16)((((imm) & 0x38) << 7) | (((imm) & 0x1c0) << 1)))
+#define C_MEM32(imm) ((sljit_u16)((((imm) & 0x4) << 4) | (((imm) & 0x38) << 7) | (((imm) & 0x40) >> 1)))
+#define C_MEM64(imm) ((sljit_u16)((((imm) & 0x38) << 7) | (((imm) & 0xc0) >> 1)))
+#define C_BRN16(imm) ((sljit_u16)((((imm) & 0x6) << 2) | (((imm) & 0x18) << 7) | (((imm) & 0x20) >> 3) | (((imm) & 0xc0) >> 1) | (((imm) & 0x100) << 4)))
+#define C_JMP16(imm) ((sljit_u16)((((imm) & 0xb40) << 1) | (((imm) & 0xe) << 2) | (((imm) & 0x10) << 7) | (((imm) & 0x20) >> 3) | (((imm) & 0x80) >> 1) | (((imm) & 0x400) >> 2)))
+
+/* Represents funct(i) parts of the instructions. */
+#define OPC(o) ((sljit_ins)(o))
+#define C_OPC(o1, o2) ((sljit_u16)((o1) | ((o2) << 13)))
+#define F3(f) ((sljit_ins)(f) << 12)
+#define F12(f) ((sljit_ins)(f) << 20)
+#define F7(f) ((sljit_ins)(f) << 25)
+
+/* Vector instruction types. */
+#define OPFVF (F3(0x5) | OPC(0x57))
+#define OPFVV (F3(0x1) | OPC(0x57))
+#define OPIVI (F3(0x3) | OPC(0x57))
+#define OPIVV (F3(0x0) | OPC(0x57))
+#define OPIVX (F3(0x4) | OPC(0x57))
+#define OPMVV (F3(0x2) | OPC(0x57))
+#define OPMVX (F3(0x6) | OPC(0x57))
+
+#define ADD (F7(0x0) | F3(0x0) | OPC(0x33))
+#define ADDI (F3(0x0) | OPC(0x13))
+#define ADD_UW (F7(0x4) | F3(0x0) | OPC(0x3b))
+#define AND (F7(0x0) | F3(0x7) | OPC(0x33))
+#define ANDI (F3(0x7) | OPC(0x13))
+#define AUIPC (OPC(0x17))
+#define BEQ (F3(0x0) | OPC(0x63))
+#define BNE (F3(0x1) | OPC(0x63))
+#define BLT (F3(0x4) | OPC(0x63))
+#define BGE (F3(0x5) | OPC(0x63))
+#define BLTU (F3(0x6) | OPC(0x63))
+#define BGEU (F3(0x7) | OPC(0x63))
+/* C_*: compressed */
+#define C_ADD (C_OPC(0x2, 0x4) | (sljit_u16)(1 << 12))
+#define C_ADDI (C_OPC(0x1, 0x0))
+#define C_ADDIW (C_OPC(0x1, 0x1))
+#define C_ADDW (C_OPC(0x1, 0x4) | (sljit_u16)(7 << 10) | (sljit_u16)(1 << 5))
+#define C_ADDI16SP (C_OPC(0x1, 0x3) | (sljit_u16)(2 << 7))
+#define C_AND (C_OPC(0x1, 0x4) | (sljit_u16)(3 << 10) | (sljit_u16)(3 << 5))
+#define C_ANDI (C_OPC(0x1, 0x4) | (sljit_u16)(2 << 10))
+#define C_BEQZ (C_OPC(0x1, 0x6))
+#define C_BNEZ (C_OPC(0x1, 0x7))
+#define C_EBREAK (C_OPC(0x2, 0x4) | (sljit_u16)(1 << 12))
+#define C_FLDSP (C_OPC(0x2, 0x1))
+#define C_FLWSP (C_OPC(0x2, 0x3))
+#define C_FSD (C_OPC(0x0, 0x5))
+#define C_FSDSP (C_OPC(0x2, 0x5))
+#define C_FSW (C_OPC(0x0, 0x7))
+#define C_FSWSP (C_OPC(0x2, 0x7))
+#define C_J (C_OPC(0x1, 0x5))
+#define C_JR (C_OPC(0x2, 0x4))
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+#define C_JAL (C_OPC(0x1, 0x1))
+#endif
+#define C_JALR (C_OPC(0x2, 0x4) | (sljit_u16)(1 << 12))
+#define C_LI (C_OPC(0x1, 0x2))
+#define C_LUI (C_OPC(0x1, 0x3))
+#define C_LDSP (C_OPC(0x2, 0x3))
+#define C_LWSP (C_OPC(0x2, 0x2))
+#define C_MV (C_OPC(0x2, 0x4))
+#define C_NOP (C_OPC(0x1, 0x0))
+#define C_SD (C_OPC(0x0, 0x7))
+#define C_SDSP (C_OPC(0x2, 0x7))
+#define C_SLLI (C_OPC(0x2, 0x0))
+#define C_OR (C_OPC(0x1, 0x4) | (sljit_u16)(3 << 10) | (sljit_u16)(2 << 5))
+#define C_SRAI (C_OPC(0x1, 0x4) | (sljit_u16)(1 << 10))
+#define C_SRLI (C_OPC(0x1, 0x4) | (sljit_u16)(0 << 10))
+#define C_SUB (C_OPC(0x1, 0x4) | (sljit_u16)(3 << 10) | (sljit_u16)(0 << 5))
+#define C_SW (C_OPC(0x0, 0x6))
+#define C_SWSP (C_OPC(0x2, 0x6))
+#define C_XOR (C_OPC(0x1, 0x4) | (sljit_u16)(3 << 10) | (sljit_u16)(1 << 5))
+/* CLZ / CTZ: zbb */
+#define CLZ (F7(0x30) | F3(0x1) | OPC(0x13))
+#define CTZ (F7(0x30) | F12(0x1) | F3(0x1) | OPC(0x13))
+#define CZERO_EQZ (F7(0x7) | F3(0x5) | OPC(0x33))
+#define CZERO_NEZ (F7(0x7) | F3(0x7) | OPC(0x33))
+#define DIV (F7(0x1) | F3(0x4) | OPC(0x33))
+#define DIVU (F7(0x1) | F3(0x5) | OPC(0x33))
+#define EBREAK (F12(0x1) | F3(0x0) | OPC(0x73))
+#define FADD_S (F7(0x0) | F3(0x7) | OPC(0x53))
+#define FDIV_S (F7(0xc) | F3(0x7) | OPC(0x53))
+#define FENCE (F3(0x0) | OPC(0xf))
+#define FEQ_S (F7(0x50) | F3(0x2) | OPC(0x53))
+#define FLD (F3(0x3) | OPC(0x7))
+#define FLE_S (F7(0x50) | F3(0x0) | OPC(0x53))
+#define FLT_S (F7(0x50) | F3(0x1) | OPC(0x53))
+/* These conversion opcodes are partly defined. */
+#define FCVT_S_D (F7(0x20) | OPC(0x53))
+#define FCVT_S_W (F7(0x68) | OPC(0x53))
+#define FCVT_S_WU (F7(0x68) | F12(0x1) | OPC(0x53))
+#define FCVT_W_S (F7(0x60) | F3(0x1) | OPC(0x53))
+#define FMUL_S (F7(0x8) | F3(0x7) | OPC(0x53))
+#define FMV_X_W (F7(0x70) | F3(0x0) | OPC(0x53))
+#define FMV_W_X (F7(0x78) | F3(0x0) | OPC(0x53))
+#define FSD (F3(0x3) | OPC(0x27))
+#define FSGNJ_S (F7(0x10) | F3(0x0) | OPC(0x53))
+#define FSGNJN_S (F7(0x10) | F3(0x1) | OPC(0x53))
+#define FSGNJX_S (F7(0x10) | F3(0x2) | OPC(0x53))
+#define FSUB_S (F7(0x4) | F3(0x7) | OPC(0x53))
+#define FSW (F3(0x2) | OPC(0x27))
+#define JAL (OPC(0x6f))
+#define JALR (F3(0x0) | OPC(0x67))
+#define LD (F3(0x3) | OPC(0x3))
+#define LUI (OPC(0x37))
+#define LW (F3(0x2) | OPC(0x3))
+/* LR: atomic */
+#define LR (F7(0x8) | OPC(0x2f))
+#define MAX (F7(0x5) | F3(0x6) | OPC(0x33))
+#define MAXU (F7(0x5) | F3(0x7) | OPC(0x33))
+#define MIN (F7(0x5) | F3(0x4) | OPC(0x33))
+#define MINU (F7(0x5) | F3(0x5) | OPC(0x33))
+#define MUL (F7(0x1) | F3(0x0) | OPC(0x33))
+#define MULH (F7(0x1) | F3(0x1) | OPC(0x33))
+#define MULHU (F7(0x1) | F3(0x3) | OPC(0x33))
+#define NOP ADDI
+#define OR (F7(0x0) | F3(0x6) | OPC(0x33))
+#define ORI (F3(0x6) | OPC(0x13))
+#define REM (F7(0x1) | F3(0x6) | OPC(0x33))
+#define REMU (F7(0x1) | F3(0x7) | OPC(0x33))
+/* REV8 / ROL / ROR / RORI: zbb */
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+#define REV8 (F12(0x698) | F3(0x5) | OPC(0x13))
+#elif (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+#define REV8 (F12(0x6b8) | F3(0x5) | OPC(0x13))
+#endif /* SLJIT_CONFIG_RISCV_32 */
+#define ROL (F7(0x30) | F3(0x1) | OPC(0x33))
+#define ROR (F7(0x30) | F3(0x5) | OPC(0x33))
+#define RORI (F7(0x30) | F3(0x5) | OPC(0x13))
+/* SC: atomic */
+#define SC (F7(0xc) | OPC(0x2f))
+#define SD (F3(0x3) | OPC(0x23))
+/* SEXTB / SEXTH: zbb */
+#define SEXTB (F7(0x30) | F12(0x4) | F3(0x1) | OPC(0x13))
+#define SEXTH (F7(0x30) | F12(0x5) | F3(0x1) | OPC(0x13))
+/* SH1ADD / SH2ADD / SH3ADD: zba */
+#define SH1ADD (F7(0x10) | F3(0x2) | OPC(0x33))
+#define SH2ADD (F7(0x10) | F3(0x4) | OPC(0x33))
+#define SH3ADD (F7(0x10) | F3(0x6) | OPC(0x33))
+#define SLL (F7(0x0) | F3(0x1) | OPC(0x33))
+#define SLLI (F3(0x1) | OPC(0x13))
+#define SLT (F7(0x0) | F3(0x2) | OPC(0x33))
+#define SLTI (F3(0x2) | OPC(0x13))
+#define SLTU (F7(0x0) | F3(0x3) | OPC(0x33))
+#define SLTUI (F3(0x3) | OPC(0x13))
+#define SRL (F7(0x0) | F3(0x5) | OPC(0x33))
+#define SRLI (F3(0x5) | OPC(0x13))
+#define SRA (F7(0x20) | F3(0x5) | OPC(0x33))
+#define SRAI (F7(0x20) | F3(0x5) | OPC(0x13))
+#define SUB (F7(0x20) | F3(0x0) | OPC(0x33))
+#define SW (F3(0x2) | OPC(0x23))
+/* V*: vector */
+#define VAND_VV (F7(0x13) | OPIVV)
+#define VFMV_FS (F7(0x21) | OPFVV)
+#define VFMV_SF (F7(0x21) | OPFVF)
+#define VFMV_VF (F7(0x2f) | OPFVF)
+#define VFWCVT_FFV (F7(0x25) | (0xc << 15) | OPFVV)
+#define VL (F7(0x1) | OPC(0x7))
+#define VMSLE_VI (F7(0x3b) | OPIVI)
+#define VMV_SX (F7(0x21) | OPMVX)
+#define VMV_VI (F7(0x2f) | OPIVI)
+#define VMV_VV (F7(0x2f) | OPIVV)
+#define VMV_VX (F7(0x2f) | OPIVX)
+#define VMV_XS (F7(0x21) | OPMVV)
+#define VOR_VV (F7(0x15) | OPIVV)
+#define VSETVLI (F7(0x0) | F3(0x7) | OPC(0x57))
+#define VSETIVLI (F7(0x60) | F3(0x7) | OPC(0x57))
+#define VS (F7(0x1) | OPC(0x27))
+#define VSLIDEDOWN_VX (F7(0x1f) | OPIVX)
+#define VSLIDEDOWN_VI (F7(0x1f) | OPIVI)
+#define VSLIDEUP_VX (F7(0x1d) | OPIVX)
+#define VSLIDEUP_VI (F7(0x1d) | OPIVI)
+#define VRGATHER_VI (F7(0x19) | OPIVI)
+#define VRGATHER_VV (F7(0x19) | OPIVV)
+#define VXOR_VV (F7(0x17) | OPIVV)
+#define VZEXT_VF2 (F7(0x25) | (0x6 << 15) | OPMVV)
+#define VZEXT_VF4 (F7(0x25) | (0x4 << 15) | OPMVV)
+#define VZEXT_VF8 (F7(0x25) | (0x2 << 15) | OPMVV)
+#define XOR (F7(0x0) | F3(0x4) | OPC(0x33))
+#define XORI (F3(0x4) | OPC(0x13))
+/* ZEXTH: zbb */
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+#define ZEXTH (F7(0x4) | F3(0x4) | OPC(0x33))
+#else /* SLJIT_CONFIG_RISCV_64 */
+#define ZEXTH (F7(0x4) | F3(0x4) | OPC(0x3B))
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+#define SIMM_MAX (0x7ff)
+#define SIMM_MIN (-0x800)
+#define SIMM16_MAX (0x1f)
+#define SIMM16_MIN (-0x20)
+#define BRANCH_MAX (0xfff)
+#define BRANCH_MIN (-0x1000)
+#define BRANCH16_MAX (0xff)
+#define BRANCH16_MIN (-0x100)
+#define JUMP_MAX (0xfffff)
+#define JUMP_MIN (-0x100000)
+#define JUMP16_MAX SIMM_MAX
+#define JUMP16_MIN SIMM_MIN
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+#define S32_MAX (0x7ffff7ffl)
+#define S32_MIN (-0x80000000l)
+#define S44_MAX (0x7fffffff7ffl)
+#define S52_MAX (0x7ffffffffffffl)
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+#define C_ADDI_W(word) (C_ADDI | (sljit_u16)((word) << 10))
+#define C_SUB_W(word) (C_SUB | (sljit_u16)((word) << 9))
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+#define BRANCH_LENGTH ((sljit_ins)(3 * sizeof(sljit_ins)) << 7)
+#define BRANCH16_LENGTH C_BRN16(5 * sizeof(sljit_u16))
+#else /* !SLJIT_CONFIG_RISCV_32 */
+#define BRANCH_LENGTH ((sljit_ins)(7 * sizeof(sljit_ins)) << 7)
+#define BRANCH16_LENGTH C_BRN16(13 * sizeof(sljit_u16))
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
+{
+ sljit_u16 *ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ ptr[0] = (sljit_u16)ins;
+ ptr[1] = (sljit_u16)(ins >> 16);
+ compiler->size += 2;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 push_inst16(struct sljit_compiler *compiler, sljit_u16 ins)
+{
+ sljit_u16 *ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_u16));
+ FAIL_IF(!ptr);
+ *ptr = ins;
+ compiler->size++;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 push_imm_s_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_sw imm)
+{
+ return push_inst(compiler, ins | IMM_S(imm));
+}
+
+static SLJIT_INLINE sljit_u16* detect_jump_type(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset)
+{
+ sljit_sw diff, cond_diff;
+ sljit_uw target_addr;
+ sljit_uw jump_addr = (sljit_uw)code_ptr;
+ sljit_uw orig_addr = jump->addr;
+ sljit_ins ins;
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ sljit_s32 jalr_offset = JUMP_MAX_SIZE - 1;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ jump->addr = jump_addr;
+ if (jump->flags & SLJIT_REWRITABLE_JUMP)
+ goto exit;
+
+ if (jump->flags & JUMP_ADDR)
+ target_addr = jump->u.target;
+ else {
+ SLJIT_ASSERT(jump->u.label != NULL);
+ target_addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
+
+ if (jump->u.label->size > orig_addr)
+ jump_addr = (sljit_uw)(code + orig_addr);
+ }
+
+ diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);
+
+ if (jump->flags & IS_COND) {
+ cond_diff = diff + SSIZE_OF(ins);
+
+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16))) {
+ SLJIT_ASSERT((code_ptr[-1] & 0xe003) == C_BEQZ || (code_ptr[-1] & 0xe003) == C_BNEZ);
+
+ cond_diff = diff + SSIZE_OF(u16);
+
+ if (diff >= BRANCH16_MIN && diff <= BRANCH16_MAX) {
+ code_ptr--;
+ code_ptr[0] = (sljit_u16)((code_ptr[0] & 0xe383) ^ 0x2000);
+ jump->flags |= PATCH_B | PATCH_16;
+ jump->addr = (sljit_uw)code_ptr;
+ return code_ptr;
+ }
+ }
+
+ if (cond_diff >= BRANCH_MIN && cond_diff <= BRANCH_MAX) {
+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16))) {
+ /* Converting 16 bit branch to 32 bit branch. */
+ code_ptr--;
+ code_ptr[1] = (sljit_u16)(((code_ptr[0] & 0x300) >> 8) | 0x4);
+ code_ptr[0] = (sljit_u16)((BNE ^ ((code_ptr[0] & 0x2000) >> 1)) | ((code_ptr[0] & 0x80) << 8));
+ } else {
+ code_ptr -= 2;
+ code_ptr[0] = (sljit_u16)((code_ptr[0] & 0xf07f) ^ 0x1000);
+ code_ptr[1] = (sljit_u16)(code_ptr[1] & 0x1ff);
+ }
+
+ jump->flags |= PATCH_B;
+ jump->addr = (sljit_uw)code_ptr;
+ return code_ptr + 1;
+ }
+ }
+
+ if (RISCV_HAS_COMPRESSED(200) && RISCV_CHECK_COMPRESSED_JUMP(jump, diff, u8)) {
+ /* A conditional instruction has larger max offset
+ than a 16 bit jump instruction. */
+ SLJIT_ASSERT(!(jump->flags & IS_COND));
+ jump->flags |= PATCH_J | PATCH_16;
+ return code_ptr;
+ }
+
+ if (diff >= JUMP_MIN && diff <= JUMP_MAX) {
+ if (jump->flags & IS_COND) {
+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))
+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(3 * sizeof(sljit_u16)));
+ else
+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (2 * sizeof(sljit_ins) << 7));
+ }
+
+ jump->flags |= PATCH_J;
+ return code_ptr + 1;
+ }
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ if (diff >= S32_MIN && diff <= S32_MAX) {
+ if (jump->flags & IS_COND) {
+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))
+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(5 * sizeof(sljit_u16)));
+ else
+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (3 * sizeof(sljit_ins) << 7));
+ }
+
+ jump->flags |= PATCH_REL32;
+ jalr_offset = 3;
+ } else if (target_addr <= (sljit_uw)S32_MAX) {
+ if (jump->flags & IS_COND) {
+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))
+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(5 * sizeof(sljit_u16)));
+ else
+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (3 * sizeof(sljit_ins) << 7));
+ }
+
+ jump->flags |= PATCH_ABS32;
+ jalr_offset = 3;
+ } else if (target_addr <= S44_MAX) {
+ if (jump->flags & IS_COND) {
+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))
+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(9 * sizeof(sljit_u16)));
+ else
+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (5 * sizeof(sljit_ins) << 7));
+ }
+
+ jump->flags |= PATCH_ABS44;
+ jalr_offset = 7;
+ } else if (target_addr <= S52_MAX) {
+ if (jump->flags & IS_COND) {
+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))
+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(11 * sizeof(sljit_u16)));
+ else
+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (6 * sizeof(sljit_ins) << 7));
+ }
+
+ jump->flags |= PATCH_ABS52;
+ jalr_offset = 9;
+ }
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+exit:
+ ins = JALR | RS1(TMP_REG1) | IMM_I(0);
+ if (jump->flags & IS_CALL)
+ ins |= RD(RETURN_ADDR_REG);
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ code_ptr[2] = (sljit_u16)ins;
+ code_ptr[3] = (sljit_u16)(ins >> 16);
+ return code_ptr + 3;
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ code_ptr += jalr_offset;
+ code_ptr[-1] = (sljit_u16)ins;
+ code_ptr[0] = (sljit_u16)(ins >> 16);
+ return code_ptr;
+#endif /* SLJIT_CONFIG_RISCV_32 */
+}
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+
+static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset)
+{
+ sljit_uw addr;
+ sljit_uw jump_addr = (sljit_uw)code_ptr;
+ sljit_sw diff;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_ASSERT(jump->flags < (JUMP_MAX_SIZE << JUMP_SIZE_SHIFT));
+ if (jump->flags & JUMP_ADDR)
+ addr = jump->u.target;
+ else {
+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code + jump->u.label->size, executable_offset);
+
+ if (jump->u.label->size > jump->addr)
+ jump_addr = (sljit_uw)(code + jump->addr);
+ }
+
+ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);
+
+ if (diff >= S32_MIN && diff <= S32_MAX) {
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));
+ jump->flags |= PATCH_REL32;
+ return 3;
+ }
+
+ if (addr <= S32_MAX) {
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));
+ jump->flags |= PATCH_ABS32;
+ return 3;
+ }
+
+ if (addr <= S44_MAX) {
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)7 << JUMP_SIZE_SHIFT));
+ jump->flags |= PATCH_ABS44;
+ return 7;
+ }
+
+ if (addr <= S52_MAX) {
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)9 << JUMP_SIZE_SHIFT));
+ jump->flags |= PATCH_ABS52;
+ return 9;
+ }
+
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)11 << JUMP_SIZE_SHIFT));
+ return 11;
+}
+
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw executable_offset)
+{
+ sljit_uw flags = jump->flags;
+ sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
+ sljit_ins ins;
+ sljit_u16 *buf = (sljit_u16 *)jump->addr;
+ sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *buf : TMP_REG1;
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ sljit_sw high;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ SLJIT_UNUSED_ARG(executable_offset);
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ if (flags & PATCH_REL32) {
+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf, executable_offset);
+
+ SLJIT_ASSERT((sljit_sw)addr >= S32_MIN && (sljit_sw)addr <= S32_MAX);
+
+ if ((addr & 0x800) != 0)
+ addr += 0x1000;
+
+ ins = AUIPC | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
+ buf[0] = (sljit_u16)ins;
+ buf[1] = (sljit_u16)(ins >> 16);
+
+ if (!(flags & JUMP_MOV_ADDR)) {
+ ins = JALR | RS1(reg) | IMM_I(addr);
+ if (jump->flags & IS_CALL)
+ ins |= RD(RETURN_ADDR_REG);
+ } else
+ ins = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);
+
+ buf[2] = (sljit_u16)ins;
+ buf[3] = (sljit_u16)(ins >> 16);
+ return;
+ }
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ if ((addr & 0x800) != 0)
+ addr += 0x1000;
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ ins = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
+ buf[0] = (sljit_u16)ins;
+ buf[1] = (sljit_u16)(ins >> 16);
+#else /* !SLJIT_CONFIG_RISCV_32 */
+
+ if (flags & PATCH_ABS32) {
+ SLJIT_ASSERT(addr <= S32_MAX);
+ ins = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
+ buf[0] = (sljit_u16)ins;
+ buf[1] = (sljit_u16)(ins >> 16);
+ } else if (flags & PATCH_ABS44) {
+ high = (sljit_sw)addr >> 12;
+ SLJIT_ASSERT((sljit_uw)high <= 0x7fffffff);
+
+ if (high > S32_MAX) {
+ SLJIT_ASSERT((high & 0x800) != 0);
+ ins = LUI | RD(reg) | (sljit_ins)0x80000000u;
+ buf[0] = (sljit_u16)ins;
+ buf[1] = (sljit_u16)(ins >> 16);
+ ins = XORI | RD(reg) | RS1(reg) | IMM_I(high);
+ buf[2] = (sljit_u16)ins;
+ buf[3] = (sljit_u16)(ins >> 16);
+ } else {
+ if ((high & 0x800) != 0)
+ high += 0x1000;
+
+ ins = LUI | RD(reg) | (sljit_ins)(high & ~0xfff);
+ buf[0] = (sljit_u16)ins;
+ buf[1] = (sljit_u16)(ins >> 16);
+ ins = ADDI | RD(reg) | RS1(reg) | IMM_I(high);
+ buf[2] = (sljit_u16)ins;
+ buf[3] = (sljit_u16)(ins >> 16);
+ }
+
+ ins = SLLI | RD(reg) | RS1(reg) | IMM_I(12);
+ buf[4] = (sljit_u16)ins;
+ buf[5] = (sljit_u16)(ins >> 16);
+ buf += 4;
+ } else {
+ high = (sljit_sw)addr >> 32;
+
+ if ((addr & 0x80000000l) != 0)
+ high = ~high;
+
+ if (flags & PATCH_ABS52) {
+ SLJIT_ASSERT(addr <= S52_MAX);
+ ins = LUI | RD(TMP_REG3) | (sljit_ins)(high << 12);
+ buf[0] = (sljit_u16)ins;
+ buf[1] = (sljit_u16)(ins >> 16);
+ } else {
+ if ((high & 0x800) != 0)
+ high += 0x1000;
+ ins = LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff);
+ buf[0] = (sljit_u16)ins;
+ buf[1] = (sljit_u16)(ins >> 16);
+ ins = ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high);
+ buf[2] = (sljit_u16)ins;
+ buf[3] = (sljit_u16)(ins >> 16);
+ buf += 2;
+ }
+
+ ins = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
+ buf[2] = (sljit_u16)ins;
+ buf[3] = (sljit_u16)(ins >> 16);
+ ins = SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I((flags & PATCH_ABS52) ? 20 : 32);
+ buf[4] = (sljit_u16)ins;
+ buf[5] = (sljit_u16)(ins >> 16);
+ ins = XOR | RD(reg) | RS1(reg) | RS2(TMP_REG3);
+ buf[6] = (sljit_u16)ins;
+ buf[7] = (sljit_u16)(ins >> 16);
+ buf += 6;
+ }
+#endif /* !SLJIT_CONFIG_RISCV_32 */
+
+ if (!(flags & JUMP_MOV_ADDR)) {
+ ins = JALR | RS1(reg) | IMM_I(addr);
+ if (jump->flags & IS_CALL)
+ ins |= RD(RETURN_ADDR_REG);
+ } else
+ ins = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);
+
+ buf[2] = (sljit_u16)ins;
+ buf[3] = (sljit_u16)(ins >> 16);
+}
+
+static SLJIT_INLINE sljit_u16 *process_extended_label(sljit_u16 *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_u16*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
+static void reduce_code_size(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+ SLJIT_NEXT_DEFINE_TYPES;
+ sljit_uw total_size;
+ sljit_uw size_reduce = 0;
+ sljit_sw diff, cond_size, cond_diff;
+
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ SLJIT_NEXT_INIT_TYPES();
+
+ while (1) {
+ SLJIT_GET_NEXT_MIN();
+
+ if (next_min_addr == SLJIT_MAX_ADDRESS)
+ break;
+
+ if (next_min_addr == next_label_size) {
+ label->size -= size_reduce;
+
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ if (next_min_addr == next_const_addr) {
+ const_->addr -= size_reduce;
+ const_ = const_->next;
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+ continue;
+ }
+
+ if (next_min_addr != next_jump_addr)
+ continue;
+
+ jump->addr -= size_reduce;
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+ total_size = JUMP_MAX_SIZE;
+
+ if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {
+ if (jump->flags & JUMP_ADDR) {
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ if (jump->u.target <= S32_MAX)
+ total_size = 4;
+ else if (jump->u.target <= S44_MAX)
+ total_size = 8;
+ else if (jump->u.target <= S52_MAX)
+ total_size = 10;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ } else {
+ /* Unit size: instruction. */
+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
+ if (jump->u.label->size > jump->addr) {
+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);
+ diff -= (sljit_sw)size_reduce;
+ }
+
+ cond_size = RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16) != 0);
+ cond_diff = diff + 2 - cond_size;
+
+ if (RISCV_COMPRESSED_CHECK(cond_size) && diff >= (BRANCH16_MIN / SSIZE_OF(u16)) && diff <= (BRANCH16_MAX / SSIZE_OF(u16)))
+ total_size = 0;
+ else if ((jump->flags & IS_COND) && cond_diff <= (BRANCH_MAX / SSIZE_OF(u16)) && cond_diff >= (BRANCH_MIN / SSIZE_OF(u16)))
+ total_size = (sljit_uw)cond_size;
+ else if (RISCV_HAS_COMPRESSED(200) && RISCV_CHECK_COMPRESSED_JUMP(jump, diff, u16))
+ total_size = 1;
+ else if (diff >= (JUMP_MIN / SSIZE_OF(u16)) && diff <= (JUMP_MAX / SSIZE_OF(u16)))
+ total_size = 2;
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ else if (diff >= (S32_MIN / SSIZE_OF(u16)) && diff <= (S32_MAX / SSIZE_OF(u16)))
+ total_size = 4;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ }
+ }
+
+ size_reduce += JUMP_MAX_SIZE - total_size;
+ jump->flags |= total_size << JUMP_SIZE_SHIFT;
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ } else {
+ total_size = 11;
+
+ if (!(jump->flags & JUMP_ADDR)) {
+ /* Real size minus 1. Unit size: 16 bit. */
+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
+ if (jump->u.label->size > jump->addr) {
+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);
+ diff -= (sljit_sw)size_reduce;
+ }
+
+ if (diff >= (S32_MIN / SSIZE_OF(u16)) && diff <= (S32_MAX / SSIZE_OF(u16)))
+ total_size = 3;
+ } else if (jump->u.target < S32_MAX)
+ total_size = 3;
+ else if (jump->u.target < S44_MAX)
+ total_size = 7;
+ else if (jump->u.target <= S52_MAX)
+ total_size = 9;
+
+ size_reduce += 11 - total_size;
+ jump->flags |= total_size << JUMP_SIZE_SHIFT;
+#endif /* !SLJIT_CONFIG_RISCV_64 */
+ }
+
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ }
+
+ compiler->size -= size_reduce;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
+{
+ struct sljit_memory_fragment *buf;
+ sljit_u16 *code;
+ sljit_u16 *code_ptr;
+ sljit_u16 *buf_ptr;
+ sljit_u16 *buf_end;
+ sljit_uw half_count;
+ SLJIT_NEXT_DEFINE_TYPES;
+ sljit_sw executable_offset;
+ sljit_uw addr;
+ sljit_ins ins;
+
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
+
+ reduce_code_size(compiler);
+
+ code = (sljit_u16 *)allocate_executable_memory(compiler->size * sizeof(sljit_u16), options, exec_allocator_data, &executable_offset);
+ PTR_FAIL_WITH_EXEC_IF(code);
+
+ reverse_buf(compiler);
+ buf = compiler->buf;
+
+ code_ptr = code;
+ half_count = 0;
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ SLJIT_NEXT_INIT_TYPES();
+ SLJIT_GET_NEXT_MIN();
+
+ do {
+ buf_ptr = (sljit_u16*)buf->memory;
+ buf_end = buf_ptr + (buf->used_size >> 1);
+ do {
+ *code_ptr = *buf_ptr++;
+ if (next_min_addr == half_count) {
+ SLJIT_ASSERT(!label || label->size >= half_count);
+ SLJIT_ASSERT(!jump || jump->addr >= half_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= half_count);
+
+ /* These structures are ordered by their address. */
+ if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+ *code_ptr = buf_ptr[-1];
+ }
+
+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ if (next_min_addr == next_jump_addr) {
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+ half_count = half_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT);
+ code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
+ SLJIT_ASSERT((jump->flags & PATCH_B) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));
+ } else {
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ half_count += 3;
+ jump->addr = (sljit_uw)code_ptr;
+ code_ptr += 3;
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ half_count += jump->flags >> JUMP_SIZE_SHIFT;
+ addr = (sljit_uw)code_ptr;
+ code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);
+ jump->addr = addr;
+#endif /* SLJIT_CONFIG_RISCV_32 */
+ }
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ } else if (next_min_addr == next_const_addr) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+ }
+
+ SLJIT_GET_NEXT_MIN();
+ }
+ code_ptr++;
+ half_count++;
+ } while (buf_ptr < buf_end);
+
+ buf = buf->next;
+ } while (buf);
+
+ if (label && label->size == half_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
+ label->u.addr = (sljit_uw)code_ptr;
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ }
+
+ SLJIT_ASSERT(!label);
+ SLJIT_ASSERT(!jump);
+ SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
+
+ jump = compiler->jumps;
+ while (jump) {
+ do {
+ if (!(jump->flags & (PATCH_B | PATCH_J)) || (jump->flags & JUMP_MOV_ADDR)) {
+ load_addr_to_reg(jump, executable_offset);
+ break;
+ }
+
+ addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
+ buf_ptr = (sljit_u16 *)jump->addr;
+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
+
+ if (jump->flags & PATCH_B) {
+ SLJIT_ASSERT(RISCV_HAS_COMPRESSED(200) || !(jump->flags & PATCH_16));
+ SLJIT_ASSERT((sljit_sw)addr >= BRANCH_MIN && (sljit_sw)addr <= BRANCH_MAX);
+
+ if (RISCV_COMPRESSED_CHECK(jump->flags & PATCH_16)) {
+ buf_ptr[0] |= C_BRN16(addr);
+ break;
+ }
+
+ buf_ptr[0] |= (sljit_u16)(((addr & 0x800) >> 4) | ((addr & 0x1e) << 7));
+ buf_ptr[1] |= (sljit_u16)(((addr & 0x7e0) << 4) | ((addr & 0x1000) << 3));
+ break;
+ }
+
+ SLJIT_ASSERT(RISCV_HAS_COMPRESSED(200) || !(jump->flags & PATCH_16));
+ if (RISCV_COMPRESSED_CHECK(jump->flags & PATCH_16)) {
+ SLJIT_ASSERT((sljit_sw)addr >= JUMP16_MIN && (sljit_sw)addr <= JUMP16_MAX);
+#if defined SLJIT_CONFIG_RISCV_32
+ ins = ((jump->flags & IS_CALL) ? C_JAL : C_J) | C_JMP16(addr);
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ SLJIT_ASSERT(!(jump->flags & IS_CALL));
+ ins = C_J | C_JMP16(addr);
+#endif /* SLJIT_CONFIG_RISCV_32 */
+ buf_ptr[0] = (sljit_u16)ins;
+ break;
+ }
+
+ SLJIT_ASSERT((sljit_sw)addr >= JUMP_MIN && (sljit_sw)addr <= JUMP_MAX);
+ addr = (addr & 0xff000) | ((addr & 0x800) << 9) | ((addr & 0x7fe) << 20) | ((addr & 0x100000) << 11);
+ ins = JAL | RD((jump->flags & IS_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | (sljit_ins)addr;
+ buf_ptr[0] = (sljit_u16)ins;
+ buf_ptr[1] = (sljit_u16)(ins >> 16);
+ } while (0);
+
+ jump = jump->next;
+ }
+
+ compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
+
+ code = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+ code_ptr = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
+ SLJIT_CACHE_FLUSH(code, code_ptr);
+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
+ return code;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type) {
+ case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return (SLJIT_IS_FPU_AVAILABLE) != 0;
+#elif defined(__riscv_float_abi_soft)
+ return 0;
+#else /* !SLJIT_IS_FPU_AVAILABLE && !__riscv_float_abi_soft */
+ return 1;
+#endif /* SLJIT_IS_FPU_AVAILABLE */
+ case SLJIT_HAS_ZERO_REGISTER:
+ case SLJIT_HAS_COPY_F32:
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ case SLJIT_HAS_COPY_F64:
+#endif /* !SLJIT_CONFIG_RISCV_64 */
+ case SLJIT_HAS_ATOMIC:
+ return RISCV_HAS_ATOMIC(200) ? 1 : 0;
+ case SLJIT_HAS_MEMORY_BARRIER:
+ return 1;
+ case SLJIT_HAS_CLZ:
+ case SLJIT_HAS_CTZ:
+ case SLJIT_HAS_REV:
+ case SLJIT_HAS_ROT:
+ return RISCV_HAS_BITMANIP_B(93) ? 1 : 0;
+ case SLJIT_HAS_CMOV:
+ return RISCV_HAS_ICOND(100) ? 2 : 0;
+ case SLJIT_HAS_SIMD:
+ return RISCV_HAS_VECTOR(100) ? 1 : 0;
+ default:
+ return 0;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
+{
+ switch (type) {
+ case SLJIT_UNORDERED_OR_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ return 2;
+
+ case SLJIT_UNORDERED:
+ case SLJIT_ORDERED:
+ return 1;
+ }
+
+ return 0;
+}
+
+/* --------------------------------------------------------------------- */
+/* Entry, exit */
+/* --------------------------------------------------------------------- */
+
+/* Creates an index in data_transfer_insts array. */
+#define LOAD_DATA 0x01
+#define WORD_DATA 0x00
+#define BYTE_DATA 0x02
+#define HALF_DATA 0x04
+#define INT_DATA 0x06
+#define SIGNED_DATA 0x08
+/* Separates integer and floating point registers */
+#define GPR_REG 0x0f
+#define DOUBLE_DATA 0x10
+#define SINGLE_DATA 0x12
+
+#define MEM_MASK 0x1f
+
+#define ARG_TEST 0x00020
+#define ALT_KEEP_CACHE 0x00040
+#define CUMULATIVE_OP 0x00080
+#define IMM_OP 0x00100
+#define MOVE_OP 0x00200
+#define SRC2_IMM 0x00400
+
+#define UNUSED_DEST 0x00800
+#define REG_DEST 0x01000
+#define REG1_SOURCE 0x02000
+#define REG2_SOURCE 0x04000
+#define SLOW_SRC1 0x08000
+#define SLOW_SRC2 0x10000
+#define SLOW_DEST 0x20000
+#define MEM_USE_TMP2 0x40000
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+#define STACK_STORE SW
+#define STACK_LOAD LW
+#define C_STACK_OFFSET_CHECK(offset) ((offset) <= 0xfc)
+#define C_STACK_LOAD(offset) (C_LWSP | C_LD32_SP(offset))
+#define C_STACK_STORE(offset) (C_SWSP | C_ST32_SP(offset))
+#else /* !SLJIT_CONFIG_RISCV_32 */
+#define STACK_STORE SD
+#define STACK_LOAD LD
+#define C_STACK_OFFSET_CHECK(offset) ((offset) <= 0x1f8)
+#define C_STACK_LOAD(offset) (C_LDSP | C_LD64_SP(offset))
+#define C_STACK_STORE(offset) (C_SDSP | C_ST64_SP(offset))
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+#include "sljitNativeRISCV_32.c"
+#else /* !SLJIT_CONFIG_RISCV_32 */
+#include "sljitNativeRISCV_64.c"
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+#define STACK_MAX_DISTANCE (-SIMM_MIN)
+
+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw);
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);
+ sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);
+ sljit_s32 i, tmp, offset;
+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if ((local_size & SSIZE_OF(sw)) != 0)
+ local_size += SSIZE_OF(sw);
+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+ }
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+#endif /* SLJIT_CONFIG_RISCV_32 */
+ local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
+ compiler->local_size = local_size;
+
+ if (local_size <= STACK_MAX_DISTANCE) {
+ /* Frequent case. */
+ offset = local_size - SSIZE_OF(sw);
+ local_size = -local_size;
+ if (RISCV_HAS_COMPRESSED(200) && local_size >= -0x200) {
+ SLJIT_ASSERT((local_size & 0x200) != 0 && (local_size & 0xf) == 0);
+ FAIL_IF(push_inst16(compiler, C_ADDI16SP | (sljit_u16)(((local_size & 0x10) << 2) | ((local_size & 0x20) >> 3) | ((local_size & 0x40) >> 1) | ((local_size & 0x180) >> 4) | (1 << 12))));
+ } else
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size)));
+ local_size = 0;
+ } else {
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(STACK_MAX_DISTANCE)));
+ local_size -= STACK_MAX_DISTANCE;
+
+ if (local_size > STACK_MAX_DISTANCE)
+ FAIL_IF(load_immediate(compiler, TMP_REG1, local_size, TMP_REG3));
+ offset = STACK_MAX_DISTANCE - SSIZE_OF(sw);
+ }
+
+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))
+ FAIL_IF(push_inst16(compiler, C_STACK_STORE(offset) | C_RS2(RETURN_ADDR_REG)));
+ else
+ FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(RETURN_ADDR_REG), offset));
+
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
+ offset -= SSIZE_OF(sw);
+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))
+ FAIL_IF(push_inst16(compiler, C_STACK_STORE(offset) | C_RS2(i)));
+ else
+ FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset));
+ }
+
+ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ offset -= SSIZE_OF(sw);
+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))
+ FAIL_IF(push_inst16(compiler, C_STACK_STORE(offset) | C_RS2(i)));
+ else
+ FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset));
+ }
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ /* This alignment is valid because offset is not used after storing FPU regs. */
+ if ((offset & SSIZE_OF(sw)) != 0)
+ offset -= SSIZE_OF(sw);
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ offset -= SSIZE_OF(f64);
+ if (RISCV_HAS_COMPRESSED(200) && offset <= 0x1f8)
+ FAIL_IF(push_inst16(compiler, C_FSDSP | C_FRS2(i) | C_ST64_SP(offset)));
+ else
+ FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset));
+ }
+
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ offset -= SSIZE_OF(f64);
+ if (RISCV_HAS_COMPRESSED(200) && offset <= 0x1f8)
+ FAIL_IF(push_inst16(compiler, C_FSDSP | C_FRS2(i) | C_ST64_SP(offset)));
+ else
+ FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset));
+ }
+
+ if (local_size > STACK_MAX_DISTANCE)
+ FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RS1(SLJIT_SP) | RS2(TMP_REG1)));
+ else if (local_size > 0)
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size)));
+
+ if (options & SLJIT_ENTER_REG_ARG)
+ return SLJIT_SUCCESS;
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ saved_arg_count = 0;
+ tmp = SLJIT_R0;
+
+ while (arg_types > 0) {
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(SLJIT_S0 - saved_arg_count) | C_RS2(tmp)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_S0 - saved_arg_count) | RS1(tmp) | IMM_I(0)));
+ saved_arg_count++;
+ }
+ tmp++;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+#undef STACK_MAX_DISTANCE
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches = ENTER_GET_FLOAT_REGS(scratches);
+ sljit_s32 fsaveds = ENTER_GET_FLOAT_REGS(saveds);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if ((local_size & SSIZE_OF(sw)) != 0)
+ local_size += SSIZE_OF(sw);
+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+ }
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, f64);
+#endif /* SLJIT_CONFIG_RISCV_32 */
+ compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
+
+ return SLJIT_SUCCESS;
+}
+
+#define STACK_MAX_DISTANCE (-SIMM_MIN - 16)
+
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)
+{
+ sljit_s32 i, tmp, offset;
+ sljit_s32 local_size = compiler->local_size;
+
+ if (local_size > STACK_MAX_DISTANCE) {
+ local_size -= STACK_MAX_DISTANCE;
+
+ if (local_size > STACK_MAX_DISTANCE) {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, local_size, TMP_REG3));
+ FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RS1(SLJIT_SP) | RS2(TMP_REG2)));
+ } else
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size)));
+
+ local_size = STACK_MAX_DISTANCE;
+ }
+
+ SLJIT_ASSERT(local_size > 0);
+
+ offset = local_size - SSIZE_OF(sw);
+ if (!is_return_to) {
+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))
+ FAIL_IF(push_inst16(compiler, C_STACK_LOAD(offset) | C_RD(RETURN_ADDR_REG)));
+ else
+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RS1(SLJIT_SP) | IMM_I(offset)));
+ }
+
+ tmp = SLJIT_S0 - compiler->saveds;
+ for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {
+ offset -= SSIZE_OF(sw);
+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))
+ FAIL_IF(push_inst16(compiler, C_STACK_LOAD(offset) | C_RD(i)));
+ else
+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
+ }
+
+ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ offset -= SSIZE_OF(sw);
+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))
+ FAIL_IF(push_inst16(compiler, C_STACK_LOAD(offset) | C_RD(i)));
+ else
+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
+ }
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ /* This alignment is valid because offset is not used after storing FPU regs. */
+ if ((offset & SSIZE_OF(sw)) != 0)
+ offset -= SSIZE_OF(sw);
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+ tmp = SLJIT_FS0 - compiler->fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ offset -= SSIZE_OF(f64);
+ if (RISCV_HAS_COMPRESSED(200) && offset <= 0x1f8)
+ FAIL_IF(push_inst16(compiler, C_FLDSP | C_FRD(i) | C_LD64_SP(offset)));
+ else
+ FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
+ }
+
+ for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ offset -= SSIZE_OF(f64);
+ if (RISCV_HAS_COMPRESSED(200) && offset <= 0x1f8)
+ FAIL_IF(push_inst16(compiler, C_FLDSP | C_FRD(i) | C_LD64_SP(offset)));
+ else
+ FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
+ }
+
+ if (RISCV_HAS_COMPRESSED(200) && local_size <= 0x1f0) {
+ SLJIT_ASSERT((local_size & 0xf) == 0);
+ return push_inst16(compiler, C_ADDI16SP | (sljit_u16)(((local_size & 0x10) << 2) | ((local_size & 0x20) >> 3) | ((local_size & 0x40) >> 1) | ((local_size & 0x180) >> 4)));
+ }
+
+ return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size));
+}
+
+#undef STACK_MAX_DISTANCE
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ FAIL_IF(emit_stack_frame_release(compiler, 0));
+ return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
+ src = TMP_REG1;
+ srcw = 0;
+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0)));
+ src = TMP_REG1;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 1));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
+}
+
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+#define ARCH_32_64(a, b) a
+#else /* !SLJIT_CONFIG_RISCV_32 */
+#define ARCH_32_64(a, b) b
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+static const sljit_ins data_transfer_insts[16 + 4] = {
+/* u w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */),
+/* u w l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x3) | OPC(0x3) /* ld */),
+/* u b s */ F3(0x0) | OPC(0x23) /* sb */,
+/* u b l */ F3(0x4) | OPC(0x3) /* lbu */,
+/* u h s */ F3(0x1) | OPC(0x23) /* sh */,
+/* u h l */ F3(0x5) | OPC(0x3) /* lhu */,
+/* u i s */ F3(0x2) | OPC(0x23) /* sw */,
+/* u i l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x6) | OPC(0x3) /* lwu */),
+
+/* s w s */ ARCH_32_64(F3(0x2) | OPC(0x23) /* sw */, F3(0x3) | OPC(0x23) /* sd */),
+/* s w l */ ARCH_32_64(F3(0x2) | OPC(0x3) /* lw */, F3(0x3) | OPC(0x3) /* ld */),
+/* s b s */ F3(0x0) | OPC(0x23) /* sb */,
+/* s b l */ F3(0x0) | OPC(0x3) /* lb */,
+/* s h s */ F3(0x1) | OPC(0x23) /* sh */,
+/* s h l */ F3(0x1) | OPC(0x3) /* lh */,
+/* s i s */ F3(0x2) | OPC(0x23) /* sw */,
+/* s i l */ F3(0x2) | OPC(0x3) /* lw */,
+
+/* d s */ F3(0x3) | OPC(0x27) /* fsd */,
+/* d l */ F3(0x3) | OPC(0x7) /* fld */,
+/* s s */ F3(0x2) | OPC(0x27) /* fsw */,
+/* s l */ F3(0x2) | OPC(0x7) /* flw */,
+};
+
+#undef ARCH_32_64
+
+static sljit_s32 push_mem_inst(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 base, sljit_sw offset)
+{
+ sljit_ins ins;
+ sljit_s32 signed_flags;
+ sljit_s32 load_flags;
+
+ SLJIT_ASSERT(FAST_IS_REG(base) && offset <= 0xfff && offset >= SIMM_MIN);
+
+ flags &= MEM_MASK;
+
+ if (RISCV_HAS_COMPRESSED(200) && offset >= 0) {
+ if (base == SLJIT_SP) {
+ signed_flags = flags | SIGNED_DATA;
+
+ if ((offset & 0x3) == 0 && offset <= 0xfc) {
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ if ((signed_flags == (SIGNED_DATA | LOAD_DATA) || signed_flags == (INT_DATA | SIGNED_DATA | LOAD_DATA)))
+ return push_inst16(compiler, C_LWSP | C_RD(reg) | C_LD32_SP(offset));
+ if ((signed_flags == SIGNED_DATA || signed_flags == (INT_DATA | SIGNED_DATA)))
+ return push_inst16(compiler, C_SWSP | C_RS2(reg) | C_ST32_SP(offset));
+ if (flags == (SINGLE_DATA | LOAD_DATA))
+ return push_inst16(compiler, C_FLWSP | C_FRD(reg) | C_LD32_SP(offset));
+ if (flags == SINGLE_DATA)
+ return push_inst16(compiler, C_FSWSP | C_FRS2(reg) | C_ST32_SP(offset));
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ if (flags == (INT_DATA | SIGNED_DATA | LOAD_DATA))
+ return push_inst16(compiler, C_LWSP | C_RD(reg) | C_LD32_SP(offset));
+ if (signed_flags == (INT_DATA | SIGNED_DATA))
+ return push_inst16(compiler, C_SWSP | C_RS2(reg) | C_ST32_SP(offset));
+#endif /* SLJIT_CONFIG_RISCV_32 */
+ }
+
+ if ((offset & 0x7) == 0 && offset <= 0x1f8) {
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ if (signed_flags == (SIGNED_DATA | LOAD_DATA))
+ return push_inst16(compiler, C_LDSP | C_RD(reg) | C_LD64_SP(offset));
+ if (signed_flags == SIGNED_DATA)
+ return push_inst16(compiler, C_SDSP | C_RS2(reg) | C_ST64_SP(offset));
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ if (flags == (DOUBLE_DATA | LOAD_DATA))
+ return push_inst16(compiler, C_FLDSP | C_FRD(reg) | C_LD64_SP(offset));
+ if (flags == DOUBLE_DATA)
+ return push_inst16(compiler, C_FSDSP | C_FRS2(reg) | C_ST64_SP(offset));
+ }
+ } else if (C_IS_R3(base) && (flags <= GPR_REG ? C_IS_R3(reg) : C_IS_FR3(reg))) {
+ SLJIT_COMPILE_ASSERT(LOAD_DATA == 1, load_data_bit_error);
+ signed_flags = flags | LOAD_DATA | SIGNED_DATA;
+ load_flags = flags | LOAD_DATA;
+
+ if ((offset & 0x3) == 0 && offset <= 0x7c) {
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ if (signed_flags == (SIGNED_DATA | LOAD_DATA) || signed_flags == (INT_DATA | SIGNED_DATA | LOAD_DATA))
+ return push_inst16(compiler, (C_SW ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_RS2_R3(reg) | C_MEM32(offset));
+ if (load_flags == (SINGLE_DATA | LOAD_DATA))
+ return push_inst16(compiler, (C_FSW ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_FRS2_R3(reg) | C_MEM32(offset));
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ if (load_flags == (INT_DATA | SIGNED_DATA | LOAD_DATA))
+ return push_inst16(compiler, (C_SW ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_RS2_R3(reg) | C_MEM32(offset));
+#endif /* SLJIT_CONFIG_RISCV_32 */
+ }
+
+ if ((offset & 0x7) == 0 && offset <= 0xf8) {
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ if (signed_flags == (SIGNED_DATA | LOAD_DATA))
+ return push_inst16(compiler, (C_SD ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_RS2_R3(reg) | C_MEM64(offset));
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ if (load_flags == (DOUBLE_DATA | LOAD_DATA))
+ return push_inst16(compiler, (C_FSD ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_FRS2_R3(reg) | C_MEM64(offset));
+ }
+ }
+ }
+
+ ins = data_transfer_insts[flags] | RS1(base);
+ if (flags & LOAD_DATA)
+ ins |= (flags <= GPR_REG ? RD(reg) : FRD(reg)) | IMM_I(offset);
+ else
+ ins |= (flags <= GPR_REG ? RS2(reg) : FRS2(reg)) | IMM_S(offset);
+
+ return push_inst(compiler, ins);
+}
+
+/* Can perform an operation using at most 1 instruction. */
+static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
+{
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+
+ if (!(arg & OFFS_REG_MASK) && argw <= SIMM_MAX && argw >= SIMM_MIN) {
+ /* Works for both absoulte and relative addresses. */
+ if (SLJIT_UNLIKELY(flags & ARG_TEST))
+ return 1;
+
+ FAIL_IF(push_mem_inst(compiler, flags, reg, arg & REG_MASK, argw));
+ return -1;
+ }
+ return 0;
+}
+
+#define TO_ARGW_HI(argw) (((argw) & ~0xfff) + (((argw) & 0x800) ? 0x1000 : 0))
+
+/* See getput_arg below.
+ Note: can_cache is called only for binary operators. */
+static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
+{
+ SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM));
+
+ /* Simple operation except for updates. */
+ if (arg & OFFS_REG_MASK) {
+ argw &= 0x3;
+ next_argw &= 0x3;
+ if (argw && argw == next_argw && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK)))
+ return 1;
+ return 0;
+ }
+
+ if (arg == next_arg) {
+ if (((next_argw - argw) <= SIMM_MAX && (next_argw - argw) >= SIMM_MIN)
+ || TO_ARGW_HI(argw) == TO_ARGW_HI(next_argw))
+ return 1;
+ return 0;
+ }
+
+ return 0;
+}
+
+/* Emit the necessary instructions. See can_cache above. */
+static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
+{
+ sljit_s32 base = arg & REG_MASK;
+ sljit_s32 tmp_r = (flags & MEM_USE_TMP2) ? TMP_REG2 : TMP_REG1;
+ sljit_sw offset, argw_hi;
+ sljit_ins ins = ADD;
+
+ SLJIT_ASSERT(arg & SLJIT_MEM);
+ if (!(next_arg & SLJIT_MEM)) {
+ next_arg = 0;
+ next_argw = 0;
+ }
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ argw &= 0x3;
+
+ if (RISCV_HAS_BITMANIP_A(93)) {
+ switch (argw) {
+ case 1:
+ ins = SH1ADD;
+ break;
+ case 2:
+ ins = SH2ADD;
+ break;
+ case 3:
+ ins = SH3ADD;
+ break;
+ }
+ FAIL_IF(push_inst(compiler, ins | RD(tmp_r) | RS1(OFFS_REG(arg)) | RS2(base)));
+ return push_mem_inst(compiler, flags, reg, tmp_r, 0);
+ }
+
+ /* Using the cache. */
+ if (argw == compiler->cache_argw) {
+ if (arg == compiler->cache_arg)
+ return push_mem_inst(compiler, flags, reg, TMP_REG3, 0);
+
+ if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) {
+ if (arg == next_arg && argw == (next_argw & 0x3)) {
+ compiler->cache_arg = arg;
+ compiler->cache_argw = argw;
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(TMP_REG3) | RS2(base)));
+ return push_mem_inst(compiler, flags, reg, TMP_REG3, 0);
+ }
+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(TMP_REG3)));
+ return push_mem_inst(compiler, flags, reg, tmp_r, 0);
+ }
+ }
+
+ if (SLJIT_UNLIKELY(argw)) {
+ compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK);
+ compiler->cache_argw = argw;
+ FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG3) | RS1(OFFS_REG(arg)) | IMM_I(argw)));
+ }
+
+ if (arg == next_arg && argw == (next_argw & 0x3)) {
+ compiler->cache_arg = arg;
+ compiler->cache_argw = argw;
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(base) | RS2(!argw ? OFFS_REG(arg) : TMP_REG3)));
+ tmp_r = TMP_REG3;
+ }
+ else
+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(!argw ? OFFS_REG(arg) : TMP_REG3)));
+
+ return push_mem_inst(compiler, flags, reg, tmp_r, 0);
+ }
+
+ if (compiler->cache_arg == arg && argw - compiler->cache_argw <= SIMM_MAX && argw - compiler->cache_argw >= SIMM_MIN)
+ return push_mem_inst(compiler, flags, reg, TMP_REG3, argw - compiler->cache_argw);
+
+ if (compiler->cache_arg == SLJIT_MEM && (argw - compiler->cache_argw <= SIMM_MAX) && (argw - compiler->cache_argw >= SIMM_MIN)) {
+ offset = argw - compiler->cache_argw;
+ } else {
+ compiler->cache_arg = SLJIT_MEM;
+
+ argw_hi = TO_ARGW_HI(argw);
+
+ if (next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN && argw_hi != TO_ARGW_HI(next_argw)) {
+ FAIL_IF(load_immediate(compiler, TMP_REG3, argw, tmp_r));
+ compiler->cache_argw = argw;
+ offset = 0;
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG3, argw_hi, tmp_r));
+ compiler->cache_argw = argw_hi;
+ offset = argw & 0xfff;
+ argw = argw_hi;
+ }
+ }
+
+ if (!base)
+ return push_mem_inst(compiler, flags, reg, TMP_REG3, offset);
+
+ if (arg == next_arg && next_argw - argw <= SIMM_MAX && next_argw - argw >= SIMM_MIN) {
+ compiler->cache_arg = arg;
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG3) | RS1(TMP_REG3) | RS2(base)));
+ return push_mem_inst(compiler, flags, reg, TMP_REG3, offset);
+ }
+
+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(TMP_REG3) | RS2(base)));
+ return push_mem_inst(compiler, flags, reg, tmp_r, offset);
+}
+
+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
+{
+ sljit_s32 base = arg & REG_MASK;
+ sljit_s32 tmp_r = TMP_REG1;
+
+ if (getput_arg_fast(compiler, flags, reg, arg, argw))
+ return compiler->error;
+
+ if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA))
+ tmp_r = reg;
+
+ if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
+ argw &= 0x3;
+
+ if (SLJIT_UNLIKELY(argw)) {
+ FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(OFFS_REG(arg)) | IMM_I(argw)));
+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(tmp_r) | RS2(base)));
+ }
+ else
+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(OFFS_REG(arg))));
+
+ argw = 0;
+ } else {
+ FAIL_IF(load_immediate(compiler, tmp_r, TO_ARGW_HI(argw), TMP_REG3));
+
+ if (base != 0)
+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(tmp_r) | RS2(base)));
+ }
+
+ return push_mem_inst(compiler, flags, reg, tmp_r, argw & 0xfff);
+}
+
+static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
+{
+ if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
+ return compiler->error;
+ return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
+}
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+#define WORD 0
+#define WORD_32 0
+#define IMM_EXTEND(v) (IMM_I(v))
+#else /* !SLJIT_CONFIG_RISCV_32 */
+#define WORD word
+#define WORD_32 0x08
+#define IMM_EXTEND(v) (IMM_I((op & SLJIT_32) ? (v) : (32 + (v))))
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+static sljit_s32 emit_add(struct sljit_compiler *compiler, sljit_ins word, sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
+{
+ SLJIT_UNUSED_ARG(word);
+
+ if (dst == src2) {
+ src2 = src1;
+ src1 = dst;
+ }
+
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1) {
+ if (WORD == 0 && src2 != 0)
+ return push_inst16(compiler, C_ADD | C_RD(dst) | C_RS2(src2));
+
+ if (WORD == 0x8 && C_IS_R3(dst) && C_IS_R3(src2))
+ return push_inst16(compiler, C_ADDW | C_RS1_R3(dst) | C_RS2_R3(src2));
+ }
+
+ return push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2));
+}
+
+static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
+{
+ sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ);
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
+ sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;
+#else /* !SLJIT_CONFIG_RISCV_64 */
+ sljit_ins word_size = 32;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
+
+ /* The OTHER_FLAG is the counter. */
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(word_size)));
+
+ /* The TMP_REG2 is the next value. */
+ if (src != TMP_REG2)
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(src) | IMM_I(0)));
+
+ FAIL_IF(push_inst(compiler, BEQ | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)((is_clz ? 4 : 5) * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20)));
+
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(OTHER_FLAG) | RS1(TMP_ZERO) | IMM_I(0)));
+ if (!is_clz) {
+ FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG1) | RS1(TMP_REG2) | IMM_I(1)));
+ FAIL_IF(push_inst(compiler, BNE | RS1(TMP_REG1) | RS2(TMP_ZERO) | ((sljit_ins)(2 * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20)));
+ } else
+ FAIL_IF(push_inst(compiler, BLT | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)(2 * SSIZE_OF(ins)) << 7) | ((sljit_ins)(8 * SSIZE_OF(ins)) << 20)));
+
+ /* The TMP_REG1 is the next shift. */
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(word_size)));
+
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(TMP_REG2) | IMM_I(0)));
+ FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(1)));
+
+ FAIL_IF(push_inst(compiler, (is_clz ? SRL : SLL) | WORD | RD(TMP_REG2) | RS1(EQUAL_FLAG) | RS2(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, BNE | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)0xfe000e80 - ((2 * SSIZE_OF(ins)) << 7))));
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(TMP_REG1) | IMM_I(-1)));
+ FAIL_IF(push_inst(compiler, (is_clz ? SRL : SLL) | WORD | RD(TMP_REG2) | RS1(EQUAL_FLAG) | RS2(TMP_REG2)));
+ FAIL_IF(push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, BEQ | RS1(TMP_REG2) | RS2(TMP_ZERO) | ((sljit_ins)0xfe000e80 - ((5 * SSIZE_OF(ins)) << 7))));
+
+ return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(OTHER_FLAG) | IMM_I(0));
+}
+
+static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
+{
+ SLJIT_UNUSED_ARG(op);
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ if (!(op & SLJIT_32)) {
+ FAIL_IF(push_inst(compiler, LUI | RD(OTHER_FLAG) | 0x10000));
+ FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(src) | IMM_I(32)));
+ FAIL_IF(push_inst(compiler, ADDI | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | IMM_I(0xfff)));
+ FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(src) | IMM_I(32)));
+ FAIL_IF(push_inst(compiler, SLLI | RD(EQUAL_FLAG) | RS1(OTHER_FLAG) | IMM_I(32)));
+ FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));
+ FAIL_IF(push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG)));
+
+ FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(dst) | IMM_I(16)));
+ FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
+ FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));
+ FAIL_IF(push_inst(compiler, SLLI | RD(EQUAL_FLAG) | RS1(OTHER_FLAG) | IMM_I(8)));
+ FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(16)));
+ FAIL_IF(push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG)));
+ FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));
+
+ FAIL_IF(push_inst(compiler, SRLI | RD(TMP_REG1) | RS1(dst) | IMM_I(8)));
+ FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
+ FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));
+ FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(8)));
+ return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));
+ }
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ FAIL_IF(push_inst(compiler, SRLI | WORD_32 | RD(TMP_REG1) | RS1(src) | IMM_I(16)));
+ FAIL_IF(push_inst(compiler, LUI | RD(OTHER_FLAG) | 0xff0000));
+ FAIL_IF(push_inst(compiler, SLLI | WORD_32 | RD(dst) | RS1(src) | IMM_I(16)));
+ FAIL_IF(push_inst(compiler, ORI | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | IMM_I(0xff)));
+ FAIL_IF(push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1)));
+
+ FAIL_IF(push_inst(compiler, SRLI | WORD_32 | RD(TMP_REG1) | RS1(dst) | IMM_I(8)));
+ FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
+ FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ FAIL_IF(push_inst(compiler, SLLI | (GET_OPCODE(op) == SLJIT_REV_S32 ? WORD_32 : 0) | RD(dst) | RS1(dst) | IMM_I(8)));
+#else /* !SLJIT_CONFIG_RISCV_64 */
+ FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(8)));
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));
+}
+
+static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
+{
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
+ sljit_ins word_size = (op & SLJIT_32) ? 32 : 64;
+#else /* !SLJIT_CONFIG_RISCV_64 */
+ sljit_ins word_size = 32;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(src) | IMM_I(8)));
+ FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src) | IMM_I(word_size - 8)));
+ FAIL_IF(push_inst(compiler, ANDI | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_I(0xff)));
+ FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI) | WORD | RD(dst) | RS1(dst) | IMM_I(word_size - 16)));
+ return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));
+}
+
+#define EMIT_LOGICAL(op_imm, op_c_imm, op_reg, op_c_reg) \
+ if (flags & SRC2_IMM) { \
+ if (op & SLJIT_SET_Z) \
+ FAIL_IF(push_inst(compiler, op_imm | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2))); \
+ if (!(flags & UNUSED_DEST)) { \
+ if (op_c_imm != 0 && RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN && C_IS_R3(dst)) \
+ FAIL_IF(push_inst16(compiler, op_c_imm | C_RS1_R3(dst) | C_IMM_I(src2))); \
+ else \
+ FAIL_IF(push_inst(compiler, op_imm | RD(dst) | RS1(src1) | IMM_I(src2))); \
+ } \
+ } else { \
+ if (dst == src2) { \
+ src2 = src1; \
+ src1 = dst; \
+ } \
+ \
+ if (op & SLJIT_SET_Z) \
+ FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); \
+ if (!(flags & UNUSED_DEST)) { \
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && C_IS_R3(dst) && C_IS_R3(src2)) \
+ FAIL_IF(push_inst16(compiler, op_c_reg | C_RS1_R3(dst) | C_RS2_R3(src2))); \
+ else \
+ FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RS1(src1) | RS2(src2))); \
+ } \
+ }
+
+static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+ sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
+{
+ sljit_s32 is_overflow, is_carry, carry_src_r, is_handled, reg;
+ sljit_ins op_imm, op_reg;
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if (dst == src2)
+ return SLJIT_SUCCESS;
+
+ if (!RISCV_HAS_COMPRESSED(200))
+ return push_inst(compiler, ADDI | RD(dst) | RS1(src2) | IMM_I(0));
+
+ /* Revert the x0 to immediate 0. */
+ if (src2 == 0)
+ return push_inst16(compiler, C_LI | C_RD(dst));
+ return push_inst16(compiler, C_MV | C_RD(dst) | C_RS2(src2));
+
+ case SLJIT_MOV_U8:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
+ return push_inst(compiler, ANDI | RD(dst) | RS1(src2) | IMM_I(0xff));
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_S8:
+ if (RISCV_HAS_BITMANIP_B(93))
+ return push_inst(compiler, SEXTB | RD(dst) | RS1(src2));
+
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(24)));
+ return push_inst(compiler, SRAI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(24));
+ }
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_U16:
+ if (RISCV_HAS_BITMANIP_B(93))
+ return push_inst(compiler, ZEXTH | RD(dst) | RS1(src2));
+
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16)));
+ return push_inst(compiler, SRLI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(16));
+ }
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_S16:
+ if (RISCV_HAS_BITMANIP_B(93))
+ return push_inst(compiler, SEXTH | RD(dst) | RS1(src2));
+
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16)));
+ return push_inst(compiler, SRAI | WORD | RD(dst) | RS1(dst) | IMM_EXTEND(16));
+ }
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ case SLJIT_MOV_U32:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (RISCV_HAS_BITMANIP_A(93))
+ return push_inst(compiler, ADD_UW | RD(dst) | RS1(src2) | RS2(TMP_ZERO));
+ FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(src2) | IMM_I(32)));
+ return push_inst(compiler, SRLI | RD(dst) | RS1(dst) | IMM_I(32));
+ }
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_MOV_S32:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (RISCV_HAS_COMPRESSED(200) && dst == src2)
+ return push_inst16(compiler, C_ADDIW | C_RD(dst));
+ return push_inst(compiler, ADDI | 0x8 | RD(dst) | RS1(src2) | IMM_I(0));
+ }
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ case SLJIT_CLZ:
+ case SLJIT_CTZ:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if (RISCV_HAS_BITMANIP_B(93))
+ return push_inst(compiler, ((GET_OPCODE(op) == SLJIT_CLZ) ? CLZ : CTZ) | WORD | RD(dst) | RS1(src2));
+
+ return emit_clz_ctz(compiler, op, dst, src2);
+
+ case SLJIT_REV:
+ case SLJIT_REV_S32:
+ case SLJIT_REV_U32:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if (RISCV_HAS_BITMANIP_B(93)) {
+#if defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64
+ FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2)));
+ if ((op & SLJIT_32) || GET_OPCODE(op) != SLJIT_REV)
+ return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U32 ? SRLI : SRAI)| RD(dst) | RS1(dst) | IMM_I(32));
+ return SLJIT_SUCCESS;
+#else /* !SLJIT_CONFIG_RISCV_64 */
+ return push_inst(compiler, REV8 | RD(dst) | RS1(src2));
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ }
+
+ return emit_rev(compiler, op, dst, src2);
+
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+ SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if (RISCV_HAS_BITMANIP_B(93)) {
+ FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2)));
+#if defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64
+ return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI)| RD(dst) | RS1(dst) | IMM_I(48));
+#else /* !SLJIT_CONFIG_RISCV_64 */
+ return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI) | RD(dst) | RS1(dst) | IMM_I(16));
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ }
+
+ return emit_rev16(compiler, op, dst, src2);
+
+ case SLJIT_ADD:
+ /* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */
+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+ carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;
+
+ if (flags & SRC2_IMM) {
+ if (is_overflow) {
+ if (dst == src1) {
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(OTHER_FLAG) | C_RS2(src1)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(0)));
+ }
+ } else if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));
+
+ /* Only the zero flag is needed. */
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) {
+ SLJIT_ASSERT(src2 != 0);
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)
+ FAIL_IF(push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
+ }
+ } else {
+ if (is_overflow)
+ FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
+ else if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, ADD | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
+
+ if (is_overflow || carry_src_r != 0) {
+ if (src1 != dst)
+ carry_src_r = (sljit_s32)src1;
+ else if (src2 != dst)
+ carry_src_r = (sljit_s32)src2;
+ else {
+ FAIL_IF(push_inst(compiler, ADDI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(0)));
+ carry_src_r = OTHER_FLAG;
+ }
+ }
+
+ /* Only the zero flag is needed. */
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
+ FAIL_IF(emit_add(compiler, WORD, dst, src1, src2));
+ }
+
+ /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
+ if (carry_src_r != 0 || (is_overflow && !(flags & SRC2_IMM))) {
+ if (flags & SRC2_IMM)
+ FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(src2)));
+ else
+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(dst) | RS2(carry_src_r)));
+ }
+
+ if (!is_overflow)
+ return SLJIT_SUCCESS;
+
+ if (flags & SRC2_IMM) {
+ if (src2 >= 0)
+ return push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(dst) | RS2(dst == src1 ? OTHER_FLAG : src1));
+ return push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(dst == src1 ? OTHER_FLAG : src1) | RS2(dst));
+ }
+
+ FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RS1(dst) | RS2(EQUAL_FLAG)));
+ if (op & SLJIT_SET_Z) {
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(EQUAL_FLAG) | C_RS2(dst)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0)));
+ }
+ FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_EXTEND(31)));
+ return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG));
+
+ case SLJIT_ADDC:
+ carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;
+
+ if (flags & SRC2_IMM) {
+ SLJIT_ASSERT(src2 != 0);
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)
+ FAIL_IF(push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
+ } else {
+ if (carry_src_r != 0) {
+ if (src1 != dst)
+ carry_src_r = (sljit_s32)src1;
+ else if (src2 != dst)
+ carry_src_r = (sljit_s32)src2;
+ else {
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(EQUAL_FLAG) | C_RS2(src1)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
+ carry_src_r = EQUAL_FLAG;
+ }
+ }
+
+ FAIL_IF(emit_add(compiler, WORD, dst, src1, src2));
+ }
+
+ /* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
+ if (carry_src_r != 0) {
+ if (flags & SRC2_IMM)
+ FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(src2)));
+ else
+ FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RS1(dst) | RS2(carry_src_r)));
+ }
+
+ if (RISCV_HAS_COMPRESSED(200) && WORD == 0)
+ FAIL_IF(push_inst16(compiler, C_ADD | C_RD(dst) | C_RS2(OTHER_FLAG)));
+ else
+ FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
+
+ if (carry_src_r == 0)
+ return SLJIT_SUCCESS;
+
+ /* Set ULESS_FLAG (dst == 0) && (OTHER_FLAG == 1). */
+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(dst) | RS2(OTHER_FLAG)));
+ /* Set carry flag. */
+ return push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(EQUAL_FLAG));
+
+ case SLJIT_SUB:
+ if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2)));
+ src2 = TMP_REG2;
+ flags &= ~SRC2_IMM;
+ }
+
+ is_handled = 0;
+
+ if (flags & SRC2_IMM) {
+ if (GET_FLAG_TYPE(op) == SLJIT_LESS) {
+ FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
+ is_handled = 1;
+ } else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) {
+ FAIL_IF(push_inst(compiler, SLTI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
+ is_handled = 1;
+ }
+ }
+
+ if (!is_handled && GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
+ is_handled = 1;
+
+ if (flags & SRC2_IMM) {
+ reg = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ if (RISCV_HAS_COMPRESSED(200) && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)
+ FAIL_IF(push_inst16(compiler, C_LI | C_RD(reg) | C_IMM_I(src2)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(reg) | RS1(TMP_ZERO) | IMM_I(src2)));
+
+ src2 = reg;
+ flags &= ~SRC2_IMM;
+ }
+
+ switch (GET_FLAG_TYPE(op)) {
+ case SLJIT_LESS:
+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
+ break;
+ case SLJIT_GREATER:
+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src2) | RS2(src1)));
+ break;
+ case SLJIT_SIG_LESS:
+ FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
+ break;
+ case SLJIT_SIG_GREATER:
+ FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src2) | RS2(src1)));
+ break;
+ }
+ }
+
+ if (is_handled) {
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-src2)));
+ if (!(flags & UNUSED_DEST)) {
+ src2 = -src2;
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)
+ return push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2));
+
+ return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2));
+ }
+ } else {
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
+ if (!(flags & UNUSED_DEST)) {
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && C_IS_R3(dst) && C_IS_R3(src2))
+ return push_inst16(compiler, C_SUB_W(WORD) | C_RS1_R3(dst) | C_RS2_R3(src2));
+
+ return push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2));
+ }
+ }
+ return SLJIT_SUCCESS;
+ }
+
+ is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
+ is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;
+
+ if (flags & SRC2_IMM) {
+ if (is_overflow) {
+ if (dst == src1) {
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(OTHER_FLAG) | C_RS2(src1)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(0)));
+ }
+ } else {
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-src2)));
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
+ }
+
+ /* Only the zero flag is needed. */
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) {
+ src2 = -src2;
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)
+ FAIL_IF(push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
+ }
+ } else {
+ if (is_overflow)
+ FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
+ else if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
+
+ if (is_overflow || is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
+
+ /* Only the zero flag is needed. */
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) {
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && C_IS_R3(dst) && C_IS_R3(src2))
+ FAIL_IF(push_inst16(compiler, C_SUB_W(WORD) | C_RS1_R3(dst) | C_RS2_R3(src2)));
+ else
+ FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)));
+ }
+ }
+
+ if (!is_overflow)
+ return SLJIT_SUCCESS;
+
+ if (flags & SRC2_IMM) {
+ if (src2 >= 0)
+ return push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(dst) | RS2(dst == src1 ? OTHER_FLAG : src1));
+ return push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(dst == src1 ? OTHER_FLAG : src1) | RS2(dst));
+ }
+
+ FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RS1(dst) | RS2(EQUAL_FLAG)));
+ if (op & SLJIT_SET_Z) {
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(EQUAL_FLAG) | C_RS2(dst)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0)));
+ }
+ FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_EXTEND(31)));
+ return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG));
+
+ case SLJIT_SUBC:
+ if ((flags & SRC2_IMM) && src2 == SIMM_MIN) {
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG2) | RS1(TMP_ZERO) | IMM_I(src2)));
+ src2 = TMP_REG2;
+ flags &= ~SRC2_IMM;
+ }
+
+ is_carry = GET_FLAG_TYPE(op) == SLJIT_CARRY;
+
+ if (flags & SRC2_IMM) {
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));
+
+ src2 = -src2;
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)
+ FAIL_IF(push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
+ } else {
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
+
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && C_IS_R3(dst) && C_IS_R3(src2))
+ FAIL_IF(push_inst16(compiler, C_SUB_W(WORD) | C_RS1_R3(dst) | C_RS2_R3(src2)));
+ else
+ FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)));
+ }
+
+ if (is_carry)
+ FAIL_IF(push_inst(compiler, SLTU | RD(TMP_REG1) | RS1(dst) | RS2(OTHER_FLAG)));
+
+ FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
+
+ if (!is_carry)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, OR | RD(OTHER_FLAG) | RS1(EQUAL_FLAG) | RS2(TMP_REG1));
+
+ case SLJIT_MUL:
+ SLJIT_ASSERT(!(flags & SRC2_IMM));
+
+ if (GET_FLAG_TYPE(op) != SLJIT_OVERFLOW)
+ return push_inst(compiler, MUL | WORD | RD(dst) | RS1(src1) | RS2(src2));
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ if (word) {
+ FAIL_IF(push_inst(compiler, MUL | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
+ FAIL_IF(push_inst(compiler, MUL | 0x8 | RD(dst) | RS1(src1) | RS2(src2)));
+ return push_inst(compiler, SUB | RD(OTHER_FLAG) | RS1(dst) | RS2(OTHER_FLAG));
+ }
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ FAIL_IF(push_inst(compiler, MULH | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
+ FAIL_IF(push_inst(compiler, MUL | RD(dst) | RS1(src1) | RS2(src2)));
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ FAIL_IF(push_inst(compiler, SRAI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(31)));
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ FAIL_IF(push_inst(compiler, SRAI | RD(OTHER_FLAG) | RS1(dst) | IMM_I(63)));
+#endif /* SLJIT_CONFIG_RISCV_32 */
+ return push_inst(compiler, SUB | RD(OTHER_FLAG) | RS1(EQUAL_FLAG) | RS2(OTHER_FLAG));
+
+ case SLJIT_AND:
+ EMIT_LOGICAL(ANDI, C_ANDI, AND, C_AND);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_OR:
+ EMIT_LOGICAL(ORI, 0, OR, C_OR);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_XOR:
+ EMIT_LOGICAL(XORI, 0, XOR, C_XOR);
+ return SLJIT_SUCCESS;
+
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ op_imm = SLLI;
+ op_reg = SLL;
+ break;
+
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ op_imm = SRLI;
+ op_reg = SRL;
+ break;
+
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ op_imm = SRAI;
+ op_reg = SRA;
+ break;
+
+ case SLJIT_ROTL:
+ case SLJIT_ROTR:
+ if (flags & SRC2_IMM) {
+ SLJIT_ASSERT(src2 != 0);
+
+ if (RISCV_HAS_BITMANIP_B(93)) {
+ if (GET_OPCODE(op) == SLJIT_ROTL) {
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ src2 = ((op & SLJIT_32) ? 32 : 64) - src2;
+#else /* !SLJIT_CONFIG_RISCV_64 */
+ src2 = 32 - src2;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ }
+ return push_inst(compiler, RORI | WORD | RD(dst) | RS1(src1) | IMM_I(src2));
+ }
+
+ op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLI : SRLI;
+ FAIL_IF(push_inst(compiler, op_imm | WORD | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ src2 = ((op & SLJIT_32) ? 32 : 64) - src2;
+#else /* !SLJIT_CONFIG_RISCV_64 */
+ src2 = 32 - src2;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLI : SLLI;
+ FAIL_IF(push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
+ return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG));
+ }
+
+ if (RISCV_HAS_BITMANIP_B(93))
+ return push_inst(compiler, (GET_OPCODE(op) == SLJIT_ROTL ? ROL : ROR) | WORD | RD(dst) | RS1(src1) | RS2(src2));
+
+ if (src2 == TMP_ZERO) {
+ if (dst != src1)
+ return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(0));
+ return SLJIT_SUCCESS;
+ }
+
+ FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(TMP_ZERO) | RS2(src2)));
+ op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SLL : SRL;
+ FAIL_IF(push_inst(compiler, op_reg | WORD | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
+ op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL;
+ FAIL_IF(push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(EQUAL_FLAG)));
+ return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG));
+ default:
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
+ }
+
+ if (flags & SRC2_IMM) {
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, op_imm | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));
+
+ if (flags & UNUSED_DEST)
+ return SLJIT_SUCCESS;
+
+ if (RISCV_HAS_COMPRESSED(200) && WORD == 0 && dst == src1) {
+ if (op_imm == SLLI)
+ return push_inst16(compiler, C_SLLI | C_RD(dst) | C_IMM_I(src2));
+
+ if (C_IS_R3(dst))
+ return push_inst16(compiler, (op_imm == SRLI ? C_SRLI : C_SRAI) | C_RS1_R3(dst) | C_IMM_I(src2));
+ }
+
+ return push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2));
+ }
+
+ if (op & SLJIT_SET_Z)
+ FAIL_IF(push_inst(compiler, op_reg | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
+
+ if (flags & UNUSED_DEST)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(src2));
+}
+
+#undef IMM_EXTEND
+
+static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ /* arg1 goes to TMP_REG1 or src reg
+ arg2 goes to TMP_REG2, imm or src reg
+ TMP_REG3 can be used for caching
+ result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */
+ sljit_s32 dst_r = TMP_REG2;
+ sljit_s32 src1_r;
+ sljit_sw src2_r = 0;
+ sljit_s32 src2_tmp_reg = (GET_OPCODE(op) >= SLJIT_OP2_BASE && FAST_IS_REG(src1)) ? TMP_REG1 : TMP_REG2;
+
+ if (!(flags & ALT_KEEP_CACHE)) {
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+ }
+
+ if (dst == 0) {
+ SLJIT_ASSERT(HAS_FLAGS(op));
+ flags |= UNUSED_DEST;
+ dst = TMP_REG2;
+ }
+ else if (FAST_IS_REG(dst)) {
+ dst_r = dst;
+ flags |= REG_DEST;
+ if (flags & MOVE_OP)
+ src2_tmp_reg = dst_r;
+ }
+ else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))
+ flags |= SLOW_DEST;
+
+ if (flags & IMM_OP) {
+ if (src2 == SLJIT_IMM && src2w != 0 && src2w <= SIMM_MAX && src2w >= SIMM_MIN) {
+ flags |= SRC2_IMM;
+ src2_r = src2w;
+ }
+ else if ((flags & CUMULATIVE_OP) && src1 == SLJIT_IMM && src1w != 0 && src1w <= SIMM_MAX && src1w >= SIMM_MIN) {
+ flags |= SRC2_IMM;
+ src2_r = src1w;
+
+ /* And swap arguments. */
+ src1 = src2;
+ src1w = src2w;
+ src2 = SLJIT_IMM;
+ /* src2w = src2_r unneeded. */
+ }
+ }
+
+ /* Source 1. */
+ if (FAST_IS_REG(src1)) {
+ src1_r = src1;
+ flags |= REG1_SOURCE;
+ } else if (src1 == SLJIT_IMM) {
+ if (src1w) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));
+ src1_r = TMP_REG1;
+ }
+ else
+ src1_r = TMP_ZERO;
+ } else {
+ if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w))
+ FAIL_IF(compiler->error);
+ else
+ flags |= SLOW_SRC1;
+ src1_r = TMP_REG1;
+ }
+
+ /* Source 2. */
+ if (FAST_IS_REG(src2)) {
+ src2_r = src2;
+ flags |= REG2_SOURCE;
+ if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)
+ dst_r = (sljit_s32)src2_r;
+ } else if (src2 == SLJIT_IMM) {
+ if (!(flags & SRC2_IMM)) {
+ if (src2w) {
+ FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w, TMP_REG3));
+ src2_r = src2_tmp_reg;
+ } else {
+ src2_r = TMP_ZERO;
+ if (flags & MOVE_OP) {
+ if (dst & SLJIT_MEM)
+ dst_r = 0;
+ else
+ op = SLJIT_MOV;
+ }
+ }
+ }
+ } else {
+ if (getput_arg_fast(compiler, flags | LOAD_DATA, src2_tmp_reg, src2, src2w))
+ FAIL_IF(compiler->error);
+ else
+ flags |= SLOW_SRC2;
+ src2_r = src2_tmp_reg;
+ }
+
+ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
+ SLJIT_ASSERT(src2_r == TMP_REG2);
+ if ((flags & SLOW_DEST) && !can_cache(src2, src2w, src1, src1w) && can_cache(src2, src2w, dst, dstw)) {
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, src2, src2w));
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA | MEM_USE_TMP2, TMP_REG2, src2, src2w, dst, dstw));
+ } else {
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+ }
+ }
+ else if (flags & SLOW_SRC1)
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+ else if (flags & SLOW_SRC2)
+ FAIL_IF(getput_arg(compiler, flags | LOAD_DATA | ((src1_r == TMP_REG1) ? MEM_USE_TMP2 : 0), src2_tmp_reg, src2, src2w, dst, dstw));
+
+ FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r));
+
+ if (dst & SLJIT_MEM) {
+ if (!(flags & SLOW_DEST)) {
+ getput_arg_fast(compiler, flags, dst_r, dst, dstw);
+ return compiler->error;
+ }
+ return getput_arg(compiler, flags, dst_r, dst, dstw, 0, 0);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
+{
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
+
+ SLJIT_ASSERT(word == 0 || word == 0x8);
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op0(compiler, op));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_BREAKPOINT:
+ if (RISCV_HAS_COMPRESSED(200))
+ return push_inst16(compiler, C_EBREAK);
+ return push_inst(compiler, EBREAK);
+ case SLJIT_NOP:
+ if (RISCV_HAS_COMPRESSED(200))
+ return push_inst16(compiler, C_NOP);
+ return push_inst(compiler, NOP);
+ case SLJIT_LMUL_UW:
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R1) | IMM_I(0)));
+ FAIL_IF(push_inst(compiler, MULHU | RD(SLJIT_R1) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));
+ return push_inst(compiler, MUL | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(TMP_REG1));
+ case SLJIT_LMUL_SW:
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R1) | IMM_I(0)));
+ FAIL_IF(push_inst(compiler, MULH | RD(SLJIT_R1) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));
+ return push_inst(compiler, MUL | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(TMP_REG1));
+ case SLJIT_DIVMOD_UW:
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R0) | IMM_I(0)));
+ FAIL_IF(push_inst(compiler, DIVU | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));
+ return push_inst(compiler, REMU | WORD | RD(SLJIT_R1) | RS1(TMP_REG1) | RS2(SLJIT_R1));
+ case SLJIT_DIVMOD_SW:
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R0) | IMM_I(0)));
+ FAIL_IF(push_inst(compiler, DIV | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));
+ return push_inst(compiler, REM | WORD | RD(SLJIT_R1) | RS1(TMP_REG1) | RS2(SLJIT_R1));
+ case SLJIT_DIV_UW:
+ return push_inst(compiler, DIVU | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1));
+ case SLJIT_DIV_SW:
+ return push_inst(compiler, DIV | WORD | RD(SLJIT_R0) | RS1(SLJIT_R0) | RS2(SLJIT_R1));
+ case SLJIT_MEMORY_BARRIER:
+ return push_inst(compiler, FENCE | 0x0ff00000);
+ case SLJIT_ENDBR:
+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
+ return SLJIT_SUCCESS;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 flags = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ if (op & SLJIT_32)
+ flags = INT_DATA | SIGNED_DATA;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+#endif /* SLJIT_CONFIG_RISCV_32 */
+ case SLJIT_MOV_P:
+ return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, srcw);
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ case SLJIT_MOV_U32:
+ return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u32)srcw : srcw);
+
+ case SLJIT_MOV_S32:
+ /* Logical operators have no W variant, so sign extended input is necessary for them. */
+ case SLJIT_MOV32:
+ return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s32)srcw : srcw);
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ case SLJIT_MOV_U8:
+ return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u8)srcw : srcw);
+
+ case SLJIT_MOV_S8:
+ return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s8)srcw : srcw);
+
+ case SLJIT_MOV_U16:
+ return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_u16)srcw : srcw);
+
+ case SLJIT_MOV_S16:
+ return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_ZERO, 0, src, (src == SLJIT_IMM) ? (sljit_s16)srcw : srcw);
+
+ case SLJIT_CLZ:
+ case SLJIT_CTZ:
+ case SLJIT_REV:
+ return emit_op(compiler, op, flags, dst, dstw, TMP_ZERO, 0, src, srcw);
+
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+ return emit_op(compiler, op, HALF_DATA, dst, dstw, TMP_ZERO, 0, src, srcw);
+
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+ return emit_op(compiler, op | SLJIT_32, INT_DATA, dst, dstw, TMP_ZERO, 0, src, srcw);
+ }
+
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 flags = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ if (op & SLJIT_32) {
+ flags |= INT_DATA | SIGNED_DATA;
+ if (src1 == SLJIT_IMM)
+ src1w = (sljit_s32)src1w;
+ if (src2 == SLJIT_IMM)
+ src2w = (sljit_s32)src2w;
+ }
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD:
+ case SLJIT_ADDC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_SUB:
+ case SLJIT_SUBC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_MUL:
+ compiler->status_flags_state = 0;
+ return emit_op(compiler, op, flags | CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_AND:
+ case SLJIT_OR:
+ case SLJIT_XOR:
+ return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ case SLJIT_ROTL:
+ case SLJIT_ROTR:
+ if (src2 == SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ src2w &= 0x1f;
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ if (op & SLJIT_32)
+ src2w &= 0x1f;
+ else
+ src2w &= 0x3f;
+#endif /* SLJIT_CONFIG_RISCV_32 */
+ }
+
+ return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ SLJIT_UNREACHABLE();
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, op, 0, 0, src1, src1w, src2, src2w);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
+
+ SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MULADD:
+ SLJIT_SKIP_CHECKS(compiler);
+ FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), TMP_REG2, 0, src1, src1w, src2, src2w));
+ return push_inst(compiler, ADD | WORD | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG2));
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1_reg,
+ sljit_s32 src2_reg,
+ sljit_s32 src3, sljit_sw src3w)
+{
+ sljit_s32 is_left;
+ sljit_ins ins1, ins2, ins3;
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ sljit_ins word = (sljit_ins)(op & SLJIT_32) >> 5;
+ sljit_s32 inp_flags = ((op & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
+ sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;
+#else /* !SLJIT_CONFIG_RISCV_64 */
+ sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
+ sljit_sw bit_length = 32;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
+
+ is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);
+
+ if (src1_reg == src2_reg) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, (is_left ? SLJIT_ROTL : SLJIT_ROTR) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);
+ }
+
+ ADJUST_LOCAL_OFFSET(src3, src3w);
+
+ if (src3 == SLJIT_IMM) {
+ src3w &= bit_length - 1;
+
+ if (src3w == 0)
+ return SLJIT_SUCCESS;
+
+ if (is_left) {
+ ins1 = SLLI | WORD | IMM_I(src3w);
+ src3w = bit_length - src3w;
+ ins2 = SRLI | WORD | IMM_I(src3w);
+ } else {
+ ins1 = SRLI | WORD | IMM_I(src3w);
+ src3w = bit_length - src3w;
+ ins2 = SLLI | WORD | IMM_I(src3w);
+ }
+
+ FAIL_IF(push_inst(compiler, ins1 | RD(dst_reg) | RS1(src1_reg)));
+ FAIL_IF(push_inst(compiler, ins2 | RD(TMP_REG1) | RS1(src2_reg)));
+ return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));
+ }
+
+ if (src3 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG2, src3, src3w));
+ src3 = TMP_REG2;
+ } else if (dst_reg == src3) {
+ push_inst(compiler, ADDI | WORD | RD(TMP_REG2) | RS1(src3) | IMM_I(0));
+ src3 = TMP_REG2;
+ }
+
+ if (is_left) {
+ ins1 = SLL;
+ ins2 = SRLI;
+ ins3 = SRL;
+ } else {
+ ins1 = SRL;
+ ins2 = SLLI;
+ ins3 = SLL;
+ }
+
+ FAIL_IF(push_inst(compiler, ins1 | WORD | RD(dst_reg) | RS1(src1_reg) | RS2(src3)));
+
+ if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {
+ FAIL_IF(push_inst(compiler, ins2 | WORD | RD(TMP_REG1) | RS1(src2_reg) | IMM_I(1)));
+ FAIL_IF(push_inst(compiler, XORI | RD(TMP_REG2) | RS1(src3) | IMM_I((sljit_ins)bit_length - 1)));
+ src2_reg = TMP_REG1;
+ } else
+ FAIL_IF(push_inst(compiler, SUB | WORD | RD(TMP_REG2) | RS1(TMP_ZERO) | RS2(src3)));
+
+ FAIL_IF(push_inst(compiler, ins3 | WORD | RD(TMP_REG1) | RS1(src2_reg) | RS2(TMP_REG2)));
+ return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r, tmp_r;
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);
+
+ if (src2 == SLJIT_IMM) {
+ src2w = (sljit_sw)((sljit_uw)src2w << shift_arg);
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
+ src2 = TMP_REG2;
+ }
+
+ if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));
+ src1 = TMP_REG1;
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+ src1 = TMP_REG1;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ ins = 0;
+
+ if (RISCV_HAS_BITMANIP_A(93)) {
+ switch (shift_arg) {
+ case 1:
+ ins = SH1ADD;
+ break;
+ case 2:
+ ins = SH2ADD;
+ break;
+ case 3:
+ ins = SH3ADD;
+ break;
+ }
+ }
+
+ if (ins == 0) {
+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(src2) | IMM_I(shift_arg)));
+ FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RS1(src1) | RS2(tmp_r)));
+ } else {
+ FAIL_IF(push_inst(compiler, ins | RD(dst_r) | RS1(src2) | RS2(src1)));
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, WORD_DATA, dst_r, dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ switch (op) {
+ case SLJIT_FAST_RETURN:
+ if (FAST_IS_REG(src)) {
+ if (src != RETURN_ADDR_REG)
+ FAIL_IF(push_inst(compiler, ADDI | RD(RETURN_ADDR_REG) | RS1(src) | IMM_I(0)));
+ } else
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
+
+ return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0));
+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
+ return SLJIT_SUCCESS;
+ case SLJIT_PREFETCH_L1:
+ case SLJIT_PREFETCH_L2:
+ case SLJIT_PREFETCH_L3:
+ case SLJIT_PREFETCH_ONCE:
+ return SLJIT_SUCCESS;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ switch (op) {
+ case SLJIT_FAST_ENTER:
+ if (FAST_IS_REG(dst)) {
+ if (dst == RETURN_ADDR_REG)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, ADDI | RD(dst) | RS1(RETURN_ADDR_REG) | IMM_I(0));
+ }
+
+ SLJIT_ASSERT(RETURN_ADDR_REG == TMP_REG2);
+ break;
+ case SLJIT_GET_RETURN_ADDRESS:
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size - SSIZE_OF(sw)));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
+{
+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
+
+ if (type == SLJIT_GP_REGISTER)
+ return reg_map[reg];
+
+ if (type == SLJIT_FLOAT_REGISTER)
+ return freg_map[reg];
+
+ return vreg_map[reg];
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_u32 size)
+{
+ SLJIT_UNUSED_ARG(size);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
+
+ if (size == 2)
+ return push_inst16(compiler, *(sljit_u16*)instruction);
+
+ return push_inst(compiler, *(sljit_ins*)instruction);
+}
+
+/* --------------------------------------------------------------------- */
+/* Floating point operators */
+/* --------------------------------------------------------------------- */
+
+#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))
+#define FMT(op) ((sljit_ins)((op & SLJIT_32) ^ SLJIT_32) << 17)
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+# define flags (sljit_u32)0
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;
+#endif /* SLJIT_CONFIG_RISCV_32 */
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src, srcw, dst, dstw));
+ src = TMP_FREG1;
+ }
+
+ FAIL_IF(push_inst(compiler, FCVT_W_S | FMT(op) | flags | RD(dst_r) | FRS1(src)));
+
+ /* Store the integer value from a VFP register. */
+ if (dst & SLJIT_MEM) {
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ return emit_op_mem2(compiler, WORD_DATA, TMP_REG2, dst, dstw, 0, 0);
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ return emit_op_mem2(compiler, flags ? WORD_DATA : INT_DATA, TMP_REG2, dst, dstw, 0, 0);
+#endif /* SLJIT_CONFIG_RISCV_32 */
+ }
+ return SLJIT_SUCCESS;
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+# undef flags
+#endif /* SLJIT_CONFIG_RISCV_32 */
+}
+
+static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (src & SLJIT_MEM) {
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
+#else /* SLJIT_CONFIG_RISCV_32 */
+ FAIL_IF(emit_op_mem2(compiler, ((ins & (1 << 21)) ? WORD_DATA : INT_DATA) | LOAD_DATA, TMP_REG1, src, srcw, dst, dstw));
+#endif /* !SLJIT_CONFIG_RISCV_32 */
+ src = TMP_REG1;
+ } else if (src == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw, TMP_REG3));
+ src = TMP_REG1;
+ }
+
+ FAIL_IF(push_inst(compiler, ins | FRD(dst_r) | RS1(src)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, DOUBLE_DATA | ((sljit_s32)(~ins >> 24) & 0x2), TMP_FREG1, dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins ins = FCVT_S_W | FMT(op);
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ if (op & SLJIT_32)
+ ins |= F3(0x7);
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)
+ ins |= (1 << 21);
+ else if (src == SLJIT_IMM)
+ srcw = (sljit_s32)srcw;
+
+ if (op != SLJIT_CONV_F64_FROM_S32)
+ ins |= F3(0x7);
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+ return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw);
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins ins = FCVT_S_WU | FMT(op);
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ if (op & SLJIT_32)
+ ins |= F3(0x7);
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW)
+ ins |= (1 << 21);
+ else if (src == SLJIT_IMM)
+ srcw = (sljit_u32)srcw;
+
+ if (op != SLJIT_CONV_F64_FROM_S32)
+ ins |= F3(0x7);
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+ return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw);
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_ins inst;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
+ src1 = TMP_FREG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, 0, 0));
+ src2 = TMP_FREG2;
+ }
+
+ switch (GET_FLAG_TYPE(op)) {
+ case SLJIT_F_EQUAL:
+ case SLJIT_ORDERED_EQUAL:
+ inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);
+ break;
+ case SLJIT_F_LESS:
+ case SLJIT_ORDERED_LESS:
+ inst = FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);
+ break;
+ case SLJIT_ORDERED_GREATER:
+ inst = FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1);
+ break;
+ case SLJIT_F_GREATER:
+ case SLJIT_UNORDERED_OR_GREATER:
+ inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2);
+ break;
+ case SLJIT_UNORDERED_OR_LESS:
+ inst = FLE_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src2) | FRS2(src1);
+ break;
+ case SLJIT_UNORDERED_OR_EQUAL:
+ FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src2)));
+ FAIL_IF(push_inst(compiler, FLT_S | FMT(op) | RD(TMP_REG1) | FRS1(src2) | FRS2(src1)));
+ inst = OR | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1);
+ break;
+ default: /* SLJIT_UNORDERED */
+ if (src1 == src2) {
+ inst = FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src1);
+ break;
+ }
+ FAIL_IF(push_inst(compiler, FEQ_S | FMT(op) | RD(OTHER_FLAG) | FRS1(src1) | FRS2(src1)));
+ FAIL_IF(push_inst(compiler, FEQ_S | FMT(op) | RD(TMP_REG1) | FRS1(src2) | FRS2(src2)));
+ inst = AND | RD(OTHER_FLAG) | RS1(OTHER_FLAG) | RS2(TMP_REG1);
+ break;
+ }
+
+ return push_inst(compiler, inst);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
+
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
+ op ^= SLJIT_32;
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op) | LOAD_DATA, dst_r, src, srcw, dst, dstw));
+ src = dst_r;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_F64:
+ if (src != dst_r) {
+ if (!(dst & SLJIT_MEM))
+ FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));
+ else
+ dst_r = src;
+ }
+ break;
+ case SLJIT_NEG_F64:
+ FAIL_IF(push_inst(compiler, FSGNJN_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));
+ break;
+ case SLJIT_ABS_F64:
+ FAIL_IF(push_inst(compiler, FSGNJX_S | FMT(op) | FRD(dst_r) | FRS1(src) | FRS2(src)));
+ break;
+ case SLJIT_CONV_F64_FROM_F32:
+ /* The SLJIT_32 bit is inverted because sljit_f32 needs to be loaded from the memory. */
+ FAIL_IF(push_inst(compiler, FCVT_S_D | ((op & SLJIT_32) ? (1 << 25) : ((1 << 20) | F3(7))) | FRD(dst_r) | FRS1(src)));
+ op ^= SLJIT_32;
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, FLOAT_DATA(op), dst_r, dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 dst_r, flags = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG2;
+
+ if (src1 & SLJIT_MEM) {
+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w)) {
+ FAIL_IF(compiler->error);
+ src1 = TMP_FREG1;
+ } else
+ flags |= SLOW_SRC1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ if (getput_arg_fast(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w)) {
+ FAIL_IF(compiler->error);
+ src2 = TMP_FREG2;
+ } else
+ flags |= SLOW_SRC2;
+ }
+
+ if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) {
+ if ((dst & SLJIT_MEM) && !can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) {
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, src1, src1w));
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
+ } else {
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, src2, src2w));
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
+ }
+ }
+ else if (flags & SLOW_SRC1)
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG1, src1, src1w, dst, dstw));
+ else if (flags & SLOW_SRC2)
+ FAIL_IF(getput_arg(compiler, FLOAT_DATA(op) | LOAD_DATA, TMP_FREG2, src2, src2w, dst, dstw));
+
+ if (flags & SLOW_SRC1)
+ src1 = TMP_FREG1;
+ if (flags & SLOW_SRC2)
+ src2 = TMP_FREG2;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD_F64:
+ FAIL_IF(push_inst(compiler, FADD_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
+ break;
+
+ case SLJIT_SUB_F64:
+ FAIL_IF(push_inst(compiler, FSUB_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
+ break;
+
+ case SLJIT_MUL_F64:
+ FAIL_IF(push_inst(compiler, FMUL_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
+ break;
+
+ case SLJIT_DIV_F64:
+ FAIL_IF(push_inst(compiler, FDIV_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2)));
+ break;
+
+ case SLJIT_COPYSIGN_F64:
+ return push_inst(compiler, FSGNJ_S | FMT(op) | FRD(dst_r) | FRS1(src1) | FRS2(src2));
+ }
+
+ if (dst_r != dst)
+ FAIL_IF(emit_op_mem2(compiler, FLOAT_DATA(op), TMP_FREG2, dst, dstw, 0, 0));
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f32 value)
+{
+ union {
+ sljit_s32 imm;
+ sljit_f32 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset32(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm == 0)
+ return push_inst(compiler, FMV_W_X | RS1(TMP_ZERO) | FRD(freg));
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm, TMP_REG3));
+ return push_inst(compiler, FMV_W_X | RS1(TMP_REG1) | FRD(freg));
+}
+
+/* --------------------------------------------------------------------- */
+/* Conditional instructions */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_label(compiler));
+
+ if (compiler->last_label && compiler->last_label->size == compiler->size)
+ return compiler->last_label;
+
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+ PTR_FAIL_IF(!label);
+ set_label(label, compiler);
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask = 0, i;
+ struct sljit_label *label = NULL;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (RISCV_HAS_COMPRESSED(200)) {
+ if (alignment <= SLJIT_LABEL_ALIGN_2) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_u16);
+
+ for (i = (mask >> 1); i != 0; i--)
+ PTR_FAIL_IF(push_inst16(compiler, C_NOP));
+ }
+ } else {
+ if (alignment <= SLJIT_LABEL_ALIGN_4) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);
+
+ for (i = (mask >> 2); i != 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+ }
+ }
+
+ if (label == NULL) {
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ if (RISCV_HAS_COMPRESSED(200)) {
+ for (i = (buffers->size + 1) >> 1; i > 0; i--)
+ PTR_FAIL_IF(push_inst16(compiler, C_NOP));
+ } else {
+ for (i = (buffers->size + 3) >> 2; i > 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+ }
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
+static sljit_ins get_jump_instruction(sljit_s32 type)
+{
+ switch (type) {
+ case SLJIT_EQUAL:
+ return BNE | RS1(EQUAL_FLAG) | RS2(TMP_ZERO);
+ case SLJIT_NOT_EQUAL:
+ return BEQ | RS1(EQUAL_FLAG) | RS2(TMP_ZERO);
+ case SLJIT_LESS:
+ case SLJIT_GREATER:
+ case SLJIT_SIG_LESS:
+ case SLJIT_SIG_GREATER:
+ case SLJIT_OVERFLOW:
+ case SLJIT_CARRY:
+ case SLJIT_ATOMIC_NOT_STORED:
+ case SLJIT_F_EQUAL:
+ case SLJIT_ORDERED_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ case SLJIT_F_LESS:
+ case SLJIT_ORDERED_LESS:
+ case SLJIT_ORDERED_GREATER:
+ case SLJIT_F_LESS_EQUAL:
+ case SLJIT_ORDERED_LESS_EQUAL:
+ case SLJIT_ORDERED_GREATER_EQUAL:
+ case SLJIT_ORDERED:
+ return BEQ | RS1(OTHER_FLAG) | RS2(TMP_ZERO);
+ break;
+ case SLJIT_GREATER_EQUAL:
+ case SLJIT_LESS_EQUAL:
+ case SLJIT_SIG_GREATER_EQUAL:
+ case SLJIT_SIG_LESS_EQUAL:
+ case SLJIT_NOT_OVERFLOW:
+ case SLJIT_NOT_CARRY:
+ case SLJIT_ATOMIC_STORED:
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_EQUAL:
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:
+ case SLJIT_UNORDERED_OR_LESS_EQUAL:
+ case SLJIT_F_GREATER:
+ case SLJIT_UNORDERED_OR_GREATER:
+ case SLJIT_UNORDERED_OR_LESS:
+ case SLJIT_UNORDERED:
+ return BNE | RS1(OTHER_FLAG) | RS2(TMP_ZERO);
+ default:
+ /* Not conditional branch. */
+ return 0;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
+{
+ struct sljit_jump *jump;
+ sljit_ins inst;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_jump(compiler, type));
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ type &= 0xff;
+
+ inst = get_jump_instruction(type);
+
+ if (inst != 0) {
+ PTR_FAIL_IF(push_inst(compiler, inst | BRANCH_LENGTH));
+ jump->flags |= IS_COND;
+ }
+
+ jump->addr = compiler->size;
+
+ if (type >= SLJIT_FAST_CALL)
+ jump->flags |= IS_CALL;
+
+ PTR_FAIL_IF(push_inst16(compiler, 0));
+
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += JUMP_MAX_SIZE - 1;
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types)
+{
+ SLJIT_UNUSED_ARG(arg_types);
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
+
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_jump(compiler, type);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ struct sljit_jump *jump;
+ sljit_s32 flags;
+ sljit_ins inst;
+ sljit_s32 src2_tmp_reg = FAST_IS_REG(src1) ? TMP_REG1 : TMP_REG2;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_cmp(compiler, type, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ flags = WORD_DATA | LOAD_DATA;
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+ if (src1 & SLJIT_MEM) {
+ PTR_FAIL_IF(emit_op_mem2(compiler, flags, TMP_REG1, src1, src1w, src2, src2w));
+ src1 = TMP_REG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ PTR_FAIL_IF(emit_op_mem2(compiler, flags | (src1 == TMP_REG1 ? MEM_USE_TMP2 : 0), src2_tmp_reg, src2, src2w, 0, 0));
+ src2 = src2_tmp_reg;
+ }
+
+ if (src1 == SLJIT_IMM) {
+ if (src1w != 0) {
+ PTR_FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));
+ src1 = TMP_REG1;
+ }
+ else
+ src1 = TMP_ZERO;
+ }
+
+ if (src2 == SLJIT_IMM) {
+ if (src2w != 0) {
+ PTR_FAIL_IF(load_immediate(compiler, src2_tmp_reg, src2w, TMP_REG3));
+ src2 = src2_tmp_reg;
+ }
+ else
+ src2 = TMP_ZERO;
+ }
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | IS_COND));
+ type &= 0xff;
+
+ switch (type) {
+ case SLJIT_EQUAL:
+ if (RISCV_HAS_COMPRESSED(200)) {
+ if (src1 == TMP_ZERO && C_IS_R3(src2)) {
+ inst = C_BNEZ | C_RS1_R3(src2) | BRANCH16_LENGTH;
+ jump->flags |= IS_COND16;
+ break;
+ }
+
+ if (src2 == TMP_ZERO && C_IS_R3(src1)) {
+ inst = C_BNEZ | C_RS1_R3(src1) | BRANCH16_LENGTH;
+ jump->flags |= IS_COND16;
+ break;
+ }
+ }
+
+ inst = BNE | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
+ break;
+ case SLJIT_NOT_EQUAL:
+ if (RISCV_HAS_COMPRESSED(200)) {
+ if (src1 == TMP_ZERO && C_IS_R3(src2)) {
+ inst = C_BEQZ | C_RS1_R3(src2) | BRANCH16_LENGTH;
+ jump->flags |= IS_COND16;
+ break;
+ }
+
+ if (src2 == TMP_ZERO && C_IS_R3(src1)) {
+ inst = C_BEQZ | C_RS1_R3(src1) | BRANCH16_LENGTH;
+ jump->flags |= IS_COND16;
+ break;
+ }
+ }
+
+ inst = BEQ | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
+ break;
+ case SLJIT_LESS:
+ inst = BGEU | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
+ break;
+ case SLJIT_GREATER_EQUAL:
+ inst = BLTU | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
+ break;
+ case SLJIT_GREATER:
+ inst = BGEU | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
+ break;
+ case SLJIT_LESS_EQUAL:
+ inst = BLTU | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
+ break;
+ case SLJIT_SIG_LESS:
+ inst = BGE | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
+ break;
+ case SLJIT_SIG_GREATER_EQUAL:
+ inst = BLT | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
+ break;
+ case SLJIT_SIG_GREATER:
+ inst = BGE | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
+ break;
+ default: /* SLJIT_SIG_LESS_EQUAL */
+ inst = BLT | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
+ break;
+ }
+
+ SLJIT_COMPILE_ASSERT((C_BEQZ & 0x2) == 0 && (C_BNEZ & 0x2) == 0, branch16_bit_error);
+ if (RISCV_COMPRESSED_CHECK((inst & 0x2) == 0))
+ PTR_FAIL_IF(push_inst16(compiler, (sljit_u16)inst));
+ else
+ PTR_FAIL_IF(push_inst(compiler, inst));
+
+ jump->addr = compiler->size;
+ PTR_FAIL_IF(push_inst16(compiler, 0));
+
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += JUMP_MAX_SIZE - 1;
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
+{
+ struct sljit_jump *jump;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
+
+ if (src != SLJIT_IMM) {
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
+ src = TMP_REG1;
+ }
+
+ if (RISCV_HAS_COMPRESSED(200))
+ return push_inst16(compiler, ((type >= SLJIT_FAST_CALL) ? C_JALR : C_JR) | C_RD(src));
+
+ return push_inst(compiler, JALR | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RS1(src) | IMM_I(0));
+ }
+
+ /* These jumps are converted to jump/call instructions when possible. */
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF(!jump);
+ set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_CALL : 0));
+ jump->u.target = (sljit_uw)srcw;
+
+ jump->addr = compiler->size;
+ FAIL_IF(push_inst16(compiler, 0));
+
+ /* Maximum number of instructions required for generating a constant. */
+ compiler->size += JUMP_MAX_SIZE - 1;
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types,
+ sljit_s32 src, sljit_sw srcw)
+{
+ SLJIT_UNUSED_ARG(arg_types);
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
+ src = TMP_REG1;
+ }
+
+ if (type & SLJIT_CALL_RETURN) {
+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src) | IMM_I(0)));
+ src = TMP_REG1;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 0));
+ type = SLJIT_JUMP;
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, type, src, srcw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 type)
+{
+ sljit_s32 src_r, dst_r, invert;
+ sljit_s32 saved_op = op;
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ sljit_s32 mem_type = WORD_DATA;
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ op = GET_OPCODE(op);
+ dst_r = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
+
+ compiler->cache_arg = 0;
+ compiler->cache_argw = 0;
+
+ if (op >= SLJIT_ADD && (dst & SLJIT_MEM))
+ FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1, dst, dstw, dst, dstw));
+
+ if (type < SLJIT_F_EQUAL) {
+ src_r = OTHER_FLAG;
+ invert = type & 0x1;
+
+ switch (type) {
+ case SLJIT_EQUAL:
+ case SLJIT_NOT_EQUAL:
+ FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RS1(EQUAL_FLAG) | IMM_I(1)));
+ src_r = dst_r;
+ break;
+ case SLJIT_OVERFLOW:
+ case SLJIT_NOT_OVERFLOW:
+ if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {
+ src_r = OTHER_FLAG;
+ break;
+ }
+ FAIL_IF(push_inst(compiler, SLTUI | RD(dst_r) | RS1(OTHER_FLAG) | IMM_I(1)));
+ src_r = dst_r;
+ invert ^= 0x1;
+ break;
+ case SLJIT_ATOMIC_STORED:
+ case SLJIT_ATOMIC_NOT_STORED:
+ invert ^= 0x1;
+ break;
+ }
+ } else {
+ invert = 0;
+ src_r = OTHER_FLAG;
+
+ switch (type) {
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_NOT_EQUAL:
+ case SLJIT_UNORDERED_OR_EQUAL: /* Not supported. */
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:
+ case SLJIT_UNORDERED_OR_LESS_EQUAL:
+ case SLJIT_F_GREATER:
+ case SLJIT_UNORDERED_OR_GREATER:
+ case SLJIT_UNORDERED_OR_LESS:
+ case SLJIT_UNORDERED:
+ invert = 1;
+ break;
+ }
+ }
+
+ if (invert) {
+ FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(src_r) | IMM_I(1)));
+ src_r = dst_r;
+ }
+
+ if (op < SLJIT_ADD) {
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, mem_type, src_r, dst, dstw);
+
+ if (src_r != dst_r)
+ return push_inst(compiler, ADDI | RD(dst_r) | RS1(src_r) | IMM_I(0));
+ return SLJIT_SUCCESS;
+ }
+
+ mem_type |= CUMULATIVE_OP | IMM_OP | ALT_KEEP_CACHE;
+
+ if (dst & SLJIT_MEM)
+ return emit_op(compiler, saved_op, mem_type, dst, dstw, TMP_REG1, 0, src_r, 0);
+ return emit_op(compiler, saved_op, mem_type, dst, dstw, dst, dstw, src_r, 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_reg)
+{
+ sljit_u16 *ptr;
+ sljit_uw size;
+ sljit_ins ins;
+ sljit_s32 cond_is_1;
+ sljit_s32 is_compare = (type & SLJIT_COMPARE_SELECT);
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ sljit_ins word = (sljit_ins)(type & SLJIT_32) >> 5;
+ sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
+#else /* !SLJIT_CONFIG_RISCV_64 */
+ sljit_s32 inp_flags = WORD_DATA | LOAD_DATA;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ SLJIT_ASSERT(WORD == 0 || WORD == 0x8);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ if (src1 == SLJIT_IMM && word)
+ src1w = (sljit_s32)src1w;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);
+
+ if (is_compare || RISCV_HAS_ICOND(100)) {
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src1, src1w));
+ src1 = TMP_REG1;
+ src1w = 0;
+ } else if (src1 == SLJIT_IMM) {
+ if (src1w == 0) {
+ src1 = TMP_ZERO;
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));
+ src1 = TMP_REG1;
+ src1w = 0;
+ }
+ }
+
+ if (RISCV_HAS_BITMANIP_B(93) && is_compare) {
+ switch (type) {
+ case SLJIT_LESS:
+ case SLJIT_LESS_EQUAL:
+ return push_inst(compiler, MINU | RD(dst_reg) | RS1(src1) | RS2(src2_reg));
+ case SLJIT_GREATER:
+ case SLJIT_GREATER_EQUAL:
+ return push_inst(compiler, MAXU | RD(dst_reg) | RS1(src1) | RS2(src2_reg));
+ case SLJIT_SIG_LESS:
+ case SLJIT_SIG_LESS_EQUAL:
+ return push_inst(compiler, MIN | RD(dst_reg) | RS1(src1) | RS2(src2_reg));
+ default:
+ return push_inst(compiler, MAX | RD(dst_reg) | RS1(src1) | RS2(src2_reg));
+ }
+ }
+
+ if (RISCV_HAS_ICOND(100)) {
+ if (is_compare) {
+ cond_is_1 = 0;
+
+ switch (type) {
+ case SLJIT_LESS:
+ case SLJIT_LESS_EQUAL:
+ cond_is_1 = 1;
+ SLJIT_FALLTHROUGH
+ case SLJIT_GREATER:
+ case SLJIT_GREATER_EQUAL:
+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2_reg)));
+ break;
+ case SLJIT_SIG_LESS:
+ case SLJIT_SIG_LESS_EQUAL:
+ cond_is_1 = 1;
+ SLJIT_FALLTHROUGH
+ default:
+ FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src1) | RS2(src2_reg)));
+ break;
+ }
+
+ type = OTHER_FLAG;
+ } else {
+ /* BEQ instruction (type is inverted). */
+ cond_is_1 = (get_jump_instruction(type) & F3(0x1)) == 0;
+ type = (type == SLJIT_EQUAL || type == SLJIT_NOT_EQUAL) ? EQUAL_FLAG : OTHER_FLAG;
+ }
+
+ if (src1 == TMP_ZERO)
+ return push_inst(compiler, (cond_is_1 ? CZERO_NEZ : CZERO_EQZ) | RD(dst_reg) | RS1(src2_reg) | RS2(type));
+
+ FAIL_IF(push_inst(compiler, (cond_is_1 ? CZERO_EQZ : CZERO_NEZ) | RD(TMP_REG1) | RS1(src1) | RS2(type)));
+ FAIL_IF(push_inst(compiler, (cond_is_1 ? CZERO_NEZ : CZERO_EQZ) | RD(dst_reg) | RS1(src2_reg) | RS2(type)));
+ return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));
+ }
+ }
+
+ if (dst_reg != src2_reg) {
+ if (dst_reg == src1) {
+ src1 = src2_reg;
+ src1w = 0;
+ src2_reg = dst_reg;
+ if (!is_compare)
+ type ^= 0x1;
+ } else {
+ if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
+ SLJIT_ASSERT(!(type & SLJIT_COMPARE_SELECT));
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(dst_reg) | IMM_I(0)));
+
+ if ((src1 & REG_MASK) == dst_reg)
+ src1 = (src1 & ~REG_MASK) | TMP_REG1;
+
+ if (OFFS_REG(src1) == dst_reg)
+ src1 = (src1 & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);
+ }
+
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst_reg) | RS1(src2_reg) | IMM_I(0)));
+ }
+ }
+
+ if (src1 == SLJIT_IMM && (src1w <= 0 && src1w >= -1)) {
+ src1 = OTHER_FLAG;
+
+ if (type == SLJIT_EQUAL || type == SLJIT_NOT_EQUAL) {
+ FAIL_IF(push_inst(compiler, SLTUI | RD(TMP_REG1) | RS1(EQUAL_FLAG) | IMM_I(1)));
+ src1 = TMP_REG1;
+ cond_is_1 = (type == SLJIT_EQUAL);
+ } else {
+ /* BEQ instruction (type is inverted). */
+ cond_is_1 = (get_jump_instruction(type) & F3(0x1)) == 0;
+ }
+
+ if (src1w == 0) {
+ if (cond_is_1)
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src1) | IMM_I(-1)));
+ else
+ FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG1) | RS1(TMP_ZERO) | RS2(src1)));
+
+ return push_inst(compiler, AND | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));
+ }
+
+ if (cond_is_1)
+ FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG1) | RS1(TMP_ZERO) | RS2(src1)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src1) | IMM_I(-1)));
+
+ return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));
+ }
+
+ size = compiler->size;
+
+ ptr = (sljit_u16 *)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ compiler->size += 2;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w));
+ } else if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, dst_reg, src1w, TMP_REG1));
+ } else
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst_reg) | RS1(src1) | IMM_I(0)));
+
+ size = compiler->size - size;
+
+ if (is_compare) {
+ switch (type) {
+ case SLJIT_LESS:
+ case SLJIT_LESS_EQUAL:
+ ins = BGEU;
+ break;
+ case SLJIT_GREATER:
+ case SLJIT_GREATER_EQUAL:
+ ins = BLTU;
+ break;
+ case SLJIT_SIG_LESS:
+ case SLJIT_SIG_LESS_EQUAL:
+ ins = BGE;
+ break;
+ default:
+ ins = BLT;
+ break;
+ }
+
+ ins |= RS1(src1) | RS2(src2_reg);
+ } else {
+ ins = get_jump_instruction(type);
+ }
+
+ ins |= (sljit_ins)((size & 0xf) << 8) | (sljit_ins)((size >> 4) << 25);
+ ptr[0] = (sljit_u16)ins;
+ ptr[1] = (sljit_u16)(ins >> 16);
+ return SLJIT_SUCCESS;
+}
+
+#undef WORD
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_freg)
+{
+ sljit_u16 *ptr;
+ sljit_ins ins;
+ sljit_uw size;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ if (dst_freg != src2_freg) {
+ if (dst_freg == src1) {
+ src1 = src2_freg;
+ src1w = 0;
+ type ^= 0x1;
+ } else
+ FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(type) | FRD(dst_freg) | FRS1(src2_freg) | FRS2(src2_freg)));
+ }
+
+ size = compiler->size;
+
+ ptr = (sljit_u16 *)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ compiler->size += 2;
+
+ if (src1 & SLJIT_MEM)
+ FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, dst_freg, src1, src1w));
+ else
+ FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(type) | FRD(dst_freg) | FRS1(src1) | FRS2(src1)));
+
+ size = compiler->size - size;
+ ins = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((size & 0xf) << 8) | (sljit_ins)((size >> 4) << 25);
+ ptr[0] = (sljit_u16)ins;
+ ptr[1] = (sljit_u16)(ins >> 16);
+ return SLJIT_SUCCESS;
+}
+
+#undef FLOAT_DATA
+#undef FMT
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_s32 flags;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
+
+ if (!(reg & REG_PAIR_MASK))
+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
+
+ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
+ memw &= 0x3;
+
+ if (SLJIT_UNLIKELY(memw != 0)) {
+ FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG1) | RS1(OFFS_REG(mem)) | IMM_I(memw)));
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(mem & REG_MASK)));
+ } else
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(mem & REG_MASK) | RS2(OFFS_REG(mem))));
+
+ mem = TMP_REG1;
+ memw = 0;
+ } else if (memw > SIMM_MAX - SSIZE_OF(sw) || memw < SIMM_MIN) {
+ if (((memw + 0x800) & 0xfff) <= 0xfff - SSIZE_OF(sw)) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, TO_ARGW_HI(memw), TMP_REG3));
+ memw &= 0xfff;
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, memw, TMP_REG3));
+ memw = 0;
+ }
+
+ if (mem & REG_MASK)
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(mem & REG_MASK)));
+
+ mem = TMP_REG1;
+ } else {
+ mem &= REG_MASK;
+ memw &= 0xfff;
+ }
+
+ SLJIT_ASSERT((memw >= 0 && memw <= SIMM_MAX - SSIZE_OF(sw)) || (memw > SIMM_MAX && memw <= 0xfff));
+
+ if (!(type & SLJIT_MEM_STORE) && mem == REG_PAIR_FIRST(reg)) {
+ FAIL_IF(push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_SECOND(reg), mem, (memw + SSIZE_OF(sw)) & 0xfff));
+ return push_mem_inst(compiler, WORD_DATA | LOAD_DATA, REG_PAIR_FIRST(reg), mem, memw);
+ }
+
+ flags = WORD_DATA | (!(type & SLJIT_MEM_STORE) ? LOAD_DATA : 0);
+
+ FAIL_IF(push_mem_inst(compiler, flags, REG_PAIR_FIRST(reg), mem, memw));
+ return push_mem_inst(compiler, flags, REG_PAIR_SECOND(reg), mem, (memw + SSIZE_OF(sw)) & 0xfff);
+}
+
+#undef TO_ARGW_HI
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 mem_reg)
+{
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));
+
+ if (!RISCV_HAS_ATOMIC(200) || (op & SLJIT_ATOMIC_USE_CAS))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ ins = LR | (3 << 12);
+ break;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ ins = LR | (2 << 12);
+ break;
+
+ default:
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, ins | RD(dst_reg) | RS1(mem_reg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src_reg,
+ sljit_s32 mem_reg,
+ sljit_s32 temp_reg)
+{
+ sljit_ins ins;
+
+ /* temp_reg == mem_reg is undefined so use another temp register */
+ SLJIT_UNUSED_ARG(temp_reg);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));
+
+ if (!RISCV_HAS_ATOMIC(200) || (op & SLJIT_ATOMIC_USE_CAS))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ ins = SC | (3 << 12);
+ break;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ ins = SC | (2 << 12);
+ break;
+
+ default:
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, ins | RD(OTHER_FLAG) | RS1(mem_reg) | RS2(src_reg));
+}
+
+static sljit_s32 sljit_max_vector_length = 0;
+
+static void init_compiler(void)
+{
+ sljit_sw vector_length;
+ sljit_s32 vector_length_log2;
+
+ if (!RISCV_HAS_VECTOR(100))
+ return;
+
+ __asm__ __volatile__ ("csrr %0, 0xc22" : "=r" (vector_length));
+
+ /* Probably something is wrong. */
+ if (vector_length < (1 << 3))
+ return;
+
+ vector_length_log2 = 3;
+ if (vector_length_log2 < 6 && vector_length > (1 << vector_length_log2))
+ vector_length_log2++;
+ sljit_max_vector_length = vector_length_log2;
+}
+
+/*
+ SEW = Selected element width
+ LMUL = Vector register group multiplier
+
+ VLMUL values (in binary):
+ 100 : reserved
+ 101 : 1/8
+ 110 : 1/4
+ 111 : 1/2
+ 000 : 1
+ 001 : 2
+ 010 : 4
+ 011 : 8
+*/
+
+static SLJIT_INLINE sljit_s32 sljit_emit_vsetivli(struct sljit_compiler *compiler, sljit_s32 type, sljit_ins vlmul)
+{
+ sljit_ins elem_size = (sljit_ins)SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins avl = (sljit_ins)1 << (SLJIT_SIMD_GET_REG_SIZE(type) - elem_size);
+
+ if (avl < 31)
+ return push_inst(compiler, VSETIVLI | RD(TMP_REG1) | (elem_size << 23) | (vlmul << 20) | (avl << 15));
+
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(avl)));
+ return push_inst(compiler, VSETVLI | RD(TMP_REG1) | (elem_size << 23) | (vlmul << 20) | RS1(TMP_REG1));
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_vsetivli_size(struct sljit_compiler *compiler, sljit_s32 reg_size, sljit_s32 elem_size)
+{
+ sljit_ins avl = (sljit_ins)1 << (reg_size - elem_size);
+
+ if (avl < 31)
+ return push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (avl << 15));
+
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(avl)));
+ return push_inst(compiler, VSETVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | RS1(TMP_REG1));
+}
+
+static sljit_s32 sljit_emit_vmem(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 elem_size, sljit_s32 mem, sljit_sw memw)
+{
+ sljit_s32 base = mem & REG_MASK;
+
+ if (elem_size > 0)
+ ins |= (1 << 14) | ((sljit_ins)elem_size << 12);
+
+ if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
+ memw &= 0x3;
+
+ if (SLJIT_UNLIKELY(memw)) {
+ FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG1) | RS1(OFFS_REG(mem)) | IMM_I(memw)));
+ }
+
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(base) | RS2(!memw ? OFFS_REG(mem) : TMP_REG1)));
+ return push_inst(compiler, ins | RS1(TMP_REG1));
+ }
+
+ if (memw == 0)
+ return push_inst(compiler, ins | RS1(base));
+
+ if (memw <= SIMM_MAX && memw >= SIMM_MIN) {
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(base) | IMM_I(memw)));
+ return push_inst(compiler, ins | RS1(TMP_REG1));
+ }
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, memw, TMP_REG3));
+
+ if (base != 0)
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(base)));
+
+ return push_inst(compiler, ins | RS1(TMP_REG1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw));
+
+ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
+
+ if (reg_size < 3 || reg_size > sljit_max_vector_length)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (elem_size > 3)
+ elem_size = 3;
+
+ FAIL_IF(sljit_emit_vsetivli_size(compiler, reg_size, elem_size));
+
+ if (srcdst & SLJIT_MEM) {
+ ins = (type & SLJIT_SIMD_STORE) ? VS : VL;
+ return sljit_emit_vmem(compiler, ins | VRD(vreg), elem_size, srcdst, srcdstw);
+ }
+
+ if (type & SLJIT_SIMD_STORE)
+ ins = VRD(srcdst) | VRS1(vreg);
+ else
+ ins = VRD(vreg) | VRS1(srcdst);
+
+ return push_inst(compiler, VMV_VV | ins);
+}
+
+static sljit_s32 sljit_simd_get_mem_flags(sljit_s32 elem_size)
+{
+ switch (elem_size) {
+ case 0:
+ return BYTE_DATA;
+ case 1:
+ return HALF_DATA;
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ case 2:
+ return INT_DATA;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ default:
+ return WORD_DATA;
+ }
+}
+
+static sljit_sw sljit_simd_get_imm(sljit_s32 elem_size, sljit_sw imm)
+{
+ switch (elem_size) {
+ case 0:
+ return (sljit_s8)imm;
+ case 1:
+ return (sljit_s16)imm;
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ case 2:
+ return (sljit_s32)imm;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ default:
+ return imm;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 flags;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw));
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (reg_size < 3 || reg_size > sljit_max_vector_length)
+ return SLJIT_ERR_UNSUPPORTED;
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2)
+ return SLJIT_ERR_UNSUPPORTED;
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)
+ return SLJIT_ERR_UNSUPPORTED;
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(sljit_emit_vsetivli(compiler, type, 0));
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (src == SLJIT_IMM)
+ return push_inst(compiler, VMV_VI | VRD(vreg) | ((sljit_ins)(srcw & 0x1f) << 15));
+
+ if (src & SLJIT_MEM) {
+ flags = (elem_size == 2) ? SINGLE_DATA : DOUBLE_DATA;
+ FAIL_IF(emit_op_mem(compiler, flags | LOAD_DATA, TMP_FREG1, src, srcw));
+ src = TMP_FREG1;
+ }
+
+ return push_inst(compiler, VFMV_VF | VRD(vreg) | FRS1(src));
+ }
+
+ if (src == SLJIT_IMM) {
+ srcw = sljit_simd_get_imm(elem_size, srcw);
+
+ if (srcw >= -0x10 && srcw <= 0xf)
+ return push_inst(compiler, VMV_VI | VRD(vreg) | ((sljit_ins)(srcw & 0x1f) << 15));
+
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw, TMP_REG3));
+ src = TMP_REG1;
+ } else if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, sljit_simd_get_mem_flags(elem_size) | LOAD_DATA, TMP_REG1, src, srcw));
+ src = TMP_REG1;
+ }
+
+ return push_inst(compiler, VMV_VX | VRD(vreg) | RS1(src));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg, sljit_s32 lane_index,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 flags;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw));
+
+ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
+
+ if (reg_size < 3 || reg_size > sljit_max_vector_length)
+ return SLJIT_ERR_UNSUPPORTED;
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2)
+ return SLJIT_ERR_UNSUPPORTED;
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)
+ return SLJIT_ERR_UNSUPPORTED;
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (type & SLJIT_SIMD_STORE) {
+ FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (1 << 15)));
+
+ if (lane_index > 0) {
+ FAIL_IF(push_inst(compiler, VSLIDEDOWN_VI | VRD(TMP_VREG1) | ((sljit_ins)lane_index << 15) | VRS2(vreg)));
+ vreg = TMP_VREG1;
+ }
+
+ if (srcdst & SLJIT_MEM)
+ return sljit_emit_vmem(compiler, VS | VRD(vreg), elem_size, srcdst, srcdstw);
+
+ if (type & SLJIT_SIMD_FLOAT)
+ return push_inst(compiler, VFMV_FS | FRD(srcdst) | VRS2(vreg));
+
+ FAIL_IF(push_inst(compiler, VMV_XS | RD(srcdst) | VRS2(vreg)));
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ if ((type & SLJIT_SIMD_LANE_SIGNED) || elem_size >= 2)
+ return SLJIT_SUCCESS;
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ if ((type & SLJIT_SIMD_LANE_SIGNED) || elem_size >= 3 || (elem_size == 2 && (type & SLJIT_32)))
+ return SLJIT_SUCCESS;
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+ if (elem_size == 0)
+ return push_inst(compiler, ANDI | RD(srcdst) | RS1(srcdst) | IMM_I(0xff));
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ flags = 16;
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ flags = (elem_size == 1) ? 48 : 32;
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+ FAIL_IF(push_inst(compiler, SLLI | RD(srcdst) | RS1(srcdst) | IMM_I(flags)));
+ return push_inst(compiler, SRLI | RD(srcdst) | RS1(srcdst) | IMM_I(flags));
+ }
+
+ if (type & SLJIT_SIMD_LANE_ZERO) {
+ FAIL_IF(sljit_emit_vsetivli(compiler, type, 0));
+ FAIL_IF(push_inst(compiler, VMV_VI | VRD(vreg)));
+ }
+
+ if (srcdst & SLJIT_MEM) {
+ FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (1 << 15)));
+ FAIL_IF(sljit_emit_vmem(compiler, VL | VRD(lane_index > 0 ? TMP_VREG1 : vreg), elem_size, srcdst, srcdstw));
+
+ if (lane_index == 0)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | ((sljit_ins)(lane_index + 1) << 15)));
+ return push_inst(compiler, VSLIDEUP_VI | VRD(vreg) | ((sljit_ins)lane_index << 15) | VRS2(TMP_VREG1));
+ }
+
+ if (!(type & SLJIT_SIMD_LANE_ZERO) || lane_index > 0)
+ FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | ((sljit_ins)(lane_index + 1) << 15)));
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ FAIL_IF(push_inst(compiler, VFMV_SF | VRD(lane_index > 0 ? TMP_VREG1 : vreg) | FRS1(srcdst)));
+
+ if (lane_index == 0)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, VSLIDEUP_VI | VRD(vreg) | ((sljit_ins)lane_index << 15) | VRS2(TMP_VREG1));
+ }
+
+ if (srcdst == SLJIT_IMM) {
+ srcdstw = sljit_simd_get_imm(elem_size, srcdstw);
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcdstw, TMP_REG3));
+ srcdst = TMP_REG1;
+ }
+
+ FAIL_IF(push_inst(compiler, VMV_SX | VRD(lane_index > 0 ? TMP_VREG1 : vreg) | RS1(srcdst)));
+
+ if (lane_index == 0)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, VSLIDEUP_VI | VRD(vreg) | ((sljit_ins)lane_index << 15) | VRS2(TMP_VREG1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_s32 src_lane_index)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index));
+
+ if (reg_size < 3 || reg_size > sljit_max_vector_length)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(sljit_emit_vsetivli(compiler, type, 0));
+
+ FAIL_IF(push_inst(compiler, VRGATHER_VI | VRD(vreg != src ? vreg : TMP_VREG1) | ((sljit_ins)src_lane_index << 15) | VRS2(src)));
+ if (vreg == src)
+ return push_inst(compiler, VMV_VV | VRD(vreg) | VRS1(TMP_VREG1));
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw));
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (reg_size < 3 || reg_size > sljit_max_vector_length)
+ return SLJIT_ERR_UNSUPPORTED;
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2)
+ return SLJIT_ERR_UNSUPPORTED;
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)
+ return SLJIT_ERR_UNSUPPORTED;
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if ((src & SLJIT_MEM) || vreg == src) {
+ ins = (sljit_ins)1 << (reg_size - elem2_size);
+ FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (ins << 15)));
+
+ if (src & SLJIT_MEM)
+ FAIL_IF(sljit_emit_vmem(compiler, VL | VRD(TMP_VREG1), elem_size, src, srcw));
+ else
+ FAIL_IF(push_inst(compiler, VMV_VV | VRD(TMP_VREG1) | VRS1(src)));
+
+ src = TMP_VREG1;
+ }
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ FAIL_IF(sljit_emit_vsetivli(compiler, type, 0x7));
+ return push_inst(compiler, VFWCVT_FFV | VRD(vreg) | VRS2(src));
+ }
+
+ ins = (sljit_ins)1 << (reg_size - elem2_size);
+ FAIL_IF(push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem2_size << 23) | (ins << 15)));
+
+ switch (elem2_size - elem_size) {
+ case 1:
+ ins = VZEXT_VF2;
+ break;
+ case 2:
+ ins = VZEXT_VF4;
+ break;
+ default:
+ ins = VZEXT_VF8;
+ break;
+ }
+
+ if (type & SLJIT_SIMD_EXTEND_SIGNED)
+ ins |= 1 << 15;
+
+ return push_inst(compiler, ins | VRD(vreg) | VRS2(src));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw));
+
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ if (reg_size < 3 || reg_size > sljit_max_vector_length)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ FAIL_IF(sljit_emit_vsetivli(compiler, type, 0));
+ FAIL_IF(push_inst(compiler, VMV_VI | VRD(TMP_VREG1) | (0x0 << 15)));
+ FAIL_IF(push_inst(compiler, VMSLE_VI | VRD(TMP_VREG1) | (0x1f << 15) | VRS2(vreg)));
+
+ FAIL_IF(sljit_emit_vsetivli_size(compiler, 2, 2));
+ FAIL_IF(push_inst(compiler, VMV_XS | RD(dst_r) | VRS2(TMP_VREG1)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, (type & SLJIT_32) ? INT_DATA : WORD_DATA, dst_r, dst, dstw);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_ins ins = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));
+
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ if (reg_size < 3 || reg_size > sljit_max_vector_length)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ switch (SLJIT_SIMD_GET_OPCODE(type)) {
+ case SLJIT_SIMD_OP2_AND:
+ ins = VAND_VV;
+ break;
+ case SLJIT_SIMD_OP2_OR:
+ ins = VOR_VV;
+ break;
+ case SLJIT_SIMD_OP2_XOR:
+ ins = VXOR_VV;
+ break;
+ case SLJIT_SIMD_OP2_SHUFFLE:
+ ins = VRGATHER_VV;
+ elem_size = 0;
+ break;
+ }
+
+ if (elem_size > 3)
+ elem_size = 3;
+
+ FAIL_IF(sljit_emit_vsetivli_size(compiler, reg_size, elem_size));
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(sljit_emit_vmem(compiler, VL | VRD(TMP_VREG1), elem_size, src2, src2w));
+ src2 = TMP_VREG1;
+ }
+
+ if (SLJIT_SIMD_GET_OPCODE(type) != SLJIT_SIMD_OP2_SHUFFLE)
+ return push_inst(compiler, ins | VRD(dst_vreg) | VRS1(src1_vreg) | VRS2(src2));
+
+ if (dst_vreg == src2) {
+ FAIL_IF(push_inst(compiler, VMV_VV | VRD(TMP_VREG1) | VRS1(src2)));
+ src2 = TMP_VREG1;
+ }
+
+ if (dst_vreg == src1_vreg) {
+ FAIL_IF(push_inst(compiler, VMV_VV | VRD(TMP_VREG2) | VRS1(src1_vreg)));
+ src1_vreg = TMP_VREG2;
+ }
+
+ return push_inst(compiler, ins | VRD(dst_vreg) | VRS1(src2) | VRS2(src1_vreg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
+{
+ struct sljit_const *const_;
+ sljit_s32 dst_r;
+ sljit_s32 mem_flags = WORD_DATA;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+ PTR_FAIL_IF(!const_);
+ set_const(const_, compiler);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ if (init_value & 0x100)
+ init_value |= 0xf00;
+ else
+ init_value &= 0xff;
+
+ PTR_FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | IMM_I(init_value)));
+ mem_flags = BYTE_DATA;
+ break;
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ case SLJIT_MOV32:
+ mem_flags = INT_DATA;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_S32:
+ if ((init_value & 0x800) != 0)
+ init_value ^= ~(sljit_sw)0xfff;
+
+ PTR_FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(init_value & ~(sljit_sw)0xfff)));
+ PTR_FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(init_value)));
+ break;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ default:
+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, ADDI | RD(dst_r)));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, dst, dstw));
+
+ return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_jump *jump;
+ sljit_s32 dst_r, target_r;
+ SLJIT_UNUSED_ARG(op);
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = TMP_REG1;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, dst, dstw));
+ }
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_mov_addr(jump, compiler, 0);
+
+ PTR_FAIL_IF(push_inst16(compiler, (sljit_u16)target_r));
+ compiler->size += JUMP_MAX_SIZE - 1;
+
+ if (op == SLJIT_ADD_ABS_ADDR) {
+ if (RISCV_HAS_COMPRESSED(200))
+ PTR_FAIL_IF(push_inst16(compiler, C_ADD | C_RD(dst_r) | C_RS2(TMP_REG1)));
+ else
+ PTR_FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RS1(dst_r) | RS2(TMP_REG1)));
+ }
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
+
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
+{
+ sljit_u16 *inst;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ inst = (sljit_u16*)addr;
+ SLJIT_ASSERT((inst[0] & 0x707f) == ADDI);
+
+ if (new_constant & 0x100)
+ new_constant |= 0xf00;
+ else
+ new_constant &= 0xff;
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ inst[1] = (sljit_u16)(new_constant << 4) | (inst[1] & 0xf);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ return;
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ inst = (sljit_u16*)addr;
+ SLJIT_ASSERT((inst[0] & 0x7f) == LUI && (inst[2] & 0x707f) == XORI);
+
+ if ((new_constant & 0x800) != 0)
+ new_constant ^= ~(sljit_sw)0xfff;
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);
+ inst[0] = (sljit_u16)((inst[0] & 0xfff) | (new_constant & 0xf000));
+ inst[1] = (sljit_u16)(new_constant >> 16);
+ inst[3] = (sljit_u16)(new_constant << 4) | (inst[3] & 0xf);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);
+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 4);
+ return;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ default:
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ return;
+ }
+}
diff --git a/deps/sljit/sljit_src/sljitNativeS390X.c b/deps/sljit/sljit_src/sljitNativeS390X.c
new file mode 100644
index 0000000..1032ec0
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativeS390X.c
@@ -0,0 +1,4822 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include
+
+#ifdef __ARCH__
+#define ENABLE_STATIC_FACILITY_DETECTION 1
+#else
+#define ENABLE_STATIC_FACILITY_DETECTION 0
+#endif
+#define ENABLE_DYNAMIC_FACILITY_DETECTION 1
+
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
+{
+ return "s390x" SLJIT_CPUINFO;
+}
+
+/* Instructions are stored as 64 bit values regardless their size. */
+typedef sljit_uw sljit_ins;
+
+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
+
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
+ 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 0, 1, 14
+};
+
+/* there are also a[2-15] available, but they are slower to access and
+ * their use is limited as mundaym explained:
+ * https://github.com/zherczeg/sljit/pull/91#discussion_r486895689
+ */
+
+/* General Purpose Registers [0-15]. */
+typedef sljit_uw sljit_gpr;
+
+/*
+ * WARNING
+ * the following code is non standard and should be improved for
+ * consistency, but doesn't use SLJIT_NUMBER_OF_REGISTERS based
+ * registers because r0 and r1 are the ABI recommended volatiles.
+ * there is a gpr() function that maps sljit to physical register numbers
+ * that should be used instead of the usual index into reg_map[] and
+ * will be retired ASAP (TODO: carenas)
+ */
+
+static const sljit_gpr r0 = 0; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 2]: 0 in address calculations; reserved */
+static const sljit_gpr r1 = 1; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 3]: reserved */
+static const sljit_gpr r2 = 2; /* reg_map[1]: 1st argument */
+static const sljit_gpr r3 = 3; /* reg_map[2]: 2nd argument */
+static const sljit_gpr r4 = 4; /* reg_map[3]: 3rd argument */
+static const sljit_gpr r5 = 5; /* reg_map[4]: 4th argument */
+static const sljit_gpr r6 = 6; /* reg_map[5]: 5th argument; 1st saved register */
+static const sljit_gpr r7 = 7; /* reg_map[6] */
+static const sljit_gpr r8 = 8; /* reg_map[7] */
+static const sljit_gpr r9 = 9; /* reg_map[8] */
+static const sljit_gpr r10 = 10; /* reg_map[9] */
+static const sljit_gpr r11 = 11; /* reg_map[10] */
+static const sljit_gpr r12 = 12; /* reg_map[11]: GOT */
+static const sljit_gpr r13 = 13; /* reg_map[12]: Literal Pool pointer */
+static const sljit_gpr r14 = 14; /* reg_map[0]: return address */
+static const sljit_gpr r15 = 15; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 1]: stack pointer */
+
+/* WARNING: r12 and r13 shouldn't be used as per ABI recommendation */
+/* TODO(carenas): r12 might conflict in PIC code, reserve? */
+/* TODO(carenas): r13 is usually pointed to "pool" per ABI, using a tmp
+ * like we do know might be faster though, reserve?
+ */
+
+/* TODO(carenas): should be named TMP_REG[1-2] for consistency */
+#define tmp0 r0
+#define tmp1 r1
+
+/* Link register. */
+static const sljit_gpr link_r = 14; /* r14 */
+
+#define TMP_FREG1 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
+
+static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2] = {
+ 0, 0, 2, 4, 6, 3, 5, 7, 15, 14, 13, 12, 11, 10, 9, 8, 1
+};
+
+#define R0A(r) (r)
+#define R4A(r) ((r) << 4)
+#define R8A(r) ((r) << 8)
+#define R12A(r) ((r) << 12)
+#define R16A(r) ((r) << 16)
+#define R20A(r) ((r) << 20)
+#define R28A(r) ((r) << 28)
+#define R32A(r) ((r) << 32)
+#define R36A(r) ((r) << 36)
+
+#define R0(r) ((sljit_ins)reg_map[r])
+
+#define F0(r) ((sljit_ins)freg_map[r])
+#define F4(r) (R4A((sljit_ins)freg_map[r]))
+#define F12(r) (R12A((sljit_ins)freg_map[r]))
+#define F20(r) (R20A((sljit_ins)freg_map[r]))
+#define F28(r) (R28A((sljit_ins)freg_map[r]))
+#define F32(r) (R32A((sljit_ins)freg_map[r]))
+#define F36(r) (R36A((sljit_ins)freg_map[r]))
+
+/* Convert SLJIT register to hardware register. */
+static SLJIT_INLINE sljit_gpr gpr(sljit_s32 r)
+{
+ SLJIT_ASSERT(r >= 0 && r < (sljit_s32)(sizeof(reg_map) / sizeof(reg_map[0])));
+ return reg_map[r];
+}
+
+static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
+{
+ sljit_ins *ibuf = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ibuf);
+ *ibuf = ins;
+
+ SLJIT_ASSERT(ins <= 0xffffffffffffL);
+
+ compiler->size++;
+ if (ins & 0xffff00000000L)
+ compiler->size++;
+
+ if (ins & 0xffffffff0000L)
+ compiler->size++;
+
+ return SLJIT_SUCCESS;
+}
+
+#define SLJIT_ADD_SUB_NO_COMPARE(status_flags_state) \
+ (((status_flags_state) & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) \
+ && !((status_flags_state) & SLJIT_CURRENT_FLAGS_COMPARE))
+
+/* Map the given type to a 4-bit condition code mask. */
+static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 type) {
+ const sljit_u8 cc0 = 1 << 3; /* equal {,to zero} */
+ const sljit_u8 cc1 = 1 << 2; /* less than {,zero} */
+ const sljit_u8 cc2 = 1 << 1; /* greater than {,zero} */
+ const sljit_u8 cc3 = 1 << 0; /* {overflow,NaN} */
+
+ switch (type) {
+ case SLJIT_EQUAL:
+ if (SLJIT_ADD_SUB_NO_COMPARE(compiler->status_flags_state)) {
+ sljit_s32 flag_type = GET_FLAG_TYPE(compiler->status_flags_state);
+ if (flag_type >= SLJIT_SIG_LESS && flag_type <= SLJIT_SIG_LESS_EQUAL)
+ return cc0;
+ if (flag_type == SLJIT_OVERFLOW)
+ return (cc0 | cc3);
+ return (cc0 | cc2);
+ }
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_ATOMIC_STORED:
+ case SLJIT_F_EQUAL:
+ case SLJIT_ORDERED_EQUAL:
+ return cc0;
+
+ case SLJIT_NOT_EQUAL:
+ if (SLJIT_ADD_SUB_NO_COMPARE(compiler->status_flags_state)) {
+ sljit_s32 flag_type = GET_FLAG_TYPE(compiler->status_flags_state);
+ if (flag_type >= SLJIT_SIG_LESS && flag_type <= SLJIT_SIG_LESS_EQUAL)
+ return (cc1 | cc2 | cc3);
+ if (flag_type == SLJIT_OVERFLOW)
+ return (cc1 | cc2);
+ return (cc1 | cc3);
+ }
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_UNORDERED_OR_NOT_EQUAL:
+ return (cc1 | cc2 | cc3);
+
+ case SLJIT_LESS:
+ case SLJIT_ATOMIC_NOT_STORED:
+ return cc1;
+
+ case SLJIT_GREATER_EQUAL:
+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:
+ return (cc0 | cc2 | cc3);
+
+ case SLJIT_GREATER:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_COMPARE)
+ return cc2;
+ return cc3;
+
+ case SLJIT_LESS_EQUAL:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_COMPARE)
+ return (cc0 | cc1);
+ return (cc0 | cc1 | cc2);
+
+ case SLJIT_SIG_LESS:
+ case SLJIT_F_LESS:
+ case SLJIT_ORDERED_LESS:
+ return cc1;
+
+ case SLJIT_NOT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
+ return (cc2 | cc3);
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_SIG_LESS_EQUAL:
+ case SLJIT_F_LESS_EQUAL:
+ case SLJIT_ORDERED_LESS_EQUAL:
+ return (cc0 | cc1);
+
+ case SLJIT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
+ return (cc0 | cc1);
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_SIG_GREATER:
+ case SLJIT_UNORDERED_OR_GREATER:
+ /* Overflow is considered greater, see SLJIT_SUB. */
+ return cc2 | cc3;
+
+ case SLJIT_SIG_GREATER_EQUAL:
+ return (cc0 | cc2 | cc3);
+
+ case SLJIT_OVERFLOW:
+ if (compiler->status_flags_state & SLJIT_SET_Z)
+ return (cc2 | cc3);
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_UNORDERED:
+ return cc3;
+
+ case SLJIT_NOT_OVERFLOW:
+ if (compiler->status_flags_state & SLJIT_SET_Z)
+ return (cc0 | cc1);
+ SLJIT_FALLTHROUGH
+
+ case SLJIT_ORDERED:
+ return (cc0 | cc1 | cc2);
+
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ return (cc1 | cc2);
+
+ case SLJIT_F_GREATER:
+ case SLJIT_ORDERED_GREATER:
+ return cc2;
+
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_ORDERED_GREATER_EQUAL:
+ return (cc0 | cc2);
+
+ case SLJIT_UNORDERED_OR_LESS_EQUAL:
+ return (cc0 | cc1 | cc3);
+
+ case SLJIT_UNORDERED_OR_EQUAL:
+ return (cc0 | cc3);
+
+ case SLJIT_UNORDERED_OR_LESS:
+ return (cc1 | cc3);
+ }
+
+ SLJIT_UNREACHABLE();
+ return (sljit_u8)-1;
+}
+
+/* Facility to bit index mappings.
+ Note: some facilities share the same bit index. */
+typedef sljit_uw facility_bit;
+#define STORE_FACILITY_LIST_EXTENDED_FACILITY 7
+#define FAST_LONG_DISPLACEMENT_FACILITY 19
+#define EXTENDED_IMMEDIATE_FACILITY 21
+#define GENERAL_INSTRUCTION_EXTENSION_FACILITY 34
+#define DISTINCT_OPERAND_FACILITY 45
+#define HIGH_WORD_FACILITY 45
+#define POPULATION_COUNT_FACILITY 45
+#define LOAD_STORE_ON_CONDITION_1_FACILITY 45
+#define MISCELLANEOUS_INSTRUCTION_EXTENSIONS_1_FACILITY 49
+#define LOAD_STORE_ON_CONDITION_2_FACILITY 53
+#define MISCELLANEOUS_INSTRUCTION_EXTENSIONS_2_FACILITY 58
+#define VECTOR_FACILITY 129
+#define VECTOR_ENHANCEMENTS_1_FACILITY 135
+
+/* Report whether a facility is known to be present due to the compiler
+ settings. This function should always be compiled to a constant
+ value given a constant argument. */
+static SLJIT_INLINE int have_facility_static(facility_bit x)
+{
+#if ENABLE_STATIC_FACILITY_DETECTION
+ switch (x) {
+ case FAST_LONG_DISPLACEMENT_FACILITY:
+ return (__ARCH__ >= 6 /* z990 */);
+ case EXTENDED_IMMEDIATE_FACILITY:
+ case STORE_FACILITY_LIST_EXTENDED_FACILITY:
+ return (__ARCH__ >= 7 /* z9-109 */);
+ case GENERAL_INSTRUCTION_EXTENSION_FACILITY:
+ return (__ARCH__ >= 8 /* z10 */);
+ case DISTINCT_OPERAND_FACILITY:
+ return (__ARCH__ >= 9 /* z196 */);
+ case MISCELLANEOUS_INSTRUCTION_EXTENSIONS_1_FACILITY:
+ return (__ARCH__ >= 10 /* zEC12 */);
+ case LOAD_STORE_ON_CONDITION_2_FACILITY:
+ case VECTOR_FACILITY:
+ return (__ARCH__ >= 11 /* z13 */);
+ case MISCELLANEOUS_INSTRUCTION_EXTENSIONS_2_FACILITY:
+ case VECTOR_ENHANCEMENTS_1_FACILITY:
+ return (__ARCH__ >= 12 /* z14 */);
+ default:
+ SLJIT_UNREACHABLE();
+ }
+#endif
+ return 0;
+}
+
+static SLJIT_INLINE unsigned long get_hwcap(void)
+{
+ static unsigned long hwcap = 0;
+ if (SLJIT_UNLIKELY(!hwcap)) {
+ hwcap = getauxval(AT_HWCAP);
+ SLJIT_ASSERT(hwcap != 0);
+ }
+ return hwcap;
+}
+
+static SLJIT_INLINE int have_stfle(void)
+{
+ if (have_facility_static(STORE_FACILITY_LIST_EXTENDED_FACILITY))
+ return 1;
+
+ return (get_hwcap() & HWCAP_S390_STFLE);
+}
+
+/* Report whether the given facility is available. This function always
+ performs a runtime check. */
+static int have_facility_dynamic(facility_bit x)
+{
+#if ENABLE_DYNAMIC_FACILITY_DETECTION
+ static struct {
+ sljit_uw bits[4];
+ } cpu_features;
+ size_t size = sizeof(cpu_features);
+ const sljit_uw word_index = x >> 6;
+ const sljit_uw bit_index = ((1UL << 63) >> (x & 63));
+
+ SLJIT_ASSERT(x < size * 8);
+ if (SLJIT_UNLIKELY(!have_stfle()))
+ return 0;
+
+ if (SLJIT_UNLIKELY(cpu_features.bits[0] == 0)) {
+ __asm__ __volatile__ (
+ "lgr %%r0, %0;"
+ "stfle 0(%1);"
+ /* outputs */:
+ /* inputs */: "d" ((size / 8) - 1), "a" (&cpu_features)
+ /* clobbers */: "r0", "cc", "memory"
+ );
+ SLJIT_ASSERT(cpu_features.bits[0] != 0);
+ }
+ return (cpu_features.bits[word_index] & bit_index) != 0;
+#else
+ return 0;
+#endif
+}
+
+#define HAVE_FACILITY(name, bit) \
+static SLJIT_INLINE int name() \
+{ \
+ static int have = -1; \
+ /* Static check first. May allow the function to be optimized away. */ \
+ if (have_facility_static(bit)) \
+ have = 1; \
+ else if (SLJIT_UNLIKELY(have < 0)) \
+ have = have_facility_dynamic(bit) ? 1 : 0; \
+\
+ return have; \
+}
+
+HAVE_FACILITY(have_eimm, EXTENDED_IMMEDIATE_FACILITY)
+HAVE_FACILITY(have_ldisp, FAST_LONG_DISPLACEMENT_FACILITY)
+HAVE_FACILITY(have_genext, GENERAL_INSTRUCTION_EXTENSION_FACILITY)
+HAVE_FACILITY(have_lscond1, LOAD_STORE_ON_CONDITION_1_FACILITY)
+HAVE_FACILITY(have_lscond2, LOAD_STORE_ON_CONDITION_2_FACILITY)
+HAVE_FACILITY(have_misc2, MISCELLANEOUS_INSTRUCTION_EXTENSIONS_2_FACILITY)
+#undef HAVE_FACILITY
+
+#define is_u12(d) (0 <= (d) && (d) <= 0x00000fffL)
+#define is_u32(d) (0 <= (d) && (d) <= 0xffffffffL)
+
+#define CHECK_SIGNED(v, bitlen) \
+ ((v) >= -(1 << ((bitlen) - 1)) && (v) < (1 << ((bitlen) - 1)))
+
+#define is_s8(d) ((sljit_sw)(d) == (sljit_s8)(d))
+#define is_s16(d) ((sljit_sw)(d) == (sljit_s16)(d))
+#define is_s20(d) CHECK_SIGNED((d), 20)
+#define is_s32(d) ((sljit_sw)(d) == (sljit_s32)(d))
+
+static SLJIT_INLINE sljit_ins disp_s20(sljit_s32 d)
+{
+ sljit_uw dh, dl;
+
+ SLJIT_ASSERT(is_s20(d));
+
+ dh = (d >> 12) & 0xff;
+ dl = ((sljit_uw)d << 8) & 0xfff00;
+ return (dh | dl) << 8;
+}
+
+/* TODO(carenas): variadic macro is not strictly needed */
+#define SLJIT_S390X_INSTRUCTION(op, ...) \
+static SLJIT_INLINE sljit_ins op(__VA_ARGS__)
+
+/* RR form instructions. */
+#define SLJIT_S390X_RR(name, pattern) \
+SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src) \
+{ \
+ return (pattern) | ((dst & 0xf) << 4) | (src & 0xf); \
+}
+
+/* AND */
+SLJIT_S390X_RR(nr, 0x1400)
+
+/* BRANCH AND SAVE */
+SLJIT_S390X_RR(basr, 0x0d00)
+
+/* BRANCH ON CONDITION */
+SLJIT_S390X_RR(bcr, 0x0700) /* TODO(mundaym): type for mask? */
+
+/* DIVIDE */
+SLJIT_S390X_RR(dr, 0x1d00)
+
+/* EXCLUSIVE OR */
+SLJIT_S390X_RR(xr, 0x1700)
+
+/* LOAD */
+SLJIT_S390X_RR(lr, 0x1800)
+
+/* LOAD COMPLEMENT */
+SLJIT_S390X_RR(lcr, 0x1300)
+
+/* OR */
+SLJIT_S390X_RR(or, 0x1600)
+
+#undef SLJIT_S390X_RR
+
+/* RRE form instructions */
+#define SLJIT_S390X_RRE(name, pattern) \
+SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src) \
+{ \
+ return (pattern) | R4A(dst) | R0A(src); \
+}
+
+/* AND */
+SLJIT_S390X_RRE(ngr, 0xb9800000)
+
+/* DIVIDE LOGICAL */
+SLJIT_S390X_RRE(dlr, 0xb9970000)
+SLJIT_S390X_RRE(dlgr, 0xb9870000)
+
+/* DIVIDE SINGLE */
+SLJIT_S390X_RRE(dsgr, 0xb90d0000)
+
+/* EXCLUSIVE OR */
+SLJIT_S390X_RRE(xgr, 0xb9820000)
+
+/* LOAD */
+SLJIT_S390X_RRE(lgr, 0xb9040000)
+SLJIT_S390X_RRE(lgfr, 0xb9140000)
+
+/* LOAD BYTE */
+SLJIT_S390X_RRE(lbr, 0xb9260000)
+SLJIT_S390X_RRE(lgbr, 0xb9060000)
+
+/* LOAD COMPLEMENT */
+SLJIT_S390X_RRE(lcgr, 0xb9030000)
+
+/* LOAD HALFWORD */
+SLJIT_S390X_RRE(lhr, 0xb9270000)
+SLJIT_S390X_RRE(lghr, 0xb9070000)
+
+/* LOAD LOGICAL */
+SLJIT_S390X_RRE(llgfr, 0xb9160000)
+
+/* LOAD LOGICAL CHARACTER */
+SLJIT_S390X_RRE(llcr, 0xb9940000)
+SLJIT_S390X_RRE(llgcr, 0xb9840000)
+
+/* LOAD LOGICAL HALFWORD */
+SLJIT_S390X_RRE(llhr, 0xb9950000)
+SLJIT_S390X_RRE(llghr, 0xb9850000)
+
+/* MULTIPLY LOGICAL */
+SLJIT_S390X_RRE(mlgr, 0xb9860000)
+
+/* MULTIPLY SINGLE */
+SLJIT_S390X_RRE(msgfr, 0xb91c0000)
+
+/* OR */
+SLJIT_S390X_RRE(ogr, 0xb9810000)
+
+/* SUBTRACT */
+SLJIT_S390X_RRE(sgr, 0xb9090000)
+
+#undef SLJIT_S390X_RRE
+
+/* RI-a form instructions */
+#define SLJIT_S390X_RIA(name, pattern, imm_type) \
+SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, imm_type imm) \
+{ \
+ return (pattern) | R20A(reg) | (imm & 0xffff); \
+}
+
+/* ADD HALFWORD IMMEDIATE */
+SLJIT_S390X_RIA(aghi, 0xa70b0000, sljit_s16)
+
+/* LOAD HALFWORD IMMEDIATE */
+SLJIT_S390X_RIA(lhi, 0xa7080000, sljit_s16)
+SLJIT_S390X_RIA(lghi, 0xa7090000, sljit_s16)
+
+/* LOAD LOGICAL IMMEDIATE */
+SLJIT_S390X_RIA(llihh, 0xa50c0000, sljit_u16)
+SLJIT_S390X_RIA(llihl, 0xa50d0000, sljit_u16)
+SLJIT_S390X_RIA(llilh, 0xa50e0000, sljit_u16)
+SLJIT_S390X_RIA(llill, 0xa50f0000, sljit_u16)
+
+/* MULTIPLY HALFWORD IMMEDIATE */
+SLJIT_S390X_RIA(mhi, 0xa70c0000, sljit_s16)
+SLJIT_S390X_RIA(mghi, 0xa70d0000, sljit_s16)
+
+/* OR IMMEDIATE */
+SLJIT_S390X_RIA(oilh, 0xa50a0000, sljit_u16)
+
+#undef SLJIT_S390X_RIA
+
+/* RIL-a form instructions (requires extended immediate facility) */
+#define SLJIT_S390X_RILA(name, pattern, imm_type) \
+SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, imm_type imm) \
+{ \
+ SLJIT_ASSERT(have_eimm()); \
+ return (pattern) | R36A(reg) | ((sljit_ins)imm & 0xffffffffu); \
+}
+
+/* ADD IMMEDIATE */
+SLJIT_S390X_RILA(agfi, 0xc20800000000, sljit_s32)
+
+/* ADD IMMEDIATE HIGH */
+SLJIT_S390X_RILA(aih, 0xcc0800000000, sljit_s32) /* TODO(mundaym): high-word facility? */
+
+/* AND IMMEDIATE */
+SLJIT_S390X_RILA(nihf, 0xc00a00000000, sljit_u32)
+
+/* EXCLUSIVE OR IMMEDIATE */
+SLJIT_S390X_RILA(xilf, 0xc00700000000, sljit_u32)
+
+/* INSERT IMMEDIATE */
+SLJIT_S390X_RILA(iihf, 0xc00800000000, sljit_u32)
+SLJIT_S390X_RILA(iilf, 0xc00900000000, sljit_u32)
+
+/* LOAD IMMEDIATE */
+SLJIT_S390X_RILA(lgfi, 0xc00100000000, sljit_s32)
+
+/* LOAD LOGICAL IMMEDIATE */
+SLJIT_S390X_RILA(llihf, 0xc00e00000000, sljit_u32)
+SLJIT_S390X_RILA(llilf, 0xc00f00000000, sljit_u32)
+
+/* SUBTRACT LOGICAL IMMEDIATE */
+SLJIT_S390X_RILA(slfi, 0xc20500000000, sljit_u32)
+
+#undef SLJIT_S390X_RILA
+
+/* RX-a form instructions */
+#define SLJIT_S390X_RXA(name, pattern) \
+SLJIT_S390X_INSTRUCTION(name, sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b) \
+{ \
+ SLJIT_ASSERT((d & 0xfff) == d); \
+\
+ return (pattern) | R20A(r) | R16A(x) | R12A(b) | (sljit_ins)(d & 0xfff); \
+}
+
+/* LOAD */
+SLJIT_S390X_RXA(l, 0x58000000)
+
+/* LOAD ADDRESS */
+SLJIT_S390X_RXA(la, 0x41000000)
+
+/* LOAD HALFWORD */
+SLJIT_S390X_RXA(lh, 0x48000000)
+
+/* MULTIPLY SINGLE */
+SLJIT_S390X_RXA(ms, 0x71000000)
+
+/* STORE */
+SLJIT_S390X_RXA(st, 0x50000000)
+
+/* STORE CHARACTER */
+SLJIT_S390X_RXA(stc, 0x42000000)
+
+/* STORE HALFWORD */
+SLJIT_S390X_RXA(sth, 0x40000000)
+
+#undef SLJIT_S390X_RXA
+
+/* RXY-a instructions */
+#define SLJIT_S390X_RXYA(name, pattern, cond) \
+SLJIT_S390X_INSTRUCTION(name, sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b) \
+{ \
+ SLJIT_ASSERT(cond); \
+\
+ return (pattern) | R36A(r) | R32A(x) | R28A(b) | disp_s20(d); \
+}
+
+/* LOAD */
+SLJIT_S390X_RXYA(ly, 0xe30000000058, have_ldisp())
+SLJIT_S390X_RXYA(lg, 0xe30000000004, 1)
+SLJIT_S390X_RXYA(lgf, 0xe30000000014, 1)
+
+/* LOAD BYTE */
+SLJIT_S390X_RXYA(lb, 0xe30000000076, have_ldisp())
+SLJIT_S390X_RXYA(lgb, 0xe30000000077, have_ldisp())
+
+/* LOAD HALFWORD */
+SLJIT_S390X_RXYA(lhy, 0xe30000000078, have_ldisp())
+SLJIT_S390X_RXYA(lgh, 0xe30000000015, 1)
+
+/* LOAD LOGICAL */
+SLJIT_S390X_RXYA(llgf, 0xe30000000016, 1)
+
+/* LOAD LOGICAL CHARACTER */
+SLJIT_S390X_RXYA(llc, 0xe30000000094, have_eimm())
+SLJIT_S390X_RXYA(llgc, 0xe30000000090, 1)
+
+/* LOAD LOGICAL HALFWORD */
+SLJIT_S390X_RXYA(llh, 0xe30000000095, have_eimm())
+SLJIT_S390X_RXYA(llgh, 0xe30000000091, 1)
+
+/* MULTIPLY SINGLE */
+SLJIT_S390X_RXYA(msy, 0xe30000000051, have_ldisp())
+SLJIT_S390X_RXYA(msg, 0xe3000000000c, 1)
+
+/* STORE */
+SLJIT_S390X_RXYA(sty, 0xe30000000050, have_ldisp())
+SLJIT_S390X_RXYA(stg, 0xe30000000024, 1)
+
+/* STORE CHARACTER */
+SLJIT_S390X_RXYA(stcy, 0xe30000000072, have_ldisp())
+
+/* STORE HALFWORD */
+SLJIT_S390X_RXYA(sthy, 0xe30000000070, have_ldisp())
+
+#undef SLJIT_S390X_RXYA
+
+/* RSY-a instructions */
+#define SLJIT_S390X_RSYA(name, pattern, cond) \
+SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_s32 d, sljit_gpr b) \
+{ \
+ SLJIT_ASSERT(cond); \
+\
+ return (pattern) | R36A(dst) | R32A(src) | R28A(b) | disp_s20(d); \
+}
+
+/* LOAD MULTIPLE */
+SLJIT_S390X_RSYA(lmg, 0xeb0000000004, 1)
+
+/* SHIFT LEFT LOGICAL */
+SLJIT_S390X_RSYA(sllg, 0xeb000000000d, 1)
+
+/* SHIFT RIGHT SINGLE */
+SLJIT_S390X_RSYA(srag, 0xeb000000000a, 1)
+
+/* STORE MULTIPLE */
+SLJIT_S390X_RSYA(stmg, 0xeb0000000024, 1)
+
+#undef SLJIT_S390X_RSYA
+
+/* RIE-f instructions (require general-instructions-extension facility) */
+#define SLJIT_S390X_RIEF(name, pattern) \
+SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_u8 start, sljit_u8 end, sljit_u8 rot) \
+{ \
+ sljit_ins i3, i4, i5; \
+\
+ SLJIT_ASSERT(have_genext()); \
+ i3 = (sljit_ins)start << 24; \
+ i4 = (sljit_ins)end << 16; \
+ i5 = (sljit_ins)rot << 8; \
+\
+ return (pattern) | R36A(dst & 0xf) | R32A(src & 0xf) | i3 | i4 | i5; \
+}
+
+/* ROTATE THEN AND SELECTED BITS */
+/* SLJIT_S390X_RIEF(rnsbg, 0xec0000000054) */
+
+/* ROTATE THEN EXCLUSIVE OR SELECTED BITS */
+/* SLJIT_S390X_RIEF(rxsbg, 0xec0000000057) */
+
+/* ROTATE THEN OR SELECTED BITS */
+SLJIT_S390X_RIEF(rosbg, 0xec0000000056)
+
+/* ROTATE THEN INSERT SELECTED BITS */
+/* SLJIT_S390X_RIEF(risbg, 0xec0000000055) */
+/* SLJIT_S390X_RIEF(risbgn, 0xec0000000059) */
+
+/* ROTATE THEN INSERT SELECTED BITS HIGH */
+SLJIT_S390X_RIEF(risbhg, 0xec000000005d)
+
+/* ROTATE THEN INSERT SELECTED BITS LOW */
+/* SLJIT_S390X_RIEF(risblg, 0xec0000000051) */
+
+#undef SLJIT_S390X_RIEF
+
+/* RRF-c instructions (require load/store-on-condition 1 facility) */
+#define SLJIT_S390X_RRFC(name, pattern) \
+SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_uw mask) \
+{ \
+ sljit_ins m3; \
+\
+ SLJIT_ASSERT(have_lscond1()); \
+ m3 = (sljit_ins)(mask & 0xf) << 12; \
+\
+ return (pattern) | m3 | R4A(dst) | R0A(src); \
+}
+
+/* LOAD HALFWORD IMMEDIATE ON CONDITION */
+SLJIT_S390X_RRFC(locr, 0xb9f20000)
+SLJIT_S390X_RRFC(locgr, 0xb9e20000)
+
+#undef SLJIT_S390X_RRFC
+
+/* RIE-g instructions (require load/store-on-condition 2 facility) */
+#define SLJIT_S390X_RIEG(name, pattern) \
+SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, sljit_sw imm, sljit_uw mask) \
+{ \
+ sljit_ins m3, i2; \
+\
+ SLJIT_ASSERT(have_lscond2()); \
+ m3 = (sljit_ins)(mask & 0xf) << 32; \
+ i2 = (sljit_ins)(imm & 0xffffL) << 16; \
+\
+ return (pattern) | R36A(reg) | m3 | i2; \
+}
+
+/* LOAD HALFWORD IMMEDIATE ON CONDITION */
+SLJIT_S390X_RIEG(lochi, 0xec0000000042)
+SLJIT_S390X_RIEG(locghi, 0xec0000000046)
+
+#undef SLJIT_S390X_RIEG
+
+#define SLJIT_S390X_RILB(name, pattern, cond) \
+SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, sljit_sw ri) \
+{ \
+ SLJIT_ASSERT(cond); \
+\
+ return (pattern) | R36A(reg) | (sljit_ins)(ri & 0xffffffff); \
+}
+
+/* BRANCH RELATIVE AND SAVE LONG */
+SLJIT_S390X_RILB(brasl, 0xc00500000000, 1)
+
+/* LOAD ADDRESS RELATIVE LONG */
+SLJIT_S390X_RILB(larl, 0xc00000000000, 1)
+
+/* LOAD RELATIVE LONG */
+SLJIT_S390X_RILB(lgrl, 0xc40800000000, have_genext())
+
+#undef SLJIT_S390X_RILB
+
+SLJIT_S390X_INSTRUCTION(br, sljit_gpr target)
+{
+ return 0x07f0 | target;
+}
+
+SLJIT_S390X_INSTRUCTION(brc, sljit_uw mask, sljit_sw target)
+{
+ sljit_ins m1 = (sljit_ins)(mask & 0xf) << 20;
+ sljit_ins ri2 = (sljit_ins)target & 0xffff;
+ return 0xa7040000L | m1 | ri2;
+}
+
+SLJIT_S390X_INSTRUCTION(brcl, sljit_uw mask, sljit_sw target)
+{
+ sljit_ins m1 = (sljit_ins)(mask & 0xf) << 36;
+ sljit_ins ri2 = (sljit_ins)target & 0xffffffff;
+ return 0xc00400000000L | m1 | ri2;
+}
+
+SLJIT_S390X_INSTRUCTION(flogr, sljit_gpr dst, sljit_gpr src)
+{
+ SLJIT_ASSERT(have_eimm());
+ return 0xb9830000 | R8A(dst) | R0A(src);
+}
+
+/* INSERT PROGRAM MASK */
+SLJIT_S390X_INSTRUCTION(ipm, sljit_gpr dst)
+{
+ return 0xb2220000 | R4A(dst);
+}
+
+/* SET PROGRAM MASK */
+SLJIT_S390X_INSTRUCTION(spm, sljit_gpr dst)
+{
+ return 0x0400 | R4A(dst);
+}
+
+/* ROTATE THEN INSERT SELECTED BITS HIGH (ZERO) */
+SLJIT_S390X_INSTRUCTION(risbhgz, sljit_gpr dst, sljit_gpr src, sljit_u8 start, sljit_u8 end, sljit_u8 rot)
+{
+ return risbhg(dst, src, start, 0x8 | end, rot);
+}
+
+#undef SLJIT_S390X_INSTRUCTION
+
+static sljit_s32 update_zero_overflow(struct sljit_compiler *compiler, sljit_s32 op, sljit_gpr dst_r)
+{
+ /* Condition codes: bits 18 and 19.
+ Transformation:
+ 0 (zero and no overflow) : unchanged
+ 1 (non-zero and no overflow) : unchanged
+ 2 (zero and overflow) : decreased by 1
+ 3 (non-zero and overflow) : decreased by 1 if non-zero */
+ FAIL_IF(push_inst(compiler, brc(0xc, 2 + 2 + ((op & SLJIT_32) ? 1 : 2) + 2 + 3 + 1)));
+ FAIL_IF(push_inst(compiler, ipm(tmp1)));
+ FAIL_IF(push_inst(compiler, (op & SLJIT_32) ? or(dst_r, dst_r) : ogr(dst_r, dst_r)));
+ FAIL_IF(push_inst(compiler, brc(0x8, 2 + 3)));
+ FAIL_IF(push_inst(compiler, slfi(tmp1, 0x10000000)));
+ FAIL_IF(push_inst(compiler, spm(tmp1)));
+ return SLJIT_SUCCESS;
+}
+
+/* load 64-bit immediate into register without clobbering flags */
+static sljit_s32 push_load_imm_inst(struct sljit_compiler *compiler, sljit_gpr target, sljit_sw v)
+{
+ /* 4 byte instructions */
+ if (is_s16(v))
+ return push_inst(compiler, lghi(target, (sljit_s16)v));
+
+ if (((sljit_uw)v & ~(sljit_uw)0x000000000000ffff) == 0)
+ return push_inst(compiler, llill(target, (sljit_u16)v));
+
+ if (((sljit_uw)v & ~(sljit_uw)0x00000000ffff0000) == 0)
+ return push_inst(compiler, llilh(target, (sljit_u16)(v >> 16)));
+
+ if (((sljit_uw)v & ~(sljit_uw)0x0000ffff00000000) == 0)
+ return push_inst(compiler, llihl(target, (sljit_u16)(v >> 32)));
+
+ if (((sljit_uw)v & ~(sljit_uw)0xffff000000000000) == 0)
+ return push_inst(compiler, llihh(target, (sljit_u16)(v >> 48)));
+
+ if (is_s32(v))
+ return push_inst(compiler, lgfi(target, (sljit_s32)v));
+
+ if (((sljit_uw)v >> 32) == 0)
+ return push_inst(compiler, llilf(target, (sljit_u32)v));
+
+ if (((sljit_uw)v << 32) == 0)
+ return push_inst(compiler, llihf(target, (sljit_u32)((sljit_uw)v >> 32)));
+
+ FAIL_IF(push_inst(compiler, llilf(target, (sljit_u32)v)));
+ return push_inst(compiler, iihf(target, (sljit_u32)(v >> 32)));
+}
+
+struct addr {
+ sljit_gpr base;
+ sljit_gpr index;
+ sljit_s32 offset;
+};
+
+/* transform memory operand into D(X,B) form with a signed 20-bit offset */
+static sljit_s32 make_addr_bxy(struct sljit_compiler *compiler,
+ struct addr *addr, sljit_s32 mem, sljit_sw off,
+ sljit_gpr tmp /* clobbered, must not be r0 */)
+{
+ sljit_gpr base = r0;
+ sljit_gpr index = r0;
+
+ SLJIT_ASSERT(tmp != r0);
+ if (mem & REG_MASK)
+ base = gpr(mem & REG_MASK);
+
+ if (mem & OFFS_REG_MASK) {
+ index = gpr(OFFS_REG(mem));
+ if (off != 0) {
+ /* shift and put the result into tmp */
+ SLJIT_ASSERT(0 <= off && off < 64);
+ FAIL_IF(push_inst(compiler, sllg(tmp, index, (sljit_s32)off, 0)));
+ index = tmp;
+ off = 0; /* clear offset */
+ }
+ }
+ else if (!is_s20(off)) {
+ FAIL_IF(push_load_imm_inst(compiler, tmp, off));
+ index = tmp;
+ off = 0; /* clear offset */
+ }
+ addr->base = base;
+ addr->index = index;
+ addr->offset = (sljit_s32)off;
+ return SLJIT_SUCCESS;
+}
+
+/* transform memory operand into D(X,B) form with an unsigned 12-bit offset */
+static sljit_s32 make_addr_bx(struct sljit_compiler *compiler,
+ struct addr *addr, sljit_s32 mem, sljit_sw off,
+ sljit_gpr tmp /* clobbered, must not be r0 */)
+{
+ sljit_gpr base = r0;
+ sljit_gpr index = r0;
+
+ SLJIT_ASSERT(tmp != r0);
+ if (mem & REG_MASK)
+ base = gpr(mem & REG_MASK);
+
+ if (mem & OFFS_REG_MASK) {
+ index = gpr(OFFS_REG(mem));
+ if (off != 0) {
+ /* shift and put the result into tmp */
+ SLJIT_ASSERT(0 <= off && off < 64);
+ FAIL_IF(push_inst(compiler, sllg(tmp, index, (sljit_s32)off, 0)));
+ index = tmp;
+ off = 0; /* clear offset */
+ }
+ }
+ else if (!is_u12(off)) {
+ FAIL_IF(push_load_imm_inst(compiler, tmp, off));
+ index = tmp;
+ off = 0; /* clear offset */
+ }
+ addr->base = base;
+ addr->index = index;
+ addr->offset = (sljit_s32)off;
+ return SLJIT_SUCCESS;
+}
+
+#define EVAL(op, r, addr) op(r, addr.offset, addr.index, addr.base)
+#define WHEN(cond, r, i1, i2, addr) \
+ (cond) ? EVAL(i1, r, addr) : EVAL(i2, r, addr)
+
+/* May clobber tmp1. */
+static sljit_s32 load_store_op(struct sljit_compiler *compiler, sljit_gpr reg,
+ sljit_s32 mem, sljit_sw memw,
+ sljit_s32 is_32bit, const sljit_ins* forms)
+{
+ struct addr addr;
+
+ SLJIT_ASSERT(mem & SLJIT_MEM);
+
+ if (is_32bit && ((mem & OFFS_REG_MASK) || is_u12(memw) || !is_s20(memw))) {
+ FAIL_IF(make_addr_bx(compiler, &addr, mem, memw, tmp1));
+ return push_inst(compiler, forms[0] | R20A(reg) | R16A(addr.index) | R12A(addr.base) | (sljit_ins)addr.offset);
+ }
+
+ FAIL_IF(make_addr_bxy(compiler, &addr, mem, memw, tmp1));
+ return push_inst(compiler, (is_32bit ? forms[1] : forms[2]) | R36A(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset));
+}
+
+static const sljit_ins load_forms[3] = {
+ 0x58000000 /* l */,
+ 0xe30000000058 /* ly */,
+ 0xe30000000004 /* lg */
+};
+
+static const sljit_ins store_forms[3] = {
+ 0x50000000 /* st */,
+ 0xe30000000050 /* sty */,
+ 0xe30000000024 /* stg */
+};
+
+static const sljit_ins store_byte_forms[3] = {
+ 0x42000000 /* stc */,
+ 0xe30000000072 /* stcy */,
+ 0
+};
+
+static const sljit_ins load_halfword_forms[3] = {
+ 0x48000000 /* lh */,
+ 0xe30000000078 /* lhy */,
+ 0xe30000000015 /* lgh */
+};
+
+/* May clobber tmp1. */
+static SLJIT_INLINE sljit_s32 load_word(struct sljit_compiler *compiler, sljit_gpr dst_r,
+ sljit_s32 src, sljit_sw srcw,
+ sljit_s32 is_32bit)
+{
+ return load_store_op(compiler, dst_r, src, srcw, is_32bit, load_forms);
+}
+
+/* May clobber tmp1. */
+static sljit_s32 load_unsigned_word(struct sljit_compiler *compiler, sljit_gpr dst_r,
+ sljit_s32 src, sljit_sw srcw,
+ sljit_s32 is_32bit)
+{
+ struct addr addr;
+ sljit_ins ins;
+
+ SLJIT_ASSERT(src & SLJIT_MEM);
+
+ FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1));
+
+ ins = is_32bit ? 0xe30000000016 /* llgf */ : 0xe30000000004 /* lg */;
+ return push_inst(compiler, ins | R36A(dst_r) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset));
+}
+
+/* May clobber tmp1. */
+static SLJIT_INLINE sljit_s32 store_word(struct sljit_compiler *compiler, sljit_gpr src_r,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 is_32bit)
+{
+ return load_store_op(compiler, src_r, dst, dstw, is_32bit, store_forms);
+}
+
+/* May clobber tmp1. */
+static SLJIT_INLINE sljit_s32 store_byte(struct sljit_compiler *compiler, sljit_gpr src_r,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ return load_store_op(compiler, src_r, dst, dstw, 1, store_byte_forms);
+}
+
+#undef WHEN
+
+static sljit_s32 emit_move(struct sljit_compiler *compiler,
+ sljit_gpr dst_r,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_gpr src_r;
+
+ SLJIT_ASSERT(!FAST_IS_REG(src) || dst_r != gpr(src & REG_MASK));
+
+ if (src == SLJIT_IMM)
+ return push_load_imm_inst(compiler, dst_r, srcw);
+
+ if (src & SLJIT_MEM)
+ return load_word(compiler, dst_r, src, srcw, (compiler->mode & SLJIT_32) != 0);
+
+ src_r = gpr(src & REG_MASK);
+ return push_inst(compiler, (compiler->mode & SLJIT_32) ? lr(dst_r, src_r) : lgr(dst_r, src_r));
+}
+
+static sljit_s32 emit_rr(struct sljit_compiler *compiler, sljit_ins ins,
+ sljit_s32 dst,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_gpr dst_r = tmp0;
+ sljit_gpr src_r = tmp1;
+ sljit_s32 needs_move = 1;
+
+ if (FAST_IS_REG(dst)) {
+ dst_r = gpr(dst);
+
+ if (dst == src1)
+ needs_move = 0;
+ else if (dst == src2) {
+ dst_r = tmp0;
+ needs_move = 2;
+ }
+ }
+
+ if (needs_move)
+ FAIL_IF(emit_move(compiler, dst_r, src1, src1w));
+
+ if (FAST_IS_REG(src2))
+ src_r = gpr(src2);
+ else
+ FAIL_IF(emit_move(compiler, tmp1, src2, src2w));
+
+ FAIL_IF(push_inst(compiler, ins | R4A(dst_r) | R0A(src_r)));
+
+ if (needs_move != 2)
+ return SLJIT_SUCCESS;
+
+ dst_r = gpr(dst & REG_MASK);
+ return push_inst(compiler, (compiler->mode & SLJIT_32) ? lr(dst_r, tmp0) : lgr(dst_r, tmp0));
+}
+
+static sljit_s32 emit_rr1(struct sljit_compiler *compiler, sljit_ins ins,
+ sljit_s32 dst,
+ sljit_s32 src1, sljit_sw src1w)
+{
+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;
+ sljit_gpr src_r = tmp1;
+
+ if (FAST_IS_REG(src1))
+ src_r = gpr(src1);
+ else
+ FAIL_IF(emit_move(compiler, tmp1, src1, src1w));
+
+ return push_inst(compiler, ins | R4A(dst_r) | R0A(src_r));
+}
+
+static sljit_s32 emit_rrf(struct sljit_compiler *compiler, sljit_ins ins,
+ sljit_s32 dst,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
+ sljit_gpr src1_r = tmp0;
+ sljit_gpr src2_r = tmp1;
+
+ if (FAST_IS_REG(src1))
+ src1_r = gpr(src1);
+ else
+ FAIL_IF(emit_move(compiler, tmp0, src1, src1w));
+
+ if (FAST_IS_REG(src2))
+ src2_r = gpr(src2);
+ else
+ FAIL_IF(emit_move(compiler, tmp1, src2, src2w));
+
+ return push_inst(compiler, ins | R4A(dst_r) | R0A(src1_r) | R12A(src2_r));
+}
+
+typedef enum {
+ RI_A,
+ RIL_A,
+} emit_ril_type;
+
+static sljit_s32 emit_ri(struct sljit_compiler *compiler, sljit_ins ins,
+ sljit_s32 dst,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_sw src2w,
+ emit_ril_type type)
+{
+ sljit_gpr dst_r = tmp0;
+ sljit_s32 needs_move = 1;
+
+ if (FAST_IS_REG(dst)) {
+ dst_r = gpr(dst);
+
+ if (dst == src1)
+ needs_move = 0;
+ }
+
+ if (needs_move)
+ FAIL_IF(emit_move(compiler, dst_r, src1, src1w));
+
+ if (type == RIL_A)
+ return push_inst(compiler, ins | R36A(dst_r) | (src2w & 0xffffffff));
+ return push_inst(compiler, ins | R20A(dst_r) | (src2w & 0xffff));
+}
+
+static sljit_s32 emit_rie_d(struct sljit_compiler *compiler, sljit_ins ins,
+ sljit_s32 dst,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_sw src2w)
+{
+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;
+ sljit_gpr src_r = tmp0;
+
+ if (!FAST_IS_REG(src1))
+ FAIL_IF(emit_move(compiler, tmp0, src1, src1w));
+ else
+ src_r = gpr(src1 & REG_MASK);
+
+ return push_inst(compiler, ins | R36A(dst_r) | R32A(src_r) | (sljit_ins)(src2w & 0xffff) << 16);
+}
+
+typedef enum {
+ RX_A,
+ RXY_A,
+} emit_rx_type;
+
+static sljit_s32 emit_rx(struct sljit_compiler *compiler, sljit_ins ins,
+ sljit_s32 dst,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ emit_rx_type type)
+{
+ sljit_gpr dst_r = tmp0;
+ sljit_s32 needs_move = 1;
+ sljit_gpr base, index;
+
+ SLJIT_ASSERT(src2 & SLJIT_MEM);
+
+ if (FAST_IS_REG(dst)) {
+ dst_r = gpr(dst);
+
+ if (dst == src1)
+ needs_move = 0;
+ else if (dst == (src2 & REG_MASK) || (dst == OFFS_REG(src2))) {
+ dst_r = tmp0;
+ needs_move = 2;
+ }
+ }
+
+ if (needs_move)
+ FAIL_IF(emit_move(compiler, dst_r, src1, src1w));
+
+ base = gpr(src2 & REG_MASK);
+ index = tmp0;
+
+ if (src2 & OFFS_REG_MASK) {
+ index = gpr(OFFS_REG(src2));
+
+ if (src2w != 0) {
+ FAIL_IF(push_inst(compiler, sllg(tmp1, index, src2w & 0x3, 0)));
+ src2w = 0;
+ index = tmp1;
+ }
+ } else if ((type == RX_A && !is_u12(src2w)) || (type == RXY_A && !is_s20(src2w))) {
+ FAIL_IF(push_load_imm_inst(compiler, tmp1, src2w));
+
+ if (src2 & REG_MASK)
+ index = tmp1;
+ else
+ base = tmp1;
+ src2w = 0;
+ }
+
+ if (type == RX_A)
+ ins |= R20A(dst_r) | R16A(index) | R12A(base) | (sljit_ins)src2w;
+ else
+ ins |= R36A(dst_r) | R32A(index) | R28A(base) | disp_s20((sljit_s32)src2w);
+
+ FAIL_IF(push_inst(compiler, ins));
+
+ if (needs_move != 2)
+ return SLJIT_SUCCESS;
+
+ dst_r = gpr(dst);
+ return push_inst(compiler, (compiler->mode & SLJIT_32) ? lr(dst_r, tmp0) : lgr(dst_r, tmp0));
+}
+
+static sljit_s32 emit_siy(struct sljit_compiler *compiler, sljit_ins ins,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw srcw)
+{
+ sljit_gpr dst_r = tmp1;
+
+ SLJIT_ASSERT(dst & SLJIT_MEM);
+
+ if (dst & OFFS_REG_MASK) {
+ sljit_gpr index = tmp1;
+
+ if ((dstw & 0x3) == 0)
+ index = gpr(OFFS_REG(dst));
+ else
+ FAIL_IF(push_inst(compiler, sllg(tmp1, index, dstw & 0x3, 0)));
+
+ FAIL_IF(push_inst(compiler, la(tmp1, 0, dst_r, index)));
+ dstw = 0;
+ }
+ else if (!is_s20(dstw)) {
+ FAIL_IF(push_load_imm_inst(compiler, tmp1, dstw));
+
+ if (dst & REG_MASK)
+ FAIL_IF(push_inst(compiler, la(tmp1, 0, dst_r, tmp1)));
+
+ dstw = 0;
+ }
+ else
+ dst_r = gpr(dst & REG_MASK);
+
+ return push_inst(compiler, ins | ((sljit_ins)(srcw & 0xff) << 32) | R28A(dst_r) | disp_s20((sljit_s32)dstw));
+}
+
+struct ins_forms {
+ sljit_ins op_r;
+ sljit_ins op_gr;
+ sljit_ins op_rk;
+ sljit_ins op_grk;
+ sljit_ins op;
+ sljit_ins op_y;
+ sljit_ins op_g;
+};
+
+static sljit_s32 emit_commutative(struct sljit_compiler *compiler, const struct ins_forms *forms,
+ sljit_s32 dst,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 mode = compiler->mode;
+ sljit_ins ins, ins_k;
+
+ if ((src1 | src2) & SLJIT_MEM) {
+ sljit_ins ins12, ins20;
+
+ if (mode & SLJIT_32) {
+ ins12 = forms->op;
+ ins20 = forms->op_y;
+ }
+ else {
+ ins12 = 0;
+ ins20 = forms->op_g;
+ }
+
+ if (ins12 && ins20) {
+ /* Extra instructions needed for address computation can be executed independently. */
+ if ((src2 & SLJIT_MEM) && (!(src1 & SLJIT_MEM)
+ || ((src1 & OFFS_REG_MASK) ? (src1w & 0x3) == 0 : is_s20(src1w)))) {
+ if ((src2 & OFFS_REG_MASK) || is_u12(src2w) || !is_s20(src2w))
+ return emit_rx(compiler, ins12, dst, src1, src1w, src2, src2w, RX_A);
+
+ return emit_rx(compiler, ins20, dst, src1, src1w, src2, src2w, RXY_A);
+ }
+
+ if (src1 & SLJIT_MEM) {
+ if ((src1 & OFFS_REG_MASK) || is_u12(src1w) || !is_s20(src1w))
+ return emit_rx(compiler, ins12, dst, src2, src2w, src1, src1w, RX_A);
+
+ return emit_rx(compiler, ins20, dst, src2, src2w, src1, src1w, RXY_A);
+ }
+ }
+ else if (ins12 || ins20) {
+ emit_rx_type rx_type;
+
+ if (ins12) {
+ rx_type = RX_A;
+ ins = ins12;
+ }
+ else {
+ rx_type = RXY_A;
+ ins = ins20;
+ }
+
+ if ((src2 & SLJIT_MEM) && (!(src1 & SLJIT_MEM)
+ || ((src1 & OFFS_REG_MASK) ? (src1w & 0x3) == 0 : (rx_type == RX_A ? is_u12(src1w) : is_s20(src1w)))))
+ return emit_rx(compiler, ins, dst, src1, src1w, src2, src2w, rx_type);
+
+ if (src1 & SLJIT_MEM)
+ return emit_rx(compiler, ins, dst, src2, src2w, src1, src1w, rx_type);
+ }
+ }
+
+ if (mode & SLJIT_32) {
+ ins = forms->op_r;
+ ins_k = forms->op_rk;
+ }
+ else {
+ ins = forms->op_gr;
+ ins_k = forms->op_grk;
+ }
+
+ SLJIT_ASSERT(ins != 0 || ins_k != 0);
+
+ if (ins && FAST_IS_REG(dst)) {
+ if (dst == src1)
+ return emit_rr(compiler, ins, dst, src1, src1w, src2, src2w);
+
+ if (dst == src2)
+ return emit_rr(compiler, ins, dst, src2, src2w, src1, src1w);
+ }
+
+ if (ins_k == 0)
+ return emit_rr(compiler, ins, dst, src1, src1w, src2, src2w);
+
+ return emit_rrf(compiler, ins_k, dst, src1, src1w, src2, src2w);
+}
+
+static sljit_s32 emit_non_commutative(struct sljit_compiler *compiler, const struct ins_forms *forms,
+ sljit_s32 dst,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 mode = compiler->mode;
+ sljit_ins ins;
+
+ if (src2 & SLJIT_MEM) {
+ sljit_ins ins12, ins20;
+
+ if (mode & SLJIT_32) {
+ ins12 = forms->op;
+ ins20 = forms->op_y;
+ }
+ else {
+ ins12 = 0;
+ ins20 = forms->op_g;
+ }
+
+ if (ins12 && ins20) {
+ if ((src2 & OFFS_REG_MASK) || is_u12(src2w) || !is_s20(src2w))
+ return emit_rx(compiler, ins12, dst, src1, src1w, src2, src2w, RX_A);
+
+ return emit_rx(compiler, ins20, dst, src1, src1w, src2, src2w, RXY_A);
+ }
+ else if (ins12)
+ return emit_rx(compiler, ins12, dst, src1, src1w, src2, src2w, RX_A);
+ else if (ins20)
+ return emit_rx(compiler, ins20, dst, src1, src1w, src2, src2w, RXY_A);
+ }
+
+ ins = (mode & SLJIT_32) ? forms->op_rk : forms->op_grk;
+
+ if (ins == 0 || (FAST_IS_REG(dst) && dst == src1))
+ return emit_rr(compiler, (mode & SLJIT_32) ? forms->op_r : forms->op_gr, dst, src1, src1w, src2, src2w);
+
+ return emit_rrf(compiler, ins, dst, src1, src1w, src2, src2w);
+}
+
+static SLJIT_INLINE sljit_u16 *process_extended_label(sljit_u16 *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_u16*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
+{
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+ sljit_sw executable_offset;
+ sljit_uw ins_size = compiler->size << 1;
+ sljit_uw pool_size = 0; /* literal pool */
+ sljit_uw pad_size;
+ sljit_uw half_count;
+ SLJIT_NEXT_DEFINE_TYPES;
+ struct sljit_memory_fragment *buf;
+ sljit_ins *buf_ptr;
+ sljit_ins *buf_end;
+ sljit_u16 *code;
+ sljit_u16 *code_ptr;
+ sljit_uw *pool, *pool_ptr;
+ sljit_ins ins;
+ sljit_sw source, offset;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
+ reverse_buf(compiler);
+
+ jump = compiler->jumps;
+ while (jump != NULL) {
+ if (jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR)) {
+ /* encoded: */
+ /* brasl %r14, (or brcl , ) */
+ /* replace with: */
+ /* lgrl %r1, */
+ /* bras %r14, %r1 (or bcr , %r1) */
+ if (((jump->flags & SLJIT_REWRITABLE_JUMP) || !is_s32(jump->u.target)))
+ pool_size += sizeof(sljit_uw);
+ else
+ jump->flags |= PATCH_IMM32;
+
+ if (!(jump->flags & JUMP_MOV_ADDR))
+ ins_size += 2;
+ }
+ jump = jump->next;
+ }
+
+ /* pad code size to 8 bytes so is accessible with half word offsets */
+ /* the literal pool needs to be doubleword aligned */
+ pad_size = ((ins_size + 7UL) & ~7UL) - ins_size;
+ SLJIT_ASSERT(pad_size < 8UL);
+
+ /* allocate target buffer */
+ code = (sljit_u16*)allocate_executable_memory(ins_size + pad_size + pool_size, options, exec_allocator_data, &executable_offset);
+ PTR_FAIL_WITH_EXEC_IF(code);
+ code_ptr = code;
+
+ /* TODO(carenas): pool is optional, and the ABI recommends it to
+ * be created before the function code, instead of
+ * globally; if generated code is too big could
+ * need offsets bigger than 32bit words and asser()
+ */
+ pool = (sljit_uw *)((sljit_uw)code + ins_size + pad_size);
+ pool_ptr = pool;
+ buf = compiler->buf;
+ half_count = 0;
+
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+ SLJIT_NEXT_INIT_TYPES();
+ SLJIT_GET_NEXT_MIN();
+
+ do {
+ buf_ptr = (sljit_ins*)buf->memory;
+ buf_end = buf_ptr + (buf->used_size >> 3);
+ do {
+ ins = *buf_ptr++;
+
+ if (next_min_addr == half_count) {
+ SLJIT_ASSERT(!label || label->size >= half_count);
+ SLJIT_ASSERT(!jump || jump->addr >= half_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= half_count);
+
+ if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ if (next_min_addr == next_jump_addr) {
+ jump->addr = (sljit_uw)code_ptr;
+
+ if (SLJIT_UNLIKELY(jump->flags & JUMP_MOV_ADDR)) {
+ if (jump->flags & PATCH_IMM32) {
+ SLJIT_ASSERT((jump->flags & JUMP_ADDR) && is_s32(jump->u.target));
+ ins = 0xc00100000000 /* lgfi */ | (ins & 0xf000000000);
+ } else if (jump->flags & JUMP_ADDR) {
+ source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ offset = (sljit_sw)(jump->u.target - (sljit_uw)source);
+
+ if ((offset & 0x1) != 0 || offset > 0xffffffffl || offset < -0x100000000l) {
+ jump->addr = (sljit_uw)pool_ptr;
+ jump->flags |= PATCH_POOL;
+
+ /* store target into pool */
+ offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source;
+ pool_ptr++;
+
+ SLJIT_ASSERT(!(offset & 1));
+ offset >>= 1;
+ SLJIT_ASSERT(is_s32(offset));
+ ins = 0xc40800000000 /* lgrl */ | (ins & 0xf000000000) | (sljit_ins)(offset & 0xffffffff);
+ }
+ }
+ } else if (jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR)) {
+ source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
+ if (jump->flags & PATCH_IMM32) {
+ SLJIT_ASSERT((jump->flags & JUMP_ADDR) && is_s32(jump->u.target));
+ code_ptr[0] = (sljit_u16)(0xc001 /* lgfi */ | R4A(tmp1));
+ code_ptr += 3;
+ } else if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {
+ offset = (sljit_sw)(jump->u.target - (sljit_uw)source);
+
+ if ((offset & 0x1) != 0 || offset > 0xffffffffl || offset < -0x100000000l)
+ jump->flags |= PATCH_POOL;
+ } else
+ jump->flags |= PATCH_POOL;
+
+ if (jump->flags & PATCH_POOL) {
+ jump->addr = (sljit_uw)pool_ptr;
+
+ /* load address into tmp1 */
+ offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source;
+
+ SLJIT_ASSERT(!(offset & 1));
+ offset >>= 1;
+ SLJIT_ASSERT(is_s32(offset));
+
+ code_ptr[0] = (sljit_u16)(0xc408 /* lgrl */ | R4A(tmp1));
+ code_ptr[1] = (sljit_u16)(offset >> 16);
+ code_ptr[2] = (sljit_u16)offset;
+ code_ptr += 3;
+ pool_ptr++;
+ }
+
+ if (jump->flags & (PATCH_POOL | PATCH_IMM32)) {
+ /* branch to tmp1 */
+ if (((ins >> 32) & 0xf) == 4) {
+ /* brcl -> bcr */
+ ins = 0x0700 /* bcr */ | ((ins >> 32) & 0xf0) | R0A(tmp1);
+ } else {
+ SLJIT_ASSERT(((ins >> 32) & 0xf) == 5);
+ /* brasl -> basr */
+ ins = 0x0d00 /* basr */ | ((ins >> 32) & 0xf0) | R0A(tmp1);
+ }
+
+ /* Adjust half_count. */
+ half_count += 2;
+ }
+ }
+
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ } else if (next_min_addr == next_const_addr) {
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
+ }
+
+ SLJIT_GET_NEXT_MIN();
+ }
+
+ if (ins & 0xffff00000000L) {
+ *code_ptr++ = (sljit_u16)(ins >> 32);
+ half_count++;
+ }
+
+ if (ins & 0xffffffff0000L) {
+ *code_ptr++ = (sljit_u16)(ins >> 16);
+ half_count++;
+ }
+
+ *code_ptr++ = (sljit_u16)ins;
+ half_count++;
+ } while (buf_ptr < buf_end);
+
+ buf = buf->next;
+ } while (buf);
+
+ if (next_label_size == half_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label = label->next;
+ }
+
+ SLJIT_ASSERT(!label);
+ SLJIT_ASSERT(!jump);
+ SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(code_ptr <= code + (ins_size >> 1));
+ SLJIT_ASSERT((sljit_u8 *)pool_ptr <= (sljit_u8 *)pool + pool_size);
+
+ jump = compiler->jumps;
+ while (jump != NULL) {
+ offset = (sljit_sw)((jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr);
+
+ if (!(jump->flags & (PATCH_POOL | PATCH_IMM32))) {
+ code_ptr = (sljit_u16*)jump->addr;
+ offset -= (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
+ /* Offset must be halfword aligned. */
+ SLJIT_ASSERT(!(offset & 1));
+ offset >>= 1;
+ SLJIT_ASSERT(is_s32(offset)); /* TODO(mundaym): handle arbitrary offsets */
+
+ code_ptr[1] = (sljit_u16)(offset >> 16);
+ code_ptr[2] = (sljit_u16)offset;
+ } else if (jump->flags & PATCH_POOL) {
+ /* Store jump target into pool. */
+ *(sljit_uw*)(jump->addr) = (sljit_uw)offset;
+ } else {
+ SLJIT_ASSERT(is_s32(offset));
+ code_ptr = (sljit_u16*)jump->addr;
+ code_ptr[1] = (sljit_u16)(offset >> 16);
+ code_ptr[2] = (sljit_u16)offset;
+ }
+ jump = jump->next;
+ }
+
+ compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
+ compiler->executable_size = ins_size;
+ if (pool_size)
+ compiler->executable_size += (pad_size + pool_size);
+
+ code = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+ code_ptr = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ SLJIT_CACHE_FLUSH(code, code_ptr);
+ SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
+ return code;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ /* TODO(mundaym): implement all */
+ switch (feature_type) {
+ case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return (SLJIT_IS_FPU_AVAILABLE) != 0;
+#else
+ return 1;
+#endif /* SLJIT_IS_FPU_AVAILABLE */
+
+ case SLJIT_HAS_CLZ:
+ case SLJIT_HAS_REV:
+ case SLJIT_HAS_ROT:
+ case SLJIT_HAS_PREFETCH:
+ case SLJIT_HAS_COPY_F32:
+ case SLJIT_HAS_COPY_F64:
+ case SLJIT_HAS_SIMD:
+ case SLJIT_HAS_ATOMIC:
+ case SLJIT_HAS_MEMORY_BARRIER:
+ return 1;
+
+ case SLJIT_HAS_CTZ:
+ return 2;
+
+ case SLJIT_HAS_CMOV:
+ return have_lscond1() ? 1 : 0;
+ }
+ return 0;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
+{
+ SLJIT_UNUSED_ARG(type);
+ return 0;
+}
+
+/* --------------------------------------------------------------------- */
+/* Entry, exit */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 fscratches;
+ sljit_s32 fsaveds;
+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
+ sljit_s32 offset, i, tmp;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ /* Saved registers are stored in callee allocated save area. */
+ SLJIT_ASSERT(gpr(SLJIT_FIRST_SAVED_REG) == r6 && gpr(SLJIT_S0) == r13);
+
+ scratches = ENTER_GET_REGS(scratches);
+ saveds = ENTER_GET_REGS(saveds);
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+
+ offset = 2 * SSIZE_OF(sw);
+ if (saveds + scratches >= SLJIT_NUMBER_OF_REGISTERS) {
+ if (saved_arg_count == 0) {
+ FAIL_IF(push_inst(compiler, stmg(r6, r14, offset, r15)));
+ offset += 9 * SSIZE_OF(sw);
+ } else {
+ FAIL_IF(push_inst(compiler, stmg(r6, r13 - (sljit_gpr)saved_arg_count, offset, r15)));
+ offset += (8 - saved_arg_count) * SSIZE_OF(sw);
+ }
+ } else {
+ if (scratches == SLJIT_FIRST_SAVED_REG) {
+ FAIL_IF(push_inst(compiler, stg(r6, offset, 0, r15)));
+ offset += SSIZE_OF(sw);
+ } else if (scratches > SLJIT_FIRST_SAVED_REG) {
+ FAIL_IF(push_inst(compiler, stmg(r6, r6 + (sljit_gpr)(scratches - SLJIT_FIRST_SAVED_REG), offset, r15)));
+ offset += (scratches - (SLJIT_FIRST_SAVED_REG - 1)) * SSIZE_OF(sw);
+ }
+
+ if (saved_arg_count == 0) {
+ if (saveds == 0) {
+ FAIL_IF(push_inst(compiler, stg(r14, offset, 0, r15)));
+ offset += SSIZE_OF(sw);
+ } else {
+ FAIL_IF(push_inst(compiler, stmg(r14 - (sljit_gpr)saveds, r14, offset, r15)));
+ offset += (saveds + 1) * SSIZE_OF(sw);
+ }
+ } else if (saveds > saved_arg_count) {
+ if (saveds == saved_arg_count + 1) {
+ FAIL_IF(push_inst(compiler, stg(r14 - (sljit_gpr)saveds, offset, 0, r15)));
+ offset += SSIZE_OF(sw);
+ } else {
+ FAIL_IF(push_inst(compiler, stmg(r14 - (sljit_gpr)saveds, r13 - (sljit_gpr)saved_arg_count, offset, r15)));
+ offset += (saveds - saved_arg_count) * SSIZE_OF(sw);
+ }
+ }
+ }
+
+ if (saved_arg_count > 0) {
+ FAIL_IF(push_inst(compiler, stg(r14, offset, 0, r15)));
+ offset += SSIZE_OF(sw);
+ }
+
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ FAIL_IF(push_inst(compiler, 0x60000000 /* std */ | F20(i) | R12A(r15) | (sljit_ins)offset));
+ offset += SSIZE_OF(sw);
+ }
+
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ FAIL_IF(push_inst(compiler, 0x60000000 /* std */ | F20(i) | R12A(r15) | (sljit_ins)offset));
+ offset += SSIZE_OF(sw);
+ }
+
+ local_size = (local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE + 0xf) & ~0xf;
+ compiler->local_size = local_size;
+
+ if (is_s20(-local_size))
+ FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(-local_size)));
+ else
+ FAIL_IF(push_inst(compiler, 0xc20400000000 /* slgfi */ | R36A(r15) | (sljit_ins)local_size));
+
+ if (options & SLJIT_ENTER_REG_ARG)
+ return SLJIT_SUCCESS;
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ saved_arg_count = 0;
+ tmp = 0;
+ while (arg_types > 0) {
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ FAIL_IF(push_inst(compiler, lgr(gpr(SLJIT_S0 - saved_arg_count), gpr(SLJIT_R0 + tmp))));
+ saved_arg_count++;
+ }
+ tmp++;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ compiler->local_size = (local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE + 0xf) & ~0xf;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_gpr last_reg)
+{
+ sljit_s32 offset, i, tmp;
+ sljit_s32 local_size = compiler->local_size;
+ sljit_s32 saveds = compiler->saveds;
+ sljit_s32 scratches = compiler->scratches;
+ sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);
+
+ if (is_u12(local_size))
+ FAIL_IF(push_inst(compiler, 0x41000000 /* ly */ | R20A(r15) | R12A(r15) | (sljit_ins)local_size));
+ else if (is_s20(local_size))
+ FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(local_size)));
+ else
+ FAIL_IF(push_inst(compiler, 0xc20a00000000 /* algfi */ | R36A(r15) | (sljit_ins)local_size));
+
+ offset = 2 * SSIZE_OF(sw);
+ if (saveds + scratches >= SLJIT_NUMBER_OF_REGISTERS) {
+ if (kept_saveds_count == 0) {
+ FAIL_IF(push_inst(compiler, lmg(r6, last_reg, offset, r15)));
+ offset += 9 * SSIZE_OF(sw);
+ } else {
+ FAIL_IF(push_inst(compiler, lmg(r6, r13 - (sljit_gpr)kept_saveds_count, offset, r15)));
+ offset += (8 - kept_saveds_count) * SSIZE_OF(sw);
+ }
+ } else {
+ if (scratches == SLJIT_FIRST_SAVED_REG) {
+ FAIL_IF(push_inst(compiler, lg(r6, offset, 0, r15)));
+ offset += SSIZE_OF(sw);
+ } else if (scratches > SLJIT_FIRST_SAVED_REG) {
+ FAIL_IF(push_inst(compiler, lmg(r6, r6 + (sljit_gpr)(scratches - SLJIT_FIRST_SAVED_REG), offset, r15)));
+ offset += (scratches - (SLJIT_FIRST_SAVED_REG - 1)) * SSIZE_OF(sw);
+ }
+
+ if (kept_saveds_count == 0) {
+ if (saveds == 0) {
+ if (last_reg == r14)
+ FAIL_IF(push_inst(compiler, lg(r14, offset, 0, r15)));
+ offset += SSIZE_OF(sw);
+ } else if (saveds == 1 && last_reg == r13) {
+ FAIL_IF(push_inst(compiler, lg(r13, offset, 0, r15)));
+ offset += 2 * SSIZE_OF(sw);
+ } else {
+ FAIL_IF(push_inst(compiler, lmg(r14 - (sljit_gpr)saveds, last_reg, offset, r15)));
+ offset += (saveds + 1) * SSIZE_OF(sw);
+ }
+ } else if (saveds > kept_saveds_count) {
+ if (saveds == kept_saveds_count + 1) {
+ FAIL_IF(push_inst(compiler, lg(r14 - (sljit_gpr)saveds, offset, 0, r15)));
+ offset += SSIZE_OF(sw);
+ } else {
+ FAIL_IF(push_inst(compiler, lmg(r14 - (sljit_gpr)saveds, r13 - (sljit_gpr)kept_saveds_count, offset, r15)));
+ offset += (saveds - kept_saveds_count) * SSIZE_OF(sw);
+ }
+ }
+ }
+
+ if (kept_saveds_count > 0) {
+ if (last_reg == r14)
+ FAIL_IF(push_inst(compiler, lg(r14, offset, 0, r15)));
+ offset += SSIZE_OF(sw);
+ }
+
+ tmp = SLJIT_FS0 - compiler->fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ FAIL_IF(push_inst(compiler, 0x68000000 /* ld */ | F20(i) | R12A(r15) | (sljit_ins)offset));
+ offset += SSIZE_OF(sw);
+ }
+
+ for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ FAIL_IF(push_inst(compiler, 0x68000000 /* ld */ | F20(i) | R12A(r15) | (sljit_ins)offset));
+ offset += SSIZE_OF(sw);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ FAIL_IF(emit_stack_frame_release(compiler, r14));
+ return push_inst(compiler, br(r14)); /* return */
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(load_word(compiler, tmp1, src, srcw, 0 /* 64-bit */));
+ src = TMP_REG2;
+ srcw = 0;
+ } else if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst(compiler, lgr(tmp1, gpr(src))));
+ src = TMP_REG2;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, r13));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
+}
+
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
+{
+ sljit_gpr arg0 = gpr(SLJIT_R0);
+ sljit_gpr arg1 = gpr(SLJIT_R1);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op0(compiler, op));
+
+ op = GET_OPCODE(op) | (op & SLJIT_32);
+ switch (op) {
+ case SLJIT_BREAKPOINT:
+ /* The following invalid instruction is emitted by gdb. */
+ return push_inst(compiler, 0x0001 /* 2-byte trap */);
+ case SLJIT_NOP:
+ return push_inst(compiler, 0x0700 /* 2-byte nop */);
+ case SLJIT_LMUL_UW:
+ FAIL_IF(push_inst(compiler, mlgr(arg0, arg0)));
+ break;
+ case SLJIT_LMUL_SW:
+ /* signed multiplication from: */
+ /* Hacker's Delight, Second Edition: Chapter 8-3. */
+ FAIL_IF(push_inst(compiler, srag(tmp0, arg0, 63, 0)));
+ FAIL_IF(push_inst(compiler, srag(tmp1, arg1, 63, 0)));
+ FAIL_IF(push_inst(compiler, ngr(tmp0, arg1)));
+ FAIL_IF(push_inst(compiler, ngr(tmp1, arg0)));
+
+ /* unsigned multiplication */
+ FAIL_IF(push_inst(compiler, mlgr(arg0, arg0)));
+
+ FAIL_IF(push_inst(compiler, sgr(arg0, tmp0)));
+ FAIL_IF(push_inst(compiler, sgr(arg0, tmp1)));
+ break;
+ case SLJIT_DIV_U32:
+ case SLJIT_DIVMOD_U32:
+ FAIL_IF(push_inst(compiler, lhi(tmp0, 0)));
+ FAIL_IF(push_inst(compiler, lr(tmp1, arg0)));
+ FAIL_IF(push_inst(compiler, dlr(tmp0, arg1)));
+ FAIL_IF(push_inst(compiler, lr(arg0, tmp1))); /* quotient */
+ if (op == SLJIT_DIVMOD_U32)
+ return push_inst(compiler, lr(arg1, tmp0)); /* remainder */
+
+ return SLJIT_SUCCESS;
+ case SLJIT_DIV_S32:
+ case SLJIT_DIVMOD_S32:
+ FAIL_IF(push_inst(compiler, 0xeb00000000dc /* srak */ | R36A(tmp0) | R32A(arg0) | (31 << 16)));
+ FAIL_IF(push_inst(compiler, lr(tmp1, arg0)));
+ FAIL_IF(push_inst(compiler, dr(tmp0, arg1)));
+ FAIL_IF(push_inst(compiler, lr(arg0, tmp1))); /* quotient */
+ if (op == SLJIT_DIVMOD_S32)
+ return push_inst(compiler, lr(arg1, tmp0)); /* remainder */
+
+ return SLJIT_SUCCESS;
+ case SLJIT_DIV_UW:
+ case SLJIT_DIVMOD_UW:
+ FAIL_IF(push_inst(compiler, lghi(tmp0, 0)));
+ FAIL_IF(push_inst(compiler, lgr(tmp1, arg0)));
+ FAIL_IF(push_inst(compiler, dlgr(tmp0, arg1)));
+ FAIL_IF(push_inst(compiler, lgr(arg0, tmp1))); /* quotient */
+ if (op == SLJIT_DIVMOD_UW)
+ return push_inst(compiler, lgr(arg1, tmp0)); /* remainder */
+
+ return SLJIT_SUCCESS;
+ case SLJIT_DIV_SW:
+ case SLJIT_DIVMOD_SW:
+ FAIL_IF(push_inst(compiler, lgr(tmp1, arg0)));
+ FAIL_IF(push_inst(compiler, dsgr(tmp0, arg1)));
+ FAIL_IF(push_inst(compiler, lgr(arg0, tmp1))); /* quotient */
+ if (op == SLJIT_DIVMOD_SW)
+ return push_inst(compiler, lgr(arg1, tmp0)); /* remainder */
+
+ return SLJIT_SUCCESS;
+ case SLJIT_MEMORY_BARRIER:
+ return push_inst(compiler, 0x0700 /* bcr */ | (0xe << 4) | 0);
+ case SLJIT_ENDBR:
+ return SLJIT_SUCCESS;
+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
+ return SLJIT_SUCCESS;
+ default:
+ SLJIT_UNREACHABLE();
+ }
+ /* swap result registers */
+ FAIL_IF(push_inst(compiler, lgr(tmp0, arg0)));
+ FAIL_IF(push_inst(compiler, lgr(arg0, arg1)));
+ return push_inst(compiler, lgr(arg1, tmp0));
+}
+
+static sljit_s32 sljit_emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_gpr dst_r, sljit_gpr src_r)
+{
+ sljit_s32 is_ctz = (GET_OPCODE(op) == SLJIT_CTZ);
+
+ if ((op & SLJIT_32) && src_r != tmp0) {
+ FAIL_IF(push_inst(compiler, 0xb9160000 /* llgfr */ | R4A(tmp0) | R0A(src_r)));
+ src_r = tmp0;
+ }
+
+ if (is_ctz) {
+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? 0x1300 /* lcr */ : 0xb9030000 /* lcgr */) | R4A(tmp1) | R0A(src_r)));
+
+ if (src_r == tmp0)
+ FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? 0x1400 /* nr */ : 0xb9800000 /* ngr */) | R4A(tmp0) | R0A(tmp1)));
+ else
+ FAIL_IF(push_inst(compiler, 0xb9e40000 /* ngrk */ | R12A(tmp1) | R4A(tmp0) | R0A(src_r)));
+
+ src_r = tmp0;
+ }
+
+ FAIL_IF(push_inst(compiler, 0xb9830000 /* flogr */ | R4A(tmp0) | R0A(src_r)));
+
+ if (is_ctz)
+ FAIL_IF(push_inst(compiler, 0xec00000000d9 /* aghik */ | R36A(tmp1) | R32A(tmp0) | ((sljit_ins)(-64 & 0xffff) << 16)));
+
+ if (op & SLJIT_32) {
+ if (!is_ctz && dst_r != tmp0)
+ return push_inst(compiler, 0xec00000000d9 /* aghik */ | R36A(dst_r) | R32A(tmp0) | ((sljit_ins)(-32 & 0xffff) << 16));
+
+ FAIL_IF(push_inst(compiler, 0xc20800000000 /* agfi */ | R36A(tmp0) | (sljit_u32)-32));
+ }
+
+ if (is_ctz)
+ FAIL_IF(push_inst(compiler, 0xec0000000057 /* rxsbg */ | R36A(tmp0) | R32A(tmp1) | ((sljit_ins)((op & SLJIT_32) ? 59 : 58) << 24) | (63 << 16) | ((sljit_ins)((op & SLJIT_32) ? 5 : 6) << 8)));
+
+ if (dst_r == tmp0)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, ((op & SLJIT_32) ? 0x1800 /* lr */ : 0xb9040000 /* lgr */) | R4A(dst_r) | R0A(tmp0));
+}
+
+static sljit_s32 sljit_emit_rev(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ struct addr addr;
+ sljit_gpr reg;
+ sljit_ins ins;
+ sljit_s32 opcode = GET_OPCODE(op);
+ sljit_s32 is_16bit = (opcode == SLJIT_REV_U16 || opcode == SLJIT_REV_S16);
+
+ if (dst & SLJIT_MEM) {
+ if (src & SLJIT_MEM) {
+ FAIL_IF(load_store_op(compiler, tmp0, src, srcw, op & SLJIT_32, is_16bit ? load_halfword_forms : load_forms));
+ reg = tmp0;
+ } else
+ reg = gpr(src);
+
+ FAIL_IF(make_addr_bxy(compiler, &addr, dst, dstw, tmp1));
+
+ if (is_16bit)
+ ins = 0xe3000000003f /* strvh */;
+ else
+ ins = (op & SLJIT_32) ? 0xe3000000003e /* strv */ : 0xe3000000002f /* strvg */;
+
+ return push_inst(compiler, ins | R36A(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset));
+ }
+
+ reg = gpr(dst);
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1));
+
+ if (is_16bit)
+ ins = 0xe3000000001f /* lrvh */;
+ else
+ ins = (op & SLJIT_32) ? 0xe3000000001e /* lrv */ : 0xe3000000000f /* lrvg */;
+
+ FAIL_IF(push_inst(compiler, ins | R36A(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)));
+
+ if (opcode == SLJIT_REV)
+ return SLJIT_SUCCESS;
+
+ if (is_16bit) {
+ if (op & SLJIT_32)
+ ins = (opcode == SLJIT_REV_U16) ? 0xb9950000 /* llhr */ : 0xb9270000 /* lhr */;
+ else
+ ins = (opcode == SLJIT_REV_U16) ? 0xb9850000 /* llghr */ : 0xb9070000 /* lghr */;
+ } else
+ ins = (opcode == SLJIT_REV_U32) ? 0xb9160000 /* llgfr */ : 0xb9140000 /* lgfr */;
+
+ return push_inst(compiler, ins | R4A(reg) | R0A(reg));
+ }
+
+ ins = (op & SLJIT_32) ? 0xb91f0000 /* lrvr */ : 0xb90f0000 /* lrvgr */;
+ FAIL_IF(push_inst(compiler, ins | R4A(reg) | R0A(gpr(src))));
+
+ if (opcode == SLJIT_REV)
+ return SLJIT_SUCCESS;
+
+ if (!is_16bit) {
+ ins = (opcode == SLJIT_REV_U32) ? 0xb9160000 /* llgfr */ : 0xb9140000 /* lgfr */;
+ return push_inst(compiler, ins | R4A(reg) | R0A(reg));
+ }
+
+ if (op & SLJIT_32) {
+ ins = (opcode == SLJIT_REV_U16) ? 0x88000000 /* srl */ : 0x8a000000 /* sra */;
+ return push_inst(compiler, ins | R20A(reg) | 16);
+ }
+
+ ins = (opcode == SLJIT_REV_U16) ? 0xeb000000000c /* srlg */ : 0xeb000000000a /* srag */;
+ return push_inst(compiler, ins | R36A(reg) | R32A(reg) | (48 << 16));
+}
+
+/* LEVAL will be defined later with different parameters as needed */
+#define WHEN2(cond, i1, i2) (cond) ? LEVAL(i1) : LEVAL(i2)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins ins;
+ struct addr mem;
+ sljit_gpr dst_r;
+ sljit_gpr src_r;
+ sljit_s32 opcode = GET_OPCODE(op);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (opcode >= SLJIT_MOV && opcode <= SLJIT_MOV_P) {
+ /* LOAD REGISTER */
+ if (FAST_IS_REG(dst) && FAST_IS_REG(src)) {
+ dst_r = gpr(dst);
+ src_r = gpr(src);
+ switch (opcode | (op & SLJIT_32)) {
+ /* 32-bit */
+ case SLJIT_MOV32_U8:
+ ins = llcr(dst_r, src_r);
+ break;
+ case SLJIT_MOV32_S8:
+ ins = lbr(dst_r, src_r);
+ break;
+ case SLJIT_MOV32_U16:
+ ins = llhr(dst_r, src_r);
+ break;
+ case SLJIT_MOV32_S16:
+ ins = lhr(dst_r, src_r);
+ break;
+ case SLJIT_MOV32:
+ if (dst_r == src_r)
+ return SLJIT_SUCCESS;
+ ins = lr(dst_r, src_r);
+ break;
+ /* 64-bit */
+ case SLJIT_MOV_U8:
+ ins = llgcr(dst_r, src_r);
+ break;
+ case SLJIT_MOV_S8:
+ ins = lgbr(dst_r, src_r);
+ break;
+ case SLJIT_MOV_U16:
+ ins = llghr(dst_r, src_r);
+ break;
+ case SLJIT_MOV_S16:
+ ins = lghr(dst_r, src_r);
+ break;
+ case SLJIT_MOV_U32:
+ ins = llgfr(dst_r, src_r);
+ break;
+ case SLJIT_MOV_S32:
+ ins = lgfr(dst_r, src_r);
+ break;
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ if (dst_r == src_r)
+ return SLJIT_SUCCESS;
+ ins = lgr(dst_r, src_r);
+ break;
+ default:
+ ins = 0;
+ SLJIT_UNREACHABLE();
+ break;
+ }
+ FAIL_IF(push_inst(compiler, ins));
+ return SLJIT_SUCCESS;
+ }
+ /* LOAD IMMEDIATE */
+ if (FAST_IS_REG(dst) && src == SLJIT_IMM) {
+ switch (opcode) {
+ case SLJIT_MOV_U8:
+ srcw = (sljit_sw)((sljit_u8)(srcw));
+ break;
+ case SLJIT_MOV_S8:
+ srcw = (sljit_sw)((sljit_s8)(srcw));
+ break;
+ case SLJIT_MOV_U16:
+ srcw = (sljit_sw)((sljit_u16)(srcw));
+ break;
+ case SLJIT_MOV_S16:
+ srcw = (sljit_sw)((sljit_s16)(srcw));
+ break;
+ case SLJIT_MOV_U32:
+ srcw = (sljit_sw)((sljit_u32)(srcw));
+ break;
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ srcw = (sljit_sw)((sljit_s32)(srcw));
+ break;
+ }
+ return push_load_imm_inst(compiler, gpr(dst), srcw);
+ }
+ /* LOAD */
+ /* TODO(carenas): avoid reg being defined later */
+ #define LEVAL(i) EVAL(i, reg, mem)
+ if (FAST_IS_REG(dst) && (src & SLJIT_MEM)) {
+ sljit_gpr reg = gpr(dst);
+
+ FAIL_IF(make_addr_bxy(compiler, &mem, src, srcw, tmp1));
+ /* TODO(carenas): convert all calls below to LEVAL */
+ switch (opcode | (op & SLJIT_32)) {
+ case SLJIT_MOV32_U8:
+ ins = llc(reg, mem.offset, mem.index, mem.base);
+ break;
+ case SLJIT_MOV32_S8:
+ ins = lb(reg, mem.offset, mem.index, mem.base);
+ break;
+ case SLJIT_MOV32_U16:
+ ins = llh(reg, mem.offset, mem.index, mem.base);
+ break;
+ case SLJIT_MOV32_S16:
+ ins = WHEN2(is_u12(mem.offset), lh, lhy);
+ break;
+ case SLJIT_MOV32:
+ ins = WHEN2(is_u12(mem.offset), l, ly);
+ break;
+ case SLJIT_MOV_U8:
+ ins = LEVAL(llgc);
+ break;
+ case SLJIT_MOV_S8:
+ ins = lgb(reg, mem.offset, mem.index, mem.base);
+ break;
+ case SLJIT_MOV_U16:
+ ins = LEVAL(llgh);
+ break;
+ case SLJIT_MOV_S16:
+ ins = lgh(reg, mem.offset, mem.index, mem.base);
+ break;
+ case SLJIT_MOV_U32:
+ ins = LEVAL(llgf);
+ break;
+ case SLJIT_MOV_S32:
+ ins = lgf(reg, mem.offset, mem.index, mem.base);
+ break;
+ case SLJIT_MOV_P:
+ case SLJIT_MOV:
+ ins = lg(reg, mem.offset, mem.index, mem.base);
+ break;
+ default:
+ ins = 0;
+ SLJIT_UNREACHABLE();
+ break;
+ }
+ FAIL_IF(push_inst(compiler, ins));
+ return SLJIT_SUCCESS;
+ }
+ /* STORE and STORE IMMEDIATE */
+ if ((dst & SLJIT_MEM) && (FAST_IS_REG(src) || src == SLJIT_IMM)) {
+ sljit_gpr reg = FAST_IS_REG(src) ? gpr(src) : tmp0;
+
+ if (src == SLJIT_IMM) {
+ /* TODO(mundaym): MOVE IMMEDIATE? */
+ FAIL_IF(push_load_imm_inst(compiler, reg, srcw));
+ }
+ FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));
+ switch (opcode) {
+ case SLJIT_MOV_U8:
+ case SLJIT_MOV_S8:
+ return push_inst(compiler,
+ WHEN2(is_u12(mem.offset), stc, stcy));
+ case SLJIT_MOV_U16:
+ case SLJIT_MOV_S16:
+ return push_inst(compiler,
+ WHEN2(is_u12(mem.offset), sth, sthy));
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ return push_inst(compiler,
+ WHEN2(is_u12(mem.offset), st, sty));
+ case SLJIT_MOV_P:
+ case SLJIT_MOV:
+ FAIL_IF(push_inst(compiler, LEVAL(stg)));
+ return SLJIT_SUCCESS;
+ default:
+ SLJIT_UNREACHABLE();
+ }
+ }
+ #undef LEVAL
+ /* MOVE CHARACTERS */
+ if ((dst & SLJIT_MEM) && (src & SLJIT_MEM)) {
+ FAIL_IF(make_addr_bxy(compiler, &mem, src, srcw, tmp1));
+ switch (opcode) {
+ case SLJIT_MOV_U8:
+ case SLJIT_MOV_S8:
+ FAIL_IF(push_inst(compiler,
+ EVAL(llgc, tmp0, mem)));
+ FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));
+ return push_inst(compiler,
+ EVAL(stcy, tmp0, mem));
+ case SLJIT_MOV_U16:
+ case SLJIT_MOV_S16:
+ FAIL_IF(push_inst(compiler,
+ EVAL(llgh, tmp0, mem)));
+ FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));
+ return push_inst(compiler,
+ EVAL(sthy, tmp0, mem));
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+ FAIL_IF(push_inst(compiler,
+ EVAL(ly, tmp0, mem)));
+ FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));
+ return push_inst(compiler,
+ EVAL(sty, tmp0, mem));
+ case SLJIT_MOV_P:
+ case SLJIT_MOV:
+ FAIL_IF(push_inst(compiler,
+ EVAL(lg, tmp0, mem)));
+ FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));
+ FAIL_IF(push_inst(compiler,
+ EVAL(stg, tmp0, mem)));
+ return SLJIT_SUCCESS;
+ default:
+ SLJIT_UNREACHABLE();
+ }
+ }
+ SLJIT_UNREACHABLE();
+ }
+
+ SLJIT_ASSERT(src != SLJIT_IMM);
+
+ dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;
+ src_r = FAST_IS_REG(src) ? gpr(src) : tmp0;
+
+ compiler->status_flags_state = op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z);
+
+ /* TODO(mundaym): optimize loads and stores */
+ switch (opcode) {
+ case SLJIT_CLZ:
+ case SLJIT_CTZ:
+ if (src & SLJIT_MEM)
+ FAIL_IF(load_unsigned_word(compiler, src_r, src, srcw, op & SLJIT_32));
+
+ FAIL_IF(sljit_emit_clz_ctz(compiler, op, dst_r, src_r));
+ break;
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+ op |= SLJIT_32;
+ SLJIT_FALLTHROUGH
+ case SLJIT_REV:
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+ return sljit_emit_rev(compiler, op, dst, dstw, src, srcw);
+ default:
+ SLJIT_UNREACHABLE();
+ }
+
+ if (dst & SLJIT_MEM)
+ return store_word(compiler, dst_r, dst, dstw, op & SLJIT_32);
+
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE int is_commutative(sljit_s32 op)
+{
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD:
+ case SLJIT_ADDC:
+ case SLJIT_MUL:
+ case SLJIT_AND:
+ case SLJIT_OR:
+ case SLJIT_XOR:
+ return 1;
+ }
+ return 0;
+}
+
+static const struct ins_forms add_forms = {
+ 0x1a00, /* ar */
+ 0xb9080000, /* agr */
+ 0xb9f80000, /* ark */
+ 0xb9e80000, /* agrk */
+ 0x5a000000, /* a */
+ 0xe3000000005a, /* ay */
+ 0xe30000000008, /* ag */
+};
+
+static const struct ins_forms logical_add_forms = {
+ 0x1e00, /* alr */
+ 0xb90a0000, /* algr */
+ 0xb9fa0000, /* alrk */
+ 0xb9ea0000, /* algrk */
+ 0x5e000000, /* al */
+ 0xe3000000005e, /* aly */
+ 0xe3000000000a, /* alg */
+};
+
+static sljit_s32 sljit_emit_add(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ int sets_overflow = (op & VARIABLE_FLAG_MASK) == SLJIT_SET_OVERFLOW;
+ int sets_zero_overflow = (op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_SET_Z | SLJIT_SET_OVERFLOW);
+ const struct ins_forms *forms;
+ sljit_ins ins;
+
+ if (src2 == SLJIT_IMM) {
+ if (!sets_zero_overflow && is_s8(src2w) && (src1 & SLJIT_MEM) && (dst == src1 && dstw == src1w)) {
+ if (sets_overflow)
+ ins = (op & SLJIT_32) ? 0xeb000000006a /* asi */ : 0xeb000000007a /* agsi */;
+ else
+ ins = (op & SLJIT_32) ? 0xeb000000006e /* alsi */ : 0xeb000000007e /* algsi */;
+ return emit_siy(compiler, ins, dst, dstw, src2w);
+ }
+
+ if (is_s16(src2w)) {
+ if (sets_overflow)
+ ins = (op & SLJIT_32) ? 0xec00000000d8 /* ahik */ : 0xec00000000d9 /* aghik */;
+ else
+ ins = (op & SLJIT_32) ? 0xec00000000da /* alhsik */ : 0xec00000000db /* alghsik */;
+ FAIL_IF(emit_rie_d(compiler, ins, dst, src1, src1w, src2w));
+ goto done;
+ }
+
+ if (!sets_overflow) {
+ if ((op & SLJIT_32) || is_u32(src2w)) {
+ ins = (op & SLJIT_32) ? 0xc20b00000000 /* alfi */ : 0xc20a00000000 /* algfi */;
+ FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A));
+ goto done;
+ }
+ if (is_u32(-src2w)) {
+ FAIL_IF(emit_ri(compiler, 0xc20400000000 /* slgfi */, dst, src1, src1w, -src2w, RIL_A));
+ goto done;
+ }
+ }
+ else if ((op & SLJIT_32) || is_s32(src2w)) {
+ ins = (op & SLJIT_32) ? 0xc20900000000 /* afi */ : 0xc20800000000 /* agfi */;
+ FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A));
+ goto done;
+ }
+ }
+
+ forms = sets_overflow ? &add_forms : &logical_add_forms;
+ FAIL_IF(emit_commutative(compiler, forms, dst, src1, src1w, src2, src2w));
+
+done:
+ if (sets_zero_overflow)
+ FAIL_IF(update_zero_overflow(compiler, op, FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0));
+
+ if (dst & SLJIT_MEM)
+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);
+
+ return SLJIT_SUCCESS;
+}
+
+static const struct ins_forms sub_forms = {
+ 0x1b00, /* sr */
+ 0xb9090000, /* sgr */
+ 0xb9f90000, /* srk */
+ 0xb9e90000, /* sgrk */
+ 0x5b000000, /* s */
+ 0xe3000000005b, /* sy */
+ 0xe30000000009, /* sg */
+};
+
+static const struct ins_forms logical_sub_forms = {
+ 0x1f00, /* slr */
+ 0xb90b0000, /* slgr */
+ 0xb9fb0000, /* slrk */
+ 0xb9eb0000, /* slgrk */
+ 0x5f000000, /* sl */
+ 0xe3000000005f, /* sly */
+ 0xe3000000000b, /* slg */
+};
+
+static sljit_s32 sljit_emit_sub(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 flag_type = GET_FLAG_TYPE(op);
+ int sets_signed = (flag_type >= SLJIT_SIG_LESS && flag_type <= SLJIT_NOT_OVERFLOW);
+ int sets_zero_overflow = (op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_SET_Z | SLJIT_SET_OVERFLOW);
+ const struct ins_forms *forms;
+ sljit_ins ins;
+
+ if (dst == TMP_REG2 && flag_type <= SLJIT_SIG_LESS_EQUAL) {
+ int compare_signed = flag_type >= SLJIT_SIG_LESS;
+
+ compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_COMPARE;
+
+ if (src2 == SLJIT_IMM) {
+ if (compare_signed || ((op & VARIABLE_FLAG_MASK) == 0 && is_s32(src2w))) {
+ if ((op & SLJIT_32) || is_s32(src2w)) {
+ ins = (op & SLJIT_32) ? 0xc20d00000000 /* cfi */ : 0xc20c00000000 /* cgfi */;
+ return emit_ri(compiler, ins, src1, src1, src1w, src2w, RIL_A);
+ }
+ } else if ((op & SLJIT_32) || is_u32(src2w)) {
+ ins = (op & SLJIT_32) ? 0xc20f00000000 /* clfi */ : 0xc20e00000000 /* clgfi */;
+ return emit_ri(compiler, ins, src1, src1, src1w, src2w, RIL_A);
+ }
+ }
+ else if (src2 & SLJIT_MEM) {
+ if ((op & SLJIT_32) && ((src2 & OFFS_REG_MASK) || is_u12(src2w))) {
+ ins = compare_signed ? 0x59000000 /* c */ : 0x55000000 /* cl */;
+ return emit_rx(compiler, ins, src1, src1, src1w, src2, src2w, RX_A);
+ }
+
+ if (compare_signed)
+ ins = (op & SLJIT_32) ? 0xe30000000059 /* cy */ : 0xe30000000020 /* cg */;
+ else
+ ins = (op & SLJIT_32) ? 0xe30000000055 /* cly */ : 0xe30000000021 /* clg */;
+ return emit_rx(compiler, ins, src1, src1, src1w, src2, src2w, RXY_A);
+ }
+
+ if (compare_signed)
+ ins = (op & SLJIT_32) ? 0x1900 /* cr */ : 0xb9200000 /* cgr */;
+ else
+ ins = (op & SLJIT_32) ? 0x1500 /* clr */ : 0xb9210000 /* clgr */;
+ return emit_rr(compiler, ins, src1, src1, src1w, src2, src2w);
+ }
+
+ if (src1 == SLJIT_IMM && src1w == 0 && (flag_type == 0 || sets_signed)) {
+ ins = (op & SLJIT_32) ? 0x1300 /* lcr */ : 0xb9030000 /* lcgr */;
+ FAIL_IF(emit_rr1(compiler, ins, dst, src2, src2w));
+ goto done;
+ }
+
+ if (src2 == SLJIT_IMM) {
+ sljit_sw neg_src2w = -src2w;
+
+ if (sets_signed || neg_src2w != 0 || (op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == 0) {
+ if (!sets_zero_overflow && is_s8(neg_src2w) && (src1 & SLJIT_MEM) && (dst == src1 && dstw == src1w)) {
+ if (sets_signed)
+ ins = (op & SLJIT_32) ? 0xeb000000006a /* asi */ : 0xeb000000007a /* agsi */;
+ else
+ ins = (op & SLJIT_32) ? 0xeb000000006e /* alsi */ : 0xeb000000007e /* algsi */;
+ return emit_siy(compiler, ins, dst, dstw, neg_src2w);
+ }
+
+ if (is_s16(neg_src2w)) {
+ if (sets_signed)
+ ins = (op & SLJIT_32) ? 0xec00000000d8 /* ahik */ : 0xec00000000d9 /* aghik */;
+ else
+ ins = (op & SLJIT_32) ? 0xec00000000da /* alhsik */ : 0xec00000000db /* alghsik */;
+ FAIL_IF(emit_rie_d(compiler, ins, dst, src1, src1w, neg_src2w));
+ goto done;
+ }
+ }
+
+ if (!sets_signed) {
+ if ((op & SLJIT_32) || is_u32(src2w)) {
+ ins = (op & SLJIT_32) ? 0xc20500000000 /* slfi */ : 0xc20400000000 /* slgfi */;
+ FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A));
+ goto done;
+ }
+ if (is_u32(neg_src2w)) {
+ FAIL_IF(emit_ri(compiler, 0xc20a00000000 /* algfi */, dst, src1, src1w, neg_src2w, RIL_A));
+ goto done;
+ }
+ }
+ else if ((op & SLJIT_32) || is_s32(neg_src2w)) {
+ ins = (op & SLJIT_32) ? 0xc20900000000 /* afi */ : 0xc20800000000 /* agfi */;
+ FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, neg_src2w, RIL_A));
+ goto done;
+ }
+ }
+
+ forms = sets_signed ? &sub_forms : &logical_sub_forms;
+ FAIL_IF(emit_non_commutative(compiler, forms, dst, src1, src1w, src2, src2w));
+
+done:
+ if (sets_signed) {
+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
+
+ if ((op & VARIABLE_FLAG_MASK) != SLJIT_SET_OVERFLOW) {
+ /* In case of overflow, the sign bit of the two source operands must be different, and
+ - the first operand is greater if the sign bit of the result is set
+ - the first operand is less if the sign bit of the result is not set
+ The -result operation sets the corrent sign, because the result cannot be zero.
+ The overflow is considered greater, since the result must be equal to INT_MIN so its sign bit is set. */
+ FAIL_IF(push_inst(compiler, brc(0xe, (op & SLJIT_32) ? (2 + 1) : (2 + 2))));
+ FAIL_IF(push_inst(compiler, (op & SLJIT_32) ? lcr(tmp1, dst_r) : lcgr(tmp1, dst_r)));
+ }
+ else if (op & SLJIT_SET_Z)
+ FAIL_IF(update_zero_overflow(compiler, op, dst_r));
+ }
+
+ if (dst & SLJIT_MEM)
+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);
+
+ return SLJIT_SUCCESS;
+}
+
+static const struct ins_forms multiply_forms = {
+ 0xb2520000, /* msr */
+ 0xb90c0000, /* msgr */
+ 0xb9fd0000, /* msrkc */
+ 0xb9ed0000, /* msgrkc */
+ 0x71000000, /* ms */
+ 0xe30000000051, /* msy */
+ 0xe3000000000c, /* msg */
+};
+
+static const struct ins_forms multiply_overflow_forms = {
+ 0,
+ 0,
+ 0xb9fd0000, /* msrkc */
+ 0xb9ed0000, /* msgrkc */
+ 0,
+ 0xe30000000053, /* msc */
+ 0xe30000000083, /* msgc */
+};
+
+static sljit_s32 sljit_emit_multiply(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_ins ins;
+
+ if (HAS_FLAGS(op)) {
+ /* if have_misc2 fails, this operation should be emulated. 32 bit emulation:
+ FAIL_IF(push_inst(compiler, lgfr(tmp0, src1_r)));
+ FAIL_IF(push_inst(compiler, msgfr(tmp0, src2_r)));
+ if (dst_r != tmp0) {
+ FAIL_IF(push_inst(compiler, lr(dst_r, tmp0)));
+ }
+ FAIL_IF(push_inst(compiler, aih(tmp0, 1)));
+ FAIL_IF(push_inst(compiler, nihf(tmp0, ~1U)));
+ FAIL_IF(push_inst(compiler, ipm(tmp1)));
+ FAIL_IF(push_inst(compiler, oilh(tmp1, 0x2000))); */
+
+ return emit_commutative(compiler, &multiply_overflow_forms, dst, src1, src1w, src2, src2w);
+ }
+
+ if (src2 == SLJIT_IMM) {
+ if (is_s16(src2w)) {
+ ins = (op & SLJIT_32) ? 0xa70c0000 /* mhi */ : 0xa70d0000 /* mghi */;
+ return emit_ri(compiler, ins, dst, src1, src1w, src2w, RI_A);
+ }
+
+ if (is_s32(src2w)) {
+ ins = (op & SLJIT_32) ? 0xc20100000000 /* msfi */ : 0xc20000000000 /* msgfi */;
+ return emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A);
+ }
+ }
+
+ return emit_commutative(compiler, &multiply_forms, dst, src1, src1w, src2, src2w);
+}
+
+static sljit_s32 sljit_emit_bitwise_imm(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_uw imm, sljit_s32 count16)
+{
+ sljit_s32 mode = compiler->mode;
+ sljit_gpr dst_r = tmp0;
+ sljit_s32 needs_move = 1;
+
+ if (FAST_IS_REG(dst)) {
+ dst_r = gpr(dst & REG_MASK);
+ if (dst == src1)
+ needs_move = 0;
+ }
+
+ if (needs_move)
+ FAIL_IF(emit_move(compiler, dst_r, src1, src1w));
+
+ if (type == SLJIT_AND) {
+ if (!(mode & SLJIT_32))
+ FAIL_IF(push_inst(compiler, 0xc00a00000000 /* nihf */ | R36A(dst_r) | (imm >> 32)));
+ return push_inst(compiler, 0xc00b00000000 /* nilf */ | R36A(dst_r) | (imm & 0xffffffff));
+ }
+ else if (type == SLJIT_OR) {
+ if (count16 >= 3) {
+ FAIL_IF(push_inst(compiler, 0xc00c00000000 /* oihf */ | R36A(dst_r) | (imm >> 32)));
+ return push_inst(compiler, 0xc00d00000000 /* oilf */ | R36A(dst_r) | (imm & 0xffffffff));
+ }
+
+ if (count16 >= 2) {
+ if ((imm & 0x00000000ffffffffull) == 0)
+ return push_inst(compiler, 0xc00c00000000 /* oihf */ | R36A(dst_r) | (imm >> 32));
+ if ((imm & 0xffffffff00000000ull) == 0)
+ return push_inst(compiler, 0xc00d00000000 /* oilf */ | R36A(dst_r) | (imm & 0xffffffff));
+ }
+
+ if ((imm & 0xffff000000000000ull) != 0)
+ FAIL_IF(push_inst(compiler, 0xa5080000 /* oihh */ | R20A(dst_r) | (imm >> 48)));
+ if ((imm & 0x0000ffff00000000ull) != 0)
+ FAIL_IF(push_inst(compiler, 0xa5090000 /* oihl */ | R20A(dst_r) | ((imm >> 32) & 0xffff)));
+ if ((imm & 0x00000000ffff0000ull) != 0)
+ FAIL_IF(push_inst(compiler, 0xa50a0000 /* oilh */ | R20A(dst_r) | ((imm >> 16) & 0xffff)));
+ if ((imm & 0x000000000000ffffull) != 0 || imm == 0)
+ return push_inst(compiler, 0xa50b0000 /* oill */ | R20A(dst_r) | (imm & 0xffff));
+ return SLJIT_SUCCESS;
+ }
+
+ if ((imm & 0xffffffff00000000ull) != 0)
+ FAIL_IF(push_inst(compiler, 0xc00600000000 /* xihf */ | R36A(dst_r) | (imm >> 32)));
+ if ((imm & 0x00000000ffffffffull) != 0 || imm == 0)
+ return push_inst(compiler, 0xc00700000000 /* xilf */ | R36A(dst_r) | (imm & 0xffffffff));
+ return SLJIT_SUCCESS;
+}
+
+static const struct ins_forms bitwise_and_forms = {
+ 0x1400, /* nr */
+ 0xb9800000, /* ngr */
+ 0xb9f40000, /* nrk */
+ 0xb9e40000, /* ngrk */
+ 0x54000000, /* n */
+ 0xe30000000054, /* ny */
+ 0xe30000000080, /* ng */
+};
+
+static const struct ins_forms bitwise_or_forms = {
+ 0x1600, /* or */
+ 0xb9810000, /* ogr */
+ 0xb9f60000, /* ork */
+ 0xb9e60000, /* ogrk */
+ 0x56000000, /* o */
+ 0xe30000000056, /* oy */
+ 0xe30000000081, /* og */
+};
+
+static const struct ins_forms bitwise_xor_forms = {
+ 0x1700, /* xr */
+ 0xb9820000, /* xgr */
+ 0xb9f70000, /* xrk */
+ 0xb9e70000, /* xgrk */
+ 0x57000000, /* x */
+ 0xe30000000057, /* xy */
+ 0xe30000000082, /* xg */
+};
+
+static sljit_s32 sljit_emit_bitwise(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 type = GET_OPCODE(op);
+ const struct ins_forms *forms;
+
+ if (src2 == SLJIT_IMM && (!(op & SLJIT_SET_Z) || (type == SLJIT_AND && dst == TMP_REG2))) {
+ sljit_s32 count16 = 0;
+ sljit_uw imm = (sljit_uw)src2w;
+
+ if (op & SLJIT_32)
+ imm &= 0xffffffffull;
+
+ if ((imm & 0x000000000000ffffull) != 0 || imm == 0)
+ count16++;
+ if ((imm & 0x00000000ffff0000ull) != 0)
+ count16++;
+ if ((imm & 0x0000ffff00000000ull) != 0)
+ count16++;
+ if ((imm & 0xffff000000000000ull) != 0)
+ count16++;
+
+ if (type == SLJIT_AND && dst == TMP_REG2 && count16 == 1) {
+ sljit_gpr src_r = tmp1;
+
+ if (FAST_IS_REG(src1))
+ src_r = gpr(src1 & REG_MASK);
+ else
+ FAIL_IF(emit_move(compiler, tmp1, src1, src1w));
+
+ if ((imm & 0x000000000000ffffull) != 0 || imm == 0)
+ return push_inst(compiler, 0xa7010000 /* tmll */ | R20A(src_r) | imm);
+ if ((imm & 0x00000000ffff0000ull) != 0)
+ return push_inst(compiler, 0xa7000000 /* tmlh */ | R20A(src_r) | (imm >> 16));
+ if ((imm & 0x0000ffff00000000ull) != 0)
+ return push_inst(compiler, 0xa7030000 /* tmhl */ | R20A(src_r) | (imm >> 32));
+ return push_inst(compiler, 0xa7020000 /* tmhh */ | R20A(src_r) | (imm >> 48));
+ }
+
+ if (!(op & SLJIT_SET_Z))
+ return sljit_emit_bitwise_imm(compiler, type, dst, src1, src1w, imm, count16);
+ }
+
+ if (type == SLJIT_AND)
+ forms = &bitwise_and_forms;
+ else if (type == SLJIT_OR)
+ forms = &bitwise_or_forms;
+ else
+ forms = &bitwise_xor_forms;
+
+ return emit_commutative(compiler, forms, dst, src1, src1w, src2, src2w);
+}
+
+static sljit_s32 sljit_emit_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 type = GET_OPCODE(op);
+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
+ sljit_gpr src_r = tmp0;
+ sljit_gpr base_r = tmp0;
+ sljit_ins imm = 0;
+ sljit_ins ins;
+
+ if (FAST_IS_REG(src1))
+ src_r = gpr(src1);
+ else
+ FAIL_IF(emit_move(compiler, tmp0, src1, src1w));
+
+ if (src2 != SLJIT_IMM) {
+ if (FAST_IS_REG(src2))
+ base_r = gpr(src2);
+ else {
+ FAIL_IF(emit_move(compiler, tmp1, src2, src2w));
+ base_r = tmp1;
+ }
+
+ if ((op & SLJIT_32) && (type == SLJIT_MSHL || type == SLJIT_MLSHR || type == SLJIT_MASHR)) {
+ if (base_r != tmp1) {
+ FAIL_IF(push_inst(compiler, 0xec0000000055 /* risbg */ | R36A(tmp1) | R32A(base_r) | (59 << 24) | (1 << 23) | (63 << 16)));
+ base_r = tmp1;
+ } else
+ FAIL_IF(push_inst(compiler, 0xa5070000 /* nill */ | R20A(tmp1) | 0x1f));
+ }
+ } else
+ imm = (sljit_ins)(src2w & ((op & SLJIT_32) ? 0x1f : 0x3f));
+
+ if ((op & SLJIT_32) && dst_r == src_r) {
+ if (type == SLJIT_SHL || type == SLJIT_MSHL)
+ ins = 0x89000000 /* sll */;
+ else if (type == SLJIT_LSHR || type == SLJIT_MLSHR)
+ ins = 0x88000000 /* srl */;
+ else
+ ins = 0x8a000000 /* sra */;
+
+ FAIL_IF(push_inst(compiler, ins | R20A(dst_r) | R12A(base_r) | imm));
+ } else {
+ if (type == SLJIT_SHL || type == SLJIT_MSHL)
+ ins = (op & SLJIT_32) ? 0xeb00000000df /* sllk */ : 0xeb000000000d /* sllg */;
+ else if (type == SLJIT_LSHR || type == SLJIT_MLSHR)
+ ins = (op & SLJIT_32) ? 0xeb00000000de /* srlk */ : 0xeb000000000c /* srlg */;
+ else
+ ins = (op & SLJIT_32) ? 0xeb00000000dc /* srak */ : 0xeb000000000a /* srag */;
+
+ FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src_r) | R28A(base_r) | (imm << 16)));
+ }
+
+ if ((op & SLJIT_SET_Z) && type != SLJIT_ASHR)
+ return push_inst(compiler, (op & SLJIT_32) ? or(dst_r, dst_r) : ogr(dst_r, dst_r));
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 sljit_emit_rotate(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
+ sljit_gpr src_r = tmp0;
+ sljit_gpr base_r = tmp0;
+ sljit_ins imm = 0;
+ sljit_ins ins;
+
+ if (FAST_IS_REG(src1))
+ src_r = gpr(src1);
+ else
+ FAIL_IF(emit_move(compiler, tmp0, src1, src1w));
+
+ if (src2 != SLJIT_IMM) {
+ if (FAST_IS_REG(src2))
+ base_r = gpr(src2);
+ else {
+ FAIL_IF(emit_move(compiler, tmp1, src2, src2w));
+ base_r = tmp1;
+ }
+ }
+
+ if (GET_OPCODE(op) == SLJIT_ROTR) {
+ if (src2 != SLJIT_IMM) {
+ ins = (op & SLJIT_32) ? 0x1300 /* lcr */ : 0xb9030000 /* lcgr */;
+ FAIL_IF(push_inst(compiler, ins | R4A(tmp1) | R0A(base_r)));
+ base_r = tmp1;
+ } else
+ src2w = -src2w;
+ }
+
+ if (src2 == SLJIT_IMM)
+ imm = (sljit_ins)(src2w & ((op & SLJIT_32) ? 0x1f : 0x3f));
+
+ ins = (op & SLJIT_32) ? 0xeb000000001d /* rll */ : 0xeb000000001c /* rllg */;
+ return push_inst(compiler, ins | R36A(dst_r) | R32A(src_r) | R28A(base_r) | (imm << 16));
+}
+
+static const struct ins_forms addc_forms = {
+ 0xb9980000, /* alcr */
+ 0xb9880000, /* alcgr */
+ 0,
+ 0,
+ 0,
+ 0xe30000000098, /* alc */
+ 0xe30000000088, /* alcg */
+};
+
+static const struct ins_forms subc_forms = {
+ 0xb9990000, /* slbr */
+ 0xb9890000, /* slbgr */
+ 0,
+ 0,
+ 0,
+ 0xe30000000099, /* slb */
+ 0xe30000000089, /* slbg */
+};
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ compiler->mode = op & SLJIT_32;
+ compiler->status_flags_state = op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z);
+
+ if (is_commutative(op) && src1 == SLJIT_IMM && src2 != SLJIT_IMM) {
+ src1 ^= src2;
+ src2 ^= src1;
+ src1 ^= src2;
+
+ src1w ^= src2w;
+ src2w ^= src1w;
+ src1w ^= src2w;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD:
+ compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_ADD;
+ return sljit_emit_add(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_ADDC:
+ compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_ADD;
+ FAIL_IF(emit_commutative(compiler, &addc_forms, dst, src1, src1w, src2, src2w));
+ if (dst & SLJIT_MEM)
+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);
+ return SLJIT_SUCCESS;
+ case SLJIT_SUB:
+ compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_SUB;
+ return sljit_emit_sub(compiler, op, dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_SUBC:
+ compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_SUB;
+ FAIL_IF(emit_non_commutative(compiler, &subc_forms, dst, src1, src1w, src2, src2w));
+ if (dst & SLJIT_MEM)
+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);
+ return SLJIT_SUCCESS;
+ case SLJIT_MUL:
+ FAIL_IF(sljit_emit_multiply(compiler, op, dst, src1, src1w, src2, src2w));
+ break;
+ case SLJIT_AND:
+ case SLJIT_OR:
+ case SLJIT_XOR:
+ FAIL_IF(sljit_emit_bitwise(compiler, op, dst, src1, src1w, src2, src2w));
+ break;
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ FAIL_IF(sljit_emit_shift(compiler, op, dst, src1, src1w, src2, src2w));
+ break;
+ case SLJIT_ROTL:
+ case SLJIT_ROTR:
+ FAIL_IF(sljit_emit_rotate(compiler, op, dst, src1, src1w, src2, src2w));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 dst_reg = (GET_OPCODE(op) == SLJIT_SUB || GET_OPCODE(op) == SLJIT_AND) ? TMP_REG2 : TMP_REG1;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, op, dst_reg, 0, src1, src1w, src2, src2w);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MULADD:
+ SLJIT_SKIP_CHECKS(compiler);
+ FAIL_IF(sljit_emit_op2(compiler, SLJIT_MUL | (op & SLJIT_32), 0 /* tmp0 */, 0, src1, src1w, src2, src2w));
+ return push_inst(compiler, ((op & SLJIT_32) ? 0x1a00 /* ar */ : 0xb9080000 /* agr */) | R4A(gpr(dst_reg)) | R0A(tmp0));
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1_reg,
+ sljit_s32 src2_reg,
+ sljit_s32 src3, sljit_sw src3w)
+{
+ sljit_s32 is_right;
+ sljit_sw bit_length = (op & SLJIT_32) ? 32 : 64;
+ sljit_gpr dst_r = gpr(dst_reg);
+ sljit_gpr src1_r = gpr(src1_reg);
+ sljit_gpr src2_r = gpr(src2_reg);
+ sljit_gpr src3_r = tmp1;
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
+
+ is_right = (GET_OPCODE(op) == SLJIT_LSHR || GET_OPCODE(op) == SLJIT_MLSHR);
+
+ if (src1_reg == src2_reg) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, (is_right ? SLJIT_ROTR : SLJIT_ROTL) | (op & SLJIT_32), dst_reg, 0, src1_reg, 0, src3, src3w);
+ }
+
+ ADJUST_LOCAL_OFFSET(src3, src3w);
+
+ if (src3 == SLJIT_IMM) {
+ src3w &= bit_length - 1;
+
+ if (src3w == 0)
+ return SLJIT_SUCCESS;
+
+ if (op & SLJIT_32) {
+ if (dst_r == src1_r) {
+ ins = is_right ? 0x88000000 /* srl */ : 0x89000000 /* sll */;
+ FAIL_IF(push_inst(compiler, ins | R20A(dst_r) | (sljit_ins)src3w));
+ } else {
+ ins = is_right ? 0xeb00000000de /* srlk */ : 0xeb00000000df /* sllk */;
+ FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src1_r) | ((sljit_ins)src3w << 16)));
+ }
+ } else {
+ ins = is_right ? 0xeb000000000c /* srlg */ : 0xeb000000000d /* sllg */;
+ FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src1_r) | ((sljit_ins)src3w << 16)));
+ }
+
+ ins = 0xec0000000055 /* risbg */;
+
+ if (is_right) {
+ src3w = bit_length - src3w;
+ ins |= ((sljit_ins)(64 - bit_length) << 24) | ((sljit_ins)(63 - src3w) << 16) | ((sljit_ins)src3w << 8);
+ } else
+ ins |= ((sljit_ins)(64 - src3w) << 24) | ((sljit_ins)63 << 16) | ((sljit_ins)(src3w + 64 - bit_length) << 8);
+
+ return push_inst(compiler, ins | R36A(dst_r) | R32A(src2_r));
+ }
+
+ if (!(src3 & SLJIT_MEM)) {
+ src3_r = gpr(src3);
+
+ if (dst_r == src3_r) {
+ FAIL_IF(push_inst(compiler, 0x1800 /* lr */ | R4A(tmp1) | R0A(src3_r)));
+ src3_r = tmp1;
+ }
+ } else
+ FAIL_IF(load_word(compiler, tmp1, src3, src3w, op & SLJIT_32));
+
+ if (op & SLJIT_32) {
+ if (GET_OPCODE(op) == SLJIT_MSHL || GET_OPCODE(op) == SLJIT_MLSHR) {
+ if (src3_r != tmp1) {
+ FAIL_IF(push_inst(compiler, 0xec0000000055 /* risbg */ | R36A(tmp1) | R32A(src3_r) | (59 << 24) | (1 << 23) | (63 << 16)));
+ src3_r = tmp1;
+ } else
+ FAIL_IF(push_inst(compiler, 0xa5070000 /* nill */ | R20A(tmp1) | 0x1f));
+ }
+
+ if (dst_r == src1_r) {
+ ins = is_right ? 0x88000000 /* srl */ : 0x89000000 /* sll */;
+ FAIL_IF(push_inst(compiler, ins | R20A(dst_r) | R12A(src3_r)));
+ } else {
+ ins = is_right ? 0xeb00000000de /* srlk */ : 0xeb00000000df /* sllk */;
+ FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src1_r) | R28A(src3_r)));
+ }
+
+ if (src3_r != tmp1) {
+ FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | 0x1f));
+ FAIL_IF(push_inst(compiler, 0x1700 /* xr */ | R4A(tmp1) | R0A(src3_r)));
+ } else
+ FAIL_IF(push_inst(compiler, 0xc00700000000 /* xilf */ | R36A(tmp1) | 0x1f));
+
+ ins = is_right ? 0xeb00000000df /* sllk */ : 0xeb00000000de /* srlk */;
+ FAIL_IF(push_inst(compiler, ins | R36A(tmp0) | R32A(src2_r) | R28A(tmp1) | (0x1 << 16)));
+
+ return push_inst(compiler, 0x1600 /* or */ | R4A(dst_r) | R0A(tmp0));
+ }
+
+ ins = is_right ? 0xeb000000000c /* srlg */ : 0xeb000000000d /* sllg */;
+ FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src1_r) | R28A(src3_r)));
+
+ ins = is_right ? 0xeb000000000d /* sllg */ : 0xeb000000000c /* srlg */;
+
+ if (!(op & SLJIT_SHIFT_INTO_NON_ZERO)) {
+ if (src3_r != tmp1)
+ FAIL_IF(push_inst(compiler, 0xa50f0000 /* llill */ | R20A(tmp1) | 0x3f));
+
+ FAIL_IF(push_inst(compiler, ins | R36A(tmp0) | R32A(src2_r) | (0x1 << 16)));
+ src2_r = tmp0;
+
+ if (src3_r != tmp1)
+ FAIL_IF(push_inst(compiler, 0xb9820000 /* xgr */ | R4A(tmp1) | R0A(src3_r)));
+ else
+ FAIL_IF(push_inst(compiler, 0xc00700000000 /* xilf */ | R36A(tmp1) | 0x3f));
+ } else
+ FAIL_IF(push_inst(compiler, 0xb9030000 /* lcgr */ | R4A(tmp1) | R0A(src3_r)));
+
+ FAIL_IF(push_inst(compiler, ins | R36A(tmp0) | R32A(src2_r) | R28A(tmp1)));
+ return push_inst(compiler, 0xb9810000 /* ogr */ | R4A(dst_r) | R0A(tmp0));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_gpr dst_r, tmp_r, src_r;
+ struct addr addr;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= 0x3f;
+
+ if (src2 == SLJIT_IMM) {
+ src2w = (sljit_sw)((sljit_uw)src2w << shift_arg);
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ tmp_r = FAST_IS_REG(dst) && (dst != src1) ? gpr(dst) : tmp0;
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(load_word(compiler, tmp_r, src2, src2w, 0 /* 64-bit */));
+ src_r = tmp_r;
+ } else {
+ src_r = gpr(src2);
+ }
+
+ FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp_r) | R32A(src_r) | ((sljit_ins)shift_arg << 16)));
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(make_addr_bxy(compiler, &addr, src1, src1w, tmp1));
+ FAIL_IF(push_inst(compiler, 0xe30000000008 /* ag */ | R36A(tmp_r) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)));
+ src_r = tmp_r;
+ } else if (src1 == SLJIT_IMM) {
+ if (is_s32(src1w)) {
+ FAIL_IF(push_inst(compiler, 0xc20800000000 /* agfi */ | R36A(tmp_r) | (sljit_u32)src1w));
+ src_r = tmp_r;
+ } else {
+ src_r = tmp_r != tmp0 ? tmp0 : tmp1;
+ FAIL_IF(push_load_imm_inst(compiler, src_r, src1w));
+ }
+ } else {
+ src_r = gpr(src1);
+ }
+
+ dst_r = (FAST_IS_REG(dst) ? gpr(dst) : tmp0);
+
+ if (src_r != tmp_r) {
+ if (src_r == dst_r) {
+ FAIL_IF(push_inst(compiler, 0xb9080000 /* agr */ | R4A(dst_r) | R0A(tmp_r)));
+ } else {
+ FAIL_IF(push_inst(compiler, 0xb9e80000 /* agrk */ | R12A(tmp_r) | R4A(dst_r) | R0A(src_r)));
+ }
+ }
+
+ if (dst & SLJIT_MEM)
+ return store_word(compiler, dst_r, dst, dstw, 0 /* 64-bit */);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_gpr src_r;
+ struct addr addr;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ switch (op) {
+ case SLJIT_FAST_RETURN:
+ if (FAST_IS_REG(src)) {
+ src_r = gpr(src);
+ if (src_r != link_r)
+ FAIL_IF(push_inst(compiler, lgr(link_r, src_r)));
+ } else
+ FAIL_IF(load_word(compiler, link_r, src, srcw, 0));
+
+ return push_inst(compiler, br(link_r));
+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
+ return SLJIT_SUCCESS;
+ case SLJIT_PREFETCH_L1:
+ case SLJIT_PREFETCH_L2:
+ case SLJIT_PREFETCH_L3:
+ case SLJIT_PREFETCH_ONCE:
+ FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp1));
+ return push_inst(compiler, 0xe31000000036 /* pfd */ | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset));
+ default:
+ return SLJIT_SUCCESS;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_gpr dst_r = link_r;
+ sljit_s32 size;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ switch (op) {
+ case SLJIT_FAST_ENTER:
+ if (FAST_IS_REG(dst)) {
+ dst_r = gpr(dst);
+
+ if (dst_r == link_r)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, lgr(dst_r, link_r));
+ }
+ break;
+ case SLJIT_GET_RETURN_ADDRESS:
+ dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;
+
+ size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 2);
+ FAIL_IF(load_word(compiler, dst_r, SLJIT_MEM1(SLJIT_SP), compiler->local_size + size, 0));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ return store_word(compiler, dst_r, dst, dstw, 0);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
+{
+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
+
+ if (type == SLJIT_GP_REGISTER)
+ return (sljit_s32)gpr(reg);
+
+ if (type != SLJIT_FLOAT_REGISTER && type != SLJIT_SIMD_REG_128)
+ return -1;
+
+ return (sljit_s32)freg_map[reg];
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_u32 size)
+{
+ sljit_ins ins = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
+
+ memcpy((sljit_u8 *)&ins + sizeof(ins) - size, instruction, size);
+ return push_inst(compiler, ins);
+}
+
+/* --------------------------------------------------------------------- */
+/* Floating point operators */
+/* --------------------------------------------------------------------- */
+
+#define FLOAT_LOAD 0
+#define FLOAT_STORE 1
+
+static sljit_s32 float_mem(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ struct addr addr;
+ sljit_ins ins;
+
+ SLJIT_ASSERT(mem & SLJIT_MEM);
+
+ if ((mem & OFFS_REG_MASK) || is_u12(memw) || !is_s20(memw)) {
+ FAIL_IF(make_addr_bx(compiler, &addr, mem, memw, tmp1));
+
+ if (op & FLOAT_STORE)
+ ins = (op & SLJIT_32) ? 0x70000000 /* ste */ : 0x60000000 /* std */;
+ else
+ ins = (op & SLJIT_32) ? 0x78000000 /* le */ : 0x68000000 /* ld */;
+
+ return push_inst(compiler, ins | F20(reg) | R16A(addr.index) | R12A(addr.base) | (sljit_ins)addr.offset);
+ }
+
+ FAIL_IF(make_addr_bxy(compiler, &addr, mem, memw, tmp1));
+
+ if (op & FLOAT_STORE)
+ ins = (op & SLJIT_32) ? 0xed0000000066 /* stey */ : 0xed0000000067 /* stdy */;
+ else
+ ins = (op & SLJIT_32) ? 0xed0000000064 /* ley */ : 0xed0000000065 /* ldy */;
+
+ return push_inst(compiler, ins | F36(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset));
+}
+
+static sljit_s32 emit_float(struct sljit_compiler *compiler, sljit_ins ins_r, sljit_ins ins,
+ sljit_s32 reg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ struct addr addr;
+
+ if (!(src & SLJIT_MEM))
+ return push_inst(compiler, ins_r | F4(reg) | F0(src));
+
+ FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1));
+ return push_inst(compiler, ins | F36(reg) | R32A(addr.index) | R28A(addr.base) | ((sljit_ins)addr.offset << 16));
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;
+ sljit_ins ins;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), TMP_FREG1, src, srcw));
+ src = TMP_FREG1;
+ }
+
+ /* M3 is set to 5 */
+ if (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)
+ ins = (op & SLJIT_32) ? 0xb3a85000 /* cgebr */ : 0xb3a95000 /* cgdbr */;
+ else
+ ins = (op & SLJIT_32) ? 0xb3985000 /* cfebr */ : 0xb3995000 /* cfdbr */;
+
+ FAIL_IF(push_inst(compiler, ins | R4A(dst_r) | F0(src)));
+
+ if (dst & SLJIT_MEM)
+ return store_word(compiler, dst_r, dst, dstw, GET_OPCODE(op) >= SLJIT_CONV_S32_FROM_F64);
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 sljit_emit_fop1_conv_f64_from_w(struct sljit_compiler *compiler, sljit_ins ins,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (src == SLJIT_IMM) {
+ FAIL_IF(push_load_imm_inst(compiler, tmp0, srcw));
+ src = (sljit_s32)tmp0;
+ }
+ else if (src & SLJIT_MEM) {
+ FAIL_IF(load_word(compiler, tmp0, src, srcw, ins & 0x100000));
+ src = (sljit_s32)tmp0;
+ }
+
+ FAIL_IF(push_inst(compiler, ins | F4(dst_r) | R0(src)));
+
+ if (dst & SLJIT_MEM)
+ return float_mem(compiler, FLOAT_STORE | ((ins & 0x10000) ? 0 : SLJIT_32), TMP_FREG1, dst, dstw);
+
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins ins;
+
+ if (src == SLJIT_IMM && GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
+ srcw = (sljit_s32)srcw;
+
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)
+ ins = (op & SLJIT_32) ? 0xb3a40000 /* cegbr */ : 0xb3a50000 /* cdgbr */;
+ else
+ ins = (op & SLJIT_32) ? 0xb3940000 /* cefbr */ : 0xb3950000 /* cdfbr */;
+
+ return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw);
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins ins;
+
+ if (src == SLJIT_IMM && GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32)
+ srcw = (sljit_u32)srcw;
+
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_UW)
+ ins = (op & SLJIT_32) ? 0xb3a00000 /* celgbr */ : 0xb3a10000 /* cdlgbr */;
+ else
+ ins = (op & SLJIT_32) ? 0xb3900000 /* celfbr */ : 0xb3910000 /* cdlfbr */;
+
+ return sljit_emit_fop1_conv_f64_from_w(compiler, ins, dst, dstw, src, srcw);
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_ins ins_r, ins;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), TMP_FREG1, src1, src1w));
+ src1 = TMP_FREG1;
+ }
+
+ if (op & SLJIT_32) {
+ ins_r = 0xb3090000 /* cebr */;
+ ins = 0xed0000000009 /* ceb */;
+ } else {
+ ins_r = 0xb3190000 /* cdbr */;
+ ins = 0xed0000000019 /* cdb */;
+ }
+
+ return emit_float(compiler, ins_r, ins, src1, src2, src2w);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r;
+ sljit_ins ins;
+
+ CHECK_ERROR();
+
+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (op == SLJIT_CONV_F64_FROM_F32)
+ FAIL_IF(emit_float(compiler, 0xb3040000 /* ldebr */, 0xed0000000004 /* ldeb */, dst_r, src, srcw));
+ else {
+ if (src & SLJIT_MEM) {
+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op == SLJIT_CONV_F32_FROM_F64 ? 0 : (op & SLJIT_32)), dst_r, src, srcw));
+ src = dst_r;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_F64:
+ if (FAST_IS_REG(dst)) {
+ if (dst == src)
+ return SLJIT_SUCCESS;
+
+ ins = (op & SLJIT_32) ? 0x3800 /* ler */ : 0x2800 /* ldr */;
+ break;
+ }
+ return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), src, dst, dstw);
+ case SLJIT_CONV_F64_FROM_F32:
+ /* Only SLJIT_CONV_F32_FROM_F64. */
+ ins = 0xb3440000 /* ledbr */;
+ break;
+ case SLJIT_NEG_F64:
+ ins = (op & SLJIT_32) ? 0xb3030000 /* lcebr */ : 0xb3130000 /* lcdbr */;
+ break;
+ default:
+ SLJIT_ASSERT(GET_OPCODE(op) == SLJIT_ABS_F64);
+ ins = (op & SLJIT_32) ? 0xb3000000 /* lpebr */ : 0xb3100000 /* lpdbr */;
+ break;
+ }
+
+ FAIL_IF(push_inst(compiler, ins | F4(dst_r) | F0(src)));
+ }
+
+ if (dst & SLJIT_MEM)
+ return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), TMP_FREG1, dst, dstw);
+
+ return SLJIT_SUCCESS;
+}
+
+#define FLOAT_MOV(op, dst_r, src_r) \
+ (((op & SLJIT_32) ? 0x3800 /* ler */ : 0x2800 /* ldr */) | F4(dst_r) | F0(src_r))
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 dst_r = TMP_FREG1;
+ sljit_ins ins_r, ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ do {
+ if (FAST_IS_REG(dst)) {
+ dst_r = dst;
+
+ if (dst == src1)
+ break;
+
+ if (dst == src2) {
+ if (GET_OPCODE(op) == SLJIT_ADD_F64 || GET_OPCODE(op) == SLJIT_MUL_F64) {
+ src2 = src1;
+ src2w = src1w;
+ src1 = dst;
+ break;
+ }
+
+ FAIL_IF(push_inst(compiler, FLOAT_MOV(op, TMP_FREG1, src2)));
+ src2 = TMP_FREG1;
+ }
+ }
+
+ if (src1 & SLJIT_MEM)
+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), dst_r, src1, src1w));
+ else
+ FAIL_IF(push_inst(compiler, FLOAT_MOV(op, dst_r, src1)));
+ } while (0);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD_F64:
+ ins_r = (op & SLJIT_32) ? 0xb30a0000 /* aebr */ : 0xb31a0000 /* adbr */;
+ ins = (op & SLJIT_32) ? 0xed000000000a /* aeb */ : 0xed000000001a /* adb */;
+ break;
+ case SLJIT_SUB_F64:
+ ins_r = (op & SLJIT_32) ? 0xb30b0000 /* sebr */ : 0xb31b0000 /* sdbr */;
+ ins = (op & SLJIT_32) ? 0xed000000000b /* seb */ : 0xed000000001b /* sdb */;
+ break;
+ case SLJIT_MUL_F64:
+ ins_r = (op & SLJIT_32) ? 0xb3170000 /* meebr */ : 0xb31c0000 /* mdbr */;
+ ins = (op & SLJIT_32) ? 0xed0000000017 /* meeb */ : 0xed000000001c /* mdb */;
+ break;
+ default:
+ SLJIT_ASSERT(GET_OPCODE(op) == SLJIT_DIV_F64);
+ ins_r = (op & SLJIT_32) ? 0xb30d0000 /* debr */ : 0xb31d0000 /* ddbr */;
+ ins = (op & SLJIT_32) ? 0xed000000000d /* deb */ : 0xed000000001d /* ddb */;
+ break;
+ }
+
+ FAIL_IF(emit_float(compiler, ins_r, ins, dst_r, src2, src2w));
+
+ if (dst & SLJIT_MEM)
+ return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), TMP_FREG1, dst, dstw);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 reg;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fop2r(compiler, op, dst_freg, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), TMP_FREG1, src2, src2w));
+ src2 = TMP_FREG1;
+ }
+
+ if (src1 & SLJIT_MEM) {
+ reg = (dst_freg == src2) ? TMP_FREG1 : dst_freg;
+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), reg, src1, src1w));
+ src1 = reg;
+ }
+
+ return push_inst(compiler, 0xb3720000 /* cpsdr */ | F12(src2) | F4(dst_freg) | F0(src1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f32 value)
+{
+ union {
+ sljit_s32 imm;
+ sljit_f32 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset32(compiler, freg, value));
+
+ u.value = value;
+
+ FAIL_IF(push_load_imm_inst(compiler, tmp1, (sljit_sw)(((sljit_uw)u.imm << 32))));
+ return push_inst(compiler, 0xb3c10000 /* ldgr */ | F4(freg) | R0A(tmp1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value)
+{
+ union {
+ sljit_sw imm;
+ sljit_f64 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset64(compiler, freg, value));
+
+ u.value = value;
+
+ FAIL_IF(push_load_imm_inst(compiler, tmp1, (sljit_sw)u.imm));
+ return push_inst(compiler, 0xb3c10000 /* ldgr */ | F4(freg) | R0A(tmp1));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg)
+{
+ sljit_gpr gen_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
+
+ gen_r = gpr(reg);
+
+ if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) {
+ if (op & SLJIT_32) {
+ FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp0) | R32A(gen_r) | (32 << 16)));
+ gen_r = tmp0;
+ }
+
+ return push_inst(compiler, 0xb3c10000 /* ldgr */ | F4(freg) | R0A(gen_r));
+ }
+
+ FAIL_IF(push_inst(compiler, 0xb3cd0000 /* lgdr */ | R4A(gen_r) | F0(freg)));
+
+ if (!(op & SLJIT_32))
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, 0xeb000000000c /* srlg */ | R36A(gen_r) | R32A(gen_r) | (32 << 16));
+}
+
+/* --------------------------------------------------------------------- */
+/* Conditional instructions */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_label(compiler));
+
+ if (compiler->last_label && compiler->last_label->size == compiler->size)
+ return compiler->last_label;
+
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+ PTR_FAIL_IF(!label);
+ set_label(label, compiler);
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, i;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (alignment <= SLJIT_LABEL_ALIGN_2) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_u16);
+
+ for (i = (mask >> 1); i != 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, 0x0700 /* 2-byte nop */));
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ for (i = (buffers->size + 1) >> 1; i > 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, 0x0700 /* 2-byte nop */));
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
+{
+ struct sljit_jump *jump;
+ sljit_u8 mask = ((type & 0xff) < SLJIT_JUMP) ? get_cc(compiler, type & 0xff) : 0xf;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_jump(compiler, type));
+
+ /* record jump */
+ jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ jump->addr = compiler->size;
+
+ /* emit jump instruction */
+ type &= 0xff;
+ if (type >= SLJIT_FAST_CALL)
+ PTR_FAIL_IF(push_inst(compiler, brasl(link_r, 0)));
+ else
+ PTR_FAIL_IF(push_inst(compiler, brcl(mask, 0)));
+
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types)
+{
+ SLJIT_UNUSED_ARG(arg_types);
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
+
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(emit_stack_frame_release(compiler, r14));
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_jump(compiler, type);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
+{
+ struct sljit_jump *jump;
+ sljit_gpr src_r = FAST_IS_REG(src) ? gpr(src) : tmp1;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
+
+ if (src != SLJIT_IMM) {
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(load_word(compiler, src_r, src, srcw, 0 /* 64-bit */));
+ }
+
+ /* emit jump instruction */
+ if (type >= SLJIT_FAST_CALL)
+ return push_inst(compiler, basr(link_r, src_r));
+
+ return push_inst(compiler, br(src_r));
+ }
+
+ jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF(!jump);
+ set_jump(jump, compiler, JUMP_ADDR);
+ jump->addr = compiler->size;
+ jump->u.target = (sljit_uw)srcw;
+
+ type &= 0xff;
+ if (type >= SLJIT_FAST_CALL)
+ return push_inst(compiler, brasl(link_r, 0));
+
+ return push_inst(compiler, brcl(0xf, 0));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types,
+ sljit_s32 src, sljit_sw srcw)
+{
+ SLJIT_UNUSED_ARG(arg_types);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
+
+ SLJIT_ASSERT(gpr(TMP_REG2) == tmp1);
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(load_word(compiler, tmp1, src, srcw, 0 /* 64-bit */));
+ src = TMP_REG2;
+ srcw = 0;
+ }
+
+ if (type & SLJIT_CALL_RETURN) {
+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ FAIL_IF(push_inst(compiler, lgr(tmp1, gpr(src))));
+ src = TMP_REG2;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, r14));
+ type = SLJIT_JUMP;
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, type, src, srcw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 type)
+{
+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
+ sljit_gpr loc_r = tmp1;
+ sljit_u8 mask = get_cc(compiler, type);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_AND:
+ case SLJIT_OR:
+ case SLJIT_XOR:
+ compiler->status_flags_state = op & SLJIT_SET_Z;
+
+ /* dst is also source operand */
+ if (dst & SLJIT_MEM)
+ FAIL_IF(load_word(compiler, dst_r, dst, dstw, op & SLJIT_32));
+
+ break;
+ case SLJIT_MOV32:
+ op |= SLJIT_32;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV:
+ /* can write straight into destination */
+ loc_r = dst_r;
+ break;
+ default:
+ SLJIT_UNREACHABLE();
+ }
+
+ /* TODO(mundaym): fold into cmov helper function? */
+ #define LEVAL(i) i(loc_r, 1, mask)
+ if (have_lscond2()) {
+ FAIL_IF(push_load_imm_inst(compiler, loc_r, 0));
+ FAIL_IF(push_inst(compiler,
+ WHEN2(op & SLJIT_32, lochi, locghi)));
+ } else {
+ FAIL_IF(push_load_imm_inst(compiler, loc_r, 1));
+ FAIL_IF(push_inst(compiler, brc(mask, 2 + 2)));
+ FAIL_IF(push_load_imm_inst(compiler, loc_r, 0));
+ }
+ #undef LEVAL
+
+ /* apply bitwise op and set condition codes */
+ switch (GET_OPCODE(op)) {
+ #define LEVAL(i) i(dst_r, loc_r)
+ case SLJIT_AND:
+ FAIL_IF(push_inst(compiler,
+ WHEN2(op & SLJIT_32, nr, ngr)));
+ break;
+ case SLJIT_OR:
+ FAIL_IF(push_inst(compiler,
+ WHEN2(op & SLJIT_32, or, ogr)));
+ break;
+ case SLJIT_XOR:
+ FAIL_IF(push_inst(compiler,
+ WHEN2(op & SLJIT_32, xr, xgr)));
+ break;
+ #undef LEVAL
+ }
+
+ /* store result to memory if required */
+ if (dst & SLJIT_MEM)
+ return store_word(compiler, dst_r, dst, dstw, (op & SLJIT_32));
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_reg)
+{
+ sljit_ins mask;
+ sljit_gpr src_r;
+ sljit_gpr dst_r = gpr(dst_reg);
+ sljit_s32 is_32bit = (type & SLJIT_32) != 0;
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ type &= ~SLJIT_32;
+ if (src1 == SLJIT_IMM && is_32bit)
+ src1w = (sljit_s32)src1w;
+
+ if (type & SLJIT_COMPARE_SELECT) {
+ type ^= SLJIT_COMPARE_SELECT;
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(load_word(compiler, tmp0, src1, src1w, is_32bit));
+ src1 = TMP_REG1;
+ src1w = 0;
+ } else if (src1 == SLJIT_IMM) {
+ if (type >= SLJIT_LESS && type <= SLJIT_LESS_EQUAL && src1w >= 0 && src1w <= 0x7fff) {
+ ins = is_32bit ? 0xc20f00000000 /* clfi */ : 0xc20e00000000 /* clgfi */;
+ FAIL_IF(push_inst(compiler, ins | R36A(gpr(src2_reg)) | (sljit_ins)src1w));
+ type ^= 0x1;
+ } else if (type >= SLJIT_SIG_LESS && type <= SLJIT_SIG_LESS_EQUAL && is_s20(src1w)) {
+ ins = is_32bit ? 0xc20d00000000 /* cfi */ : 0xc20c00000000 /* cgfi */;
+ FAIL_IF(push_inst(compiler, ins | R36A(gpr(src2_reg)) | ((sljit_ins)src1w & 0xffffffff)));
+ type ^= 0x1;
+ } else {
+ FAIL_IF(push_load_imm_inst(compiler, tmp0, src1w));
+ src1 = TMP_REG1;
+ src1w = 0;
+ }
+ }
+
+ if (FAST_IS_REG(src1)) {
+ if (type >= SLJIT_LESS && type <= SLJIT_LESS_EQUAL)
+ ins = is_32bit ? 0x1500 /* clr */ : 0xb9210000 /* clgr */;
+ else
+ ins = is_32bit ? 0x1900 /* cr */ : 0xb9200000 /* cgr */;
+ FAIL_IF(push_inst(compiler, ins | R4A(gpr(src1)) | R0A(gpr(src2_reg))));
+ }
+ }
+
+ if (dst_reg != src2_reg) {
+ if (src1 == dst_reg) {
+ src1 = src2_reg;
+ src1w = 0;
+ type ^= 0x1;
+ } else {
+ if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
+ FAIL_IF(load_word(compiler, dst_r, src1, src1w, is_32bit));
+ src1 = src2_reg;
+ src1w = 0;
+ type ^= 0x1;
+ } else
+ FAIL_IF(push_inst(compiler, (is_32bit ? 0x1800 /* lr */ : 0xb9040000 /* lgr */) | R4A(dst_r) | R0A(gpr(src2_reg))));
+ }
+ }
+
+ mask = get_cc(compiler, type);
+
+ if (src1 & SLJIT_MEM) {
+ if (src1 & OFFS_REG_MASK) {
+ src_r = gpr(OFFS_REG(src1));
+
+ if (src1w != 0) {
+ FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp1) | R32A(src_r) | ((sljit_ins)(src1w & 0x3) << 16)));
+ src_r = tmp1;
+ }
+
+ FAIL_IF(push_inst(compiler, 0xb9e80000 /* agrk */ | R12A(src_r) | R4A(tmp1) | R0A(gpr(src1 & REG_MASK))));
+ src_r = tmp1;
+ src1w = 0;
+ } else if (!is_s20(src1w)) {
+ FAIL_IF(push_load_imm_inst(compiler, tmp1, src1w));
+
+ if (src1 & REG_MASK)
+ FAIL_IF(push_inst(compiler, 0xb9080000 /* agr */ | R4A(tmp1) | R0A(gpr(src1 & REG_MASK))));
+
+ src_r = tmp1;
+ src1w = 0;
+ } else
+ src_r = gpr(src1 & REG_MASK);
+
+ ins = is_32bit ? 0xeb00000000f2 /* loc */ : 0xeb00000000e2 /* locg */;
+ return push_inst(compiler, ins | R36A(dst_r) | (mask << 32) | R28A(src_r) | disp_s20((sljit_s32)src1w));
+ }
+
+ if (src1 == SLJIT_IMM) {
+ if (have_lscond2() && is_s16(src1w)) {
+ ins = is_32bit ? 0xec0000000042 /* lochi */ : 0xec0000000046 /* locghi */;
+ return push_inst(compiler, ins | R36A(dst_r) | (mask << 32) | (sljit_ins)(src1w & 0xffff) << 16);
+ }
+
+ FAIL_IF(push_load_imm_inst(compiler, tmp1, src1w));
+ src_r = tmp1;
+ } else
+ src_r = gpr(src1);
+
+ ins = is_32bit ? 0xb9f20000 /* locr */ : 0xb9e20000 /* locgr */;
+ return push_inst(compiler, ins | (mask << 12) | R4A(dst_r) | R0A(src_r));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_freg)
+{
+ sljit_ins ins;
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ if (dst_freg != src2_freg) {
+ if (dst_freg == src1) {
+ src1 = src2_freg;
+ src1w = 0;
+ type ^= 0x1;
+ } else {
+ ins = (type & SLJIT_32) ? 0x3800 /* ler */ : 0x2800 /* ldr */;
+ FAIL_IF(push_inst(compiler, ins | F4(dst_freg) | F0(src2_freg)));
+ }
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1);
+ FAIL_IF(!jump);
+
+ if (!(src1 & SLJIT_MEM)) {
+ ins = (type & SLJIT_32) ? 0x3800 /* ler */ : 0x2800 /* ldr */;
+ FAIL_IF(push_inst(compiler, ins | F4(dst_freg) | F0(src1)));
+ } else
+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (type & SLJIT_32), dst_freg, src1, src1w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ FAIL_IF(!label);
+
+ sljit_set_label(jump, label);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_ins ins, reg1, reg2, base, offs = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
+
+ if (!(reg & REG_PAIR_MASK))
+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
+
+ ADJUST_LOCAL_OFFSET(mem, memw);
+
+ base = gpr(mem & REG_MASK);
+ reg1 = gpr(REG_PAIR_FIRST(reg));
+ reg2 = gpr(REG_PAIR_SECOND(reg));
+
+ if (mem & OFFS_REG_MASK) {
+ memw &= 0x3;
+ offs = gpr(OFFS_REG(mem));
+
+ if (memw != 0) {
+ FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp1) | R32A(offs) | ((sljit_ins)memw << 16)));
+ offs = tmp1;
+ } else if (!(type & SLJIT_MEM_STORE) && (base == reg1 || base == reg2) && (offs == reg1 || offs == reg2)) {
+ FAIL_IF(push_inst(compiler, 0xb9f80000 | R12A(tmp1) | R4A(base) | R0A(offs)));
+ base = tmp1;
+ offs = 0;
+ }
+
+ memw = 0;
+ } else if (memw < -0x80000 || memw > 0x7ffff - ((reg2 == reg1 + 1) ? 0 : SSIZE_OF(sw))) {
+ FAIL_IF(push_load_imm_inst(compiler, tmp1, memw));
+
+ if (base == 0)
+ base = tmp1;
+ else
+ offs = tmp1;
+
+ memw = 0;
+ }
+
+ if (offs == 0 && reg2 == (reg1 + 1)) {
+ ins = (type & SLJIT_MEM_STORE) ? 0xeb0000000024 /* stmg */ : 0xeb0000000004 /* lmg */;
+ return push_inst(compiler, ins | R36A(reg1) | R32A(reg2) | R28A(base) | disp_s20((sljit_s32)memw));
+ }
+
+ ins = ((type & SLJIT_MEM_STORE) ? 0xe30000000024 /* stg */ : 0xe30000000004 /* lg */) | R32A(offs) | R28A(base);
+
+ if (!(type & SLJIT_MEM_STORE) && base == reg1) {
+ FAIL_IF(push_inst(compiler, ins | R36A(reg2) | disp_s20((sljit_s32)memw + SSIZE_OF(sw))));
+ return push_inst(compiler, ins | R36A(reg1) | disp_s20((sljit_s32)memw));
+ }
+
+ FAIL_IF(push_inst(compiler, ins | R36A(reg1) | disp_s20((sljit_s32)memw)));
+ return push_inst(compiler, ins | R36A(reg2) | disp_s20((sljit_s32)memw + SSIZE_OF(sw)));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);
+ struct addr addr;
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw));
+
+ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
+
+ if (reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (!(srcdst & SLJIT_MEM)) {
+ if (type & SLJIT_SIMD_STORE)
+ ins = F36(srcdst) | F32(vreg);
+ else
+ ins = F36(vreg) | F32(srcdst);
+
+ return push_inst(compiler, 0xe70000000056 /* vlr */ | ins);
+ }
+
+ FAIL_IF(make_addr_bx(compiler, &addr, srcdst, srcdstw, tmp1));
+ ins = F36(vreg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset);
+
+ if (alignment >= 4)
+ ins |= 4 << 12;
+ else if (alignment == 3)
+ ins |= 3 << 12;
+
+ return push_inst(compiler, ((type & SLJIT_SIMD_STORE) ? 0xe7000000000e /* vst */ : 0xe70000000006 /* vl */) | ins);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ struct addr addr;
+ sljit_gpr reg;
+ sljit_sw sign_ext;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw));
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1));
+ return push_inst(compiler, 0xe70000000005 /* vlrep */ | F36(vreg)
+ | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset) | ((sljit_ins)elem_size << 12));
+ }
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (src == SLJIT_IMM)
+ return push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(vreg));
+
+ return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(vreg) | F32(src) | ((sljit_ins)elem_size << 12));
+ }
+
+ if (src == SLJIT_IMM) {
+ sign_ext = 0x10000;
+
+ switch (elem_size) {
+ case 0:
+ srcw &= 0xff;
+ sign_ext = (sljit_s8)srcw;
+ break;
+ case 1:
+ srcw &= 0xffff;
+ sign_ext = (sljit_s16)srcw;
+ break;
+ case 2:
+ if ((sljit_s32)srcw == (sljit_s16)srcw) {
+ srcw &= 0xffff;
+ sign_ext = (sljit_s16)srcw;
+ } else
+ srcw &= 0xffffffff;
+ break;
+ default:
+ if (srcw == (sljit_s16)srcw) {
+ srcw &= 0xffff;
+ sign_ext = (sljit_s16)srcw;
+ }
+ break;
+ }
+
+ if (sign_ext != 0x10000) {
+ if (sign_ext == 0 || sign_ext == -1)
+ return push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(vreg)
+ | (sign_ext == 0 ? 0 : ((sljit_ins)0xffff << 16)));
+
+ return push_inst(compiler, 0xe70000000045 /* vrepi */ | F36(vreg)
+ | ((sljit_ins)srcw << 16) | ((sljit_ins)elem_size << 12));
+ }
+
+ push_load_imm_inst(compiler, tmp0, srcw);
+ reg = tmp0;
+ } else
+ reg = gpr(src);
+
+ FAIL_IF(push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(vreg) | R32A(reg) | ((sljit_ins)elem_size << 12)));
+ return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(vreg) | F32(vreg) | ((sljit_ins)elem_size << 12));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg, sljit_s32 lane_index,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ struct addr addr;
+ sljit_gpr reg;
+ sljit_ins ins = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw));
+
+ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
+
+ if (reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (srcdst & SLJIT_MEM) {
+ FAIL_IF(make_addr_bx(compiler, &addr, srcdst, srcdstw, tmp1));
+ ins = F36(vreg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset);
+ }
+
+ if (type & SLJIT_SIMD_LANE_ZERO) {
+ if ((srcdst & SLJIT_MEM) && lane_index == ((1 << (3 - elem_size)) - 1))
+ return push_inst(compiler, 0xe70000000004 /* vllez */ | ins | ((sljit_ins)elem_size << 12));
+
+ if ((type & SLJIT_SIMD_FLOAT) && vreg == srcdst) {
+ FAIL_IF(push_inst(compiler, 0xe70000000056 /* vlr */ | F36(TMP_FREG1) | F32(vreg)));
+ srcdst = TMP_FREG1;
+ srcdstw = 0;
+ }
+
+ FAIL_IF(push_inst(compiler, 0xe70000000044 /* vgbm */ | F36(vreg)));
+ }
+
+ if (srcdst & SLJIT_MEM) {
+ switch (elem_size) {
+ case 0:
+ ins |= 0xe70000000000 /* vleb */;
+ break;
+ case 1:
+ ins |= 0xe70000000001 /* vleh */;
+ break;
+ case 2:
+ ins |= 0xe70000000003 /* vlef */;
+ break;
+ default:
+ ins |= 0xe70000000002 /* vleg */;
+ break;
+ }
+
+ /* Convert to vsteb - vsteg */
+ if (type & SLJIT_SIMD_STORE)
+ ins |= 0x8;
+
+ return push_inst(compiler, ins | ((sljit_ins)lane_index << 12));
+ }
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (type & SLJIT_SIMD_STORE)
+ return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(srcdst) | F32(vreg) | ((sljit_ins)lane_index << 16) | ((sljit_ins)elem_size << 12));
+
+ if (elem_size == 3) {
+ if (lane_index == 0)
+ ins = F32(srcdst) | F28(vreg) | (1 << 12);
+ else
+ ins = F32(vreg) | F28(srcdst);
+
+ return push_inst(compiler, 0xe70000000084 /* vpdi */ | F36(vreg) | ins);
+ }
+
+ FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(tmp0) | F32(srcdst) | ((sljit_ins)2 << 12)));
+ return push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(vreg) | R32A(tmp0) | ((sljit_ins)lane_index << 16) | ((sljit_ins)2 << 12));
+ }
+
+ if (srcdst == SLJIT_IMM) {
+ switch (elem_size) {
+ case 0:
+ ins = 0xe70000000040 /* vleib */;
+ srcdstw &= 0xff;
+ break;
+ case 1:
+ ins = 0xe70000000041 /* vleih */;
+ srcdstw &= 0xffff;
+ break;
+ case 2:
+ if ((sljit_s32)srcdstw == (sljit_s16)srcdstw) {
+ srcdstw &= 0xffff;
+ ins = 0xe70000000043 /* vleif */;
+ } else
+ srcdstw &= 0xffffffff;
+ break;
+ default:
+ if (srcdstw == (sljit_s16)srcdstw) {
+ srcdstw &= 0xffff;
+ ins = 0xe70000000042 /* vleig */;
+ }
+ break;
+ }
+
+ if (ins != 0)
+ return push_inst(compiler, ins | F36(vreg) | ((sljit_ins)srcdstw << 16) | ((sljit_ins)lane_index << 12));
+
+ push_load_imm_inst(compiler, tmp0, srcdstw);
+ reg = tmp0;
+ } else
+ reg = gpr(srcdst);
+
+ ins = ((sljit_ins)lane_index << 16) | ((sljit_ins)elem_size << 12);
+
+ if (!(type & SLJIT_SIMD_STORE))
+ return push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(vreg) | R32A(reg) | ins);
+
+ FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(reg) | F32(vreg) | ins));
+
+ if (!(type & SLJIT_SIMD_LANE_SIGNED) || elem_size >= 3)
+ return SLJIT_SUCCESS;
+
+ switch (elem_size) {
+ case 0:
+ ins = 0xb9060000 /* lgbr */;
+ break;
+ case 1:
+ ins = 0xb9070000 /* lghr */;
+ break;
+ default:
+ ins = 0xb9140000 /* lgfr */;
+ break;
+ }
+
+ return push_inst(compiler, ins | R4A(reg) | R0A(reg));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_s32 src_lane_index)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index));
+
+ if (reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, 0xe7000000004d /* vrep */ | F36(vreg) | F32(src)
+ | ((sljit_ins)src_lane_index << 16) | ((sljit_ins)elem_size << 12));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);
+ struct addr addr;
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw));
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1));
+ ins = F36(vreg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset);
+
+ switch (elem2_size - elem_size) {
+ case 1:
+ ins |= 0xe70000000002 /* vleg */;
+ break;
+ case 2:
+ ins |= 0xe70000000003 /* vlef */;
+ break;
+ default:
+ ins |= 0xe70000000001 /* vleh */;
+ break;
+ }
+
+ FAIL_IF(push_inst(compiler, ins));
+ src = vreg;
+ }
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ FAIL_IF(push_inst(compiler, 0xe700000000d5 /* vuplh */ | F36(vreg) | F32(src) | (2 << 12)));
+ FAIL_IF(push_inst(compiler, 0xe70000000030 /* vesl */ | F36(vreg) | F32(vreg) | (32 << 16) | (3 << 12)));
+ return push_inst(compiler, 0xe700000000c4 /* vfll */ | F36(vreg) | F32(vreg) | (2 << 12));
+ }
+
+ ins = ((type & SLJIT_SIMD_EXTEND_SIGNED) ? 0xe700000000d7 /* vuph */ : 0xe700000000d5 /* vuplh */) | F36(vreg);
+
+ do {
+ FAIL_IF(push_inst(compiler, ins | F32(src) | ((sljit_ins)elem_size << 12)));
+ src = vreg;
+ } while (++elem_size < elem2_size);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_gpr dst_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw));
+
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ if (reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && elem_size < 2)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ switch (elem_size) {
+ case 0:
+ push_load_imm_inst(compiler, tmp0, (sljit_sw)0x4048505860687078);
+ push_load_imm_inst(compiler, tmp1, (sljit_sw)0x0008101820283038);
+ FAIL_IF(push_inst(compiler, 0xe70000000062 /* vlvgp */ | F36(TMP_FREG1) | R32A(tmp1) | R28A(tmp0)));
+ break;
+ case 1:
+ push_load_imm_inst(compiler, tmp0, (sljit_sw)0x0010203040506070);
+ break;
+ case 2:
+ push_load_imm_inst(compiler, tmp0, (sljit_sw)0x8080808000204060);
+ break;
+ default:
+ push_load_imm_inst(compiler, tmp0, (sljit_sw)0x8080808080800040);
+ break;
+ }
+
+ if (elem_size != 0)
+ FAIL_IF(push_inst(compiler, 0xe70000000022 /* vlvg */ | F36(TMP_FREG1) | R32A(tmp0) | (1 << 16) | (3 << 12)));
+
+ FAIL_IF(push_inst(compiler, 0xe70000000085 /* vbperm */ | F36(TMP_FREG1) | F32(vreg) | F28(TMP_FREG1)));
+
+ dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;
+ FAIL_IF(push_inst(compiler, 0xe70000000021 /* vlgv */ | R36A(dst_r) | F32(TMP_FREG1)
+ | (elem_size == 0 ? ((3 << 16) | (1 << 12)) : (7 << 16))));
+
+ if (dst_r == tmp0)
+ return store_word(compiler, tmp0, dst, dstw, type & SLJIT_32);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 alignment;
+ struct addr addr;
+ sljit_ins ins = 0, load_ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ if (reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ switch (SLJIT_SIMD_GET_OPCODE(type)) {
+ case SLJIT_SIMD_OP2_AND:
+ ins = 0xe70000000068 /* vn */;
+ break;
+ case SLJIT_SIMD_OP2_OR:
+ ins = 0xe7000000006a /* vo */;
+ break;
+ case SLJIT_SIMD_OP2_XOR:
+ ins = 0xe7000000006d /* vx */;
+ break;
+ case SLJIT_SIMD_OP2_SHUFFLE:
+ ins = 0xe7000000008c /* vperm */;
+ break;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(make_addr_bx(compiler, &addr, src2, src2w, tmp1));
+ load_ins = 0xe70000000006 /* vl */ | F36(TMP_FREG1) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset);
+ alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);
+
+ if (alignment >= 4)
+ load_ins |= 4 << 12;
+ else if (alignment == 3)
+ load_ins |= 3 << 12;
+
+ FAIL_IF(push_inst(compiler, load_ins));
+ src2 = TMP_FREG1;
+ }
+
+ if (SLJIT_SIMD_GET_OPCODE(type) == SLJIT_SIMD_OP2_SHUFFLE)
+ return push_inst(compiler, ins | F36(dst_vreg) | F32(src1_vreg) | F28(src1_vreg) | F12(src2));
+
+ return push_inst(compiler, ins | F36(dst_vreg) | F32(src1_vreg) | F28(src2));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 mem_reg)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));
+
+ if (op & SLJIT_ATOMIC_USE_LS)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV32:
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op1(compiler, op & ~SLJIT_ATOMIC_USE_CAS, dst_reg, 0, SLJIT_MEM1(mem_reg), 0);
+ default:
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src_reg,
+ sljit_s32 mem_reg,
+ sljit_s32 temp_reg)
+{
+ sljit_ins ins;
+ sljit_gpr tmp_r = gpr(temp_reg);
+ sljit_gpr mem_r = gpr(mem_reg);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));
+
+ if (op & SLJIT_ATOMIC_USE_LS)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV32:
+ case SLJIT_MOV_U32:
+ ins = 0xba000000 /* cs */ | R20A(tmp_r) | R16A(gpr(src_reg)) | R12A(mem_r);
+ break;
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+ ins = 0xeb0000000030 /* csg */ | R36A(tmp_r) | R32A(gpr(src_reg)) | R28A(mem_r);
+ break;
+ default:
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ return push_inst(compiler, ins);
+}
+
+/* --------------------------------------------------------------------- */
+/* Other instructions */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
+{
+ struct sljit_const *const_;
+ sljit_gpr dst_r;
+ int is_32 = 0;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+ PTR_FAIL_IF(!const_);
+ set_const((struct sljit_const*)const_, compiler);
+
+ dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ if (init_value & 0x100)
+ init_value |= 0xff00;
+ else
+ init_value &= 0xff;
+
+ PTR_FAIL_IF(push_inst(compiler, 0xa7090000 /* lghi */ | R20A(dst_r) | (sljit_ins)(init_value & 0xffff)));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(store_byte(compiler, dst_r, dst, dstw));
+ return (struct sljit_const*)const_;
+
+ case SLJIT_MOV32:
+ is_32 = 1;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_S32:
+ PTR_FAIL_IF(push_inst(compiler, 0xc00100000000 /* lgfi */ | R36A(dst_r) | (sljit_ins)(init_value & 0xffffffff)));
+ break;
+
+ default:
+ PTR_FAIL_IF(push_inst(compiler, 0xc00f00000000 /* llilf */ | R36A(dst_r) | (sljit_ins)(init_value & 0xffffffff)));
+ PTR_FAIL_IF(push_inst(compiler, 0xc00800000000 /* iihf */ | R36A(dst_r) | (sljit_ins)((init_value >> 32) & 0xffffffff)));
+ break;
+ }
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(store_word(compiler, dst_r, dst, dstw, is_32));
+
+ return (struct sljit_const*)const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
+{
+ /* Update the constant pool. */
+ sljit_uw *ptr = (sljit_uw *)addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0);
+ *ptr = new_target;
+ SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1);
+ SLJIT_CACHE_FLUSH(ptr, ptr + 1);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
+{
+ sljit_u16 *inst = (sljit_u16*)addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ SLJIT_ASSERT((inst[0] & 0xff0f) == 0xa709 /* lghi */);
+
+ if (new_constant & 0x100)
+ new_constant |= 0xff00;
+ else
+ new_constant &= 0xff;
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ inst[1] = (sljit_u16)new_constant;
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_u16*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ return;
+
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ SLJIT_ASSERT((inst[0] & 0xff0f) == 0xc001 /* lgfi */);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 3, 0);
+ inst[1] = (sljit_u16)(new_constant >> 16);
+ inst[2] = (sljit_u16)new_constant;
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 3, 1);
+ inst = (sljit_u16*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 3);
+ return;
+
+ default:
+ SLJIT_ASSERT((inst[0] & 0xff0f) == 0xc00f /* llilf */ && (inst[3] & 0xff0f) == 0xc008 /* iihf */);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 0);
+ inst[1] = (sljit_u16)(new_constant >> 16);
+ inst[2] = (sljit_u16)new_constant;
+ inst[4] = (sljit_u16)(new_constant >> 48);
+ inst[5] = (sljit_u16)(new_constant >> 32);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 1);
+ inst = (sljit_u16*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 6);
+ return;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_jump *jump;
+ sljit_gpr dst_r, target_r;
+ SLJIT_UNUSED_ARG(op);
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = tmp1;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(load_word(compiler, dst_r, dst, dstw, 0));
+ }
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_mov_addr(jump, compiler, 0);
+
+ /* Might be converted to lgrl. */
+ PTR_FAIL_IF(push_inst(compiler, 0xc00000000000 /* larl */ | R36A(target_r)));
+
+ if (op == SLJIT_ADD_ABS_ADDR)
+ PTR_FAIL_IF(push_inst(compiler, 0xb90a0000 /* algr */ | R4A(dst_r) | R0A(tmp1)));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(store_word(compiler, dst_r, dst, dstw, 0));
+
+ return jump;
+}
+
+/* TODO(carenas): EVAL probably should move up or be refactored */
+#undef WHEN2
+#undef EVAL
+
+#undef tmp1
+#undef tmp0
+
+/* TODO(carenas): undef other macros that spill like is_u12? */
diff --git a/deps/sljit/sljit_src/sljitNativeX86_32.c b/deps/sljit/sljit_src/sljitNativeX86_32.c
new file mode 100644
index 0000000..95faa74
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativeX86_32.c
@@ -0,0 +1,1707 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* x86 32-bit arch dependent functions. */
+
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
+static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, sljit_sw imm)
+{
+ sljit_u8 *inst;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_sw));
+ FAIL_IF(!inst);
+ INC_SIZE(1 + sizeof(sljit_sw));
+ *inst++ = opcode;
+ sljit_unaligned_store_sw(inst, imm);
+ return SLJIT_SUCCESS;
+}
+
+/* Size contains the flags as well. */
+static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw size,
+ /* The register or immediate operand. */
+ sljit_s32 a, sljit_sw imma,
+ /* The general operand (not immediate). */
+ sljit_s32 b, sljit_sw immb)
+{
+ sljit_u8 *inst;
+ sljit_u8 *buf_ptr;
+ sljit_u8 reg_map_b;
+ sljit_uw flags = size;
+ sljit_uw inst_size;
+
+ /* Both cannot be switched on. */
+ SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
+ /* Size flags not allowed for typed instructions. */
+ SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);
+ /* Both size flags cannot be switched on. */
+ SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
+ /* SSE2 and immediate is not possible. */
+ SLJIT_ASSERT(a != SLJIT_IMM || !(flags & EX86_SSE2));
+ SLJIT_ASSERT(((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))
+ & ((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0);
+ SLJIT_ASSERT((flags & (EX86_VEX_EXT | EX86_REX)) != EX86_VEX_EXT);
+
+ size &= 0xf;
+ /* The mod r/m byte is always present. */
+ inst_size = size + 1;
+
+ if (flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))
+ inst_size++;
+
+ /* Calculate size of b. */
+ if (b & SLJIT_MEM) {
+ if (!(b & REG_MASK))
+ inst_size += sizeof(sljit_sw);
+ else {
+ if (immb != 0 && !(b & OFFS_REG_MASK)) {
+ /* Immediate operand. */
+ if (immb <= 127 && immb >= -128)
+ inst_size += sizeof(sljit_s8);
+ else
+ inst_size += sizeof(sljit_sw);
+ } else if (reg_map[b & REG_MASK] == 5) {
+ /* Swap registers if possible. */
+ if ((b & OFFS_REG_MASK) && (immb & 0x3) == 0 && reg_map[OFFS_REG(b)] != 5)
+ b = SLJIT_MEM | OFFS_REG(b) | TO_OFFS_REG(b & REG_MASK);
+ else
+ inst_size += sizeof(sljit_s8);
+ }
+
+ if (reg_map[b & REG_MASK] == 4 && !(b & OFFS_REG_MASK))
+ b |= TO_OFFS_REG(SLJIT_SP);
+
+ if (b & OFFS_REG_MASK)
+ inst_size += 1; /* SIB byte. */
+ }
+ }
+
+ /* Calculate size of a. */
+ if (a == SLJIT_IMM) {
+ if (flags & EX86_BIN_INS) {
+ if (imma <= 127 && imma >= -128) {
+ inst_size += sizeof(sljit_s8);
+ flags |= EX86_BYTE_ARG;
+ } else
+ inst_size += sizeof(sljit_sw);
+ } else if (flags & EX86_SHIFT_INS) {
+ SLJIT_ASSERT(imma <= 0x1f);
+ if (imma != 1) {
+ inst_size += sizeof(sljit_s8);
+ flags |= EX86_BYTE_ARG;
+ }
+ } else if (flags & EX86_BYTE_ARG)
+ inst_size += sizeof(sljit_s8);
+ else if (flags & EX86_HALF_ARG)
+ inst_size += sizeof(sljit_s16);
+ else
+ inst_size += sizeof(sljit_sw);
+ } else
+ SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);
+ PTR_FAIL_IF(!inst);
+
+ /* Encoding the byte. */
+ INC_SIZE(inst_size);
+ if (flags & EX86_PREF_F2)
+ *inst++ = 0xf2;
+ else if (flags & EX86_PREF_F3)
+ *inst++ = 0xf3;
+ else if (flags & EX86_PREF_66)
+ *inst++ = 0x66;
+
+ buf_ptr = inst + size;
+
+ /* Encode mod/rm byte. */
+ if (!(flags & EX86_SHIFT_INS)) {
+ if ((flags & EX86_BIN_INS) && a == SLJIT_IMM)
+ *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
+
+ if (a == SLJIT_IMM)
+ *buf_ptr = 0;
+ else if (!(flags & EX86_SSE2_OP1))
+ *buf_ptr = U8(reg_map[a] << 3);
+ else
+ *buf_ptr = U8(freg_map[a] << 3);
+ } else {
+ if (a == SLJIT_IMM) {
+ if (imma == 1)
+ *inst = GROUP_SHIFT_1;
+ else
+ *inst = GROUP_SHIFT_N;
+ } else
+ *inst = GROUP_SHIFT_CL;
+ *buf_ptr = 0;
+ }
+
+ if (!(b & SLJIT_MEM)) {
+ *buf_ptr = U8(*buf_ptr | MOD_REG | (!(flags & EX86_SSE2_OP2) ? reg_map[b] : freg_map[b]));
+ buf_ptr++;
+ } else if (b & REG_MASK) {
+ reg_map_b = reg_map[b & REG_MASK];
+
+ if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) {
+ if (immb != 0 || reg_map_b == 5) {
+ if (immb <= 127 && immb >= -128)
+ *buf_ptr |= 0x40;
+ else
+ *buf_ptr |= 0x80;
+ }
+
+ if (!(b & OFFS_REG_MASK))
+ *buf_ptr++ |= reg_map_b;
+ else {
+ buf_ptr[0] |= 0x04;
+ buf_ptr[1] = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3));
+ buf_ptr += 2;
+ }
+
+ if (immb != 0 || reg_map_b == 5) {
+ if (immb <= 127 && immb >= -128)
+ *buf_ptr++ = U8(immb); /* 8 bit displacement. */
+ else {
+ sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */
+ buf_ptr += sizeof(sljit_sw);
+ }
+ }
+ } else {
+ if (reg_map_b == 5)
+ *buf_ptr |= 0x40;
+
+ buf_ptr[0] |= 0x04;
+ buf_ptr[1] = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3) | (immb << 6));
+ buf_ptr += 2;
+
+ if (reg_map_b == 5)
+ *buf_ptr++ = 0;
+ }
+ } else {
+ *buf_ptr++ |= 0x05;
+ sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */
+ buf_ptr += sizeof(sljit_sw);
+ }
+
+ if (a == SLJIT_IMM) {
+ if (flags & EX86_BYTE_ARG)
+ *buf_ptr = U8(imma);
+ else if (flags & EX86_HALF_ARG)
+ sljit_unaligned_store_s16(buf_ptr, (sljit_s16)imma);
+ else if (!(flags & EX86_SHIFT_INS))
+ sljit_unaligned_store_sw(buf_ptr, imma);
+ }
+
+ return inst;
+}
+
+static sljit_s32 emit_vex_instruction(struct sljit_compiler *compiler, sljit_uw op,
+ /* The first and second register operand. */
+ sljit_s32 a, sljit_s32 v,
+ /* The general operand (not immediate). */
+ sljit_s32 b, sljit_sw immb)
+{
+ sljit_u8 *inst;
+ sljit_u8 vex = 0;
+ sljit_u8 vex_m = 0;
+ sljit_uw size;
+
+ SLJIT_ASSERT(((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))
+ & ((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0);
+
+ if (op & VEX_OP_0F38)
+ vex_m = 0x2;
+ else if (op & VEX_OP_0F3A)
+ vex_m = 0x3;
+
+ if (op & VEX_W) {
+ if (vex_m == 0)
+ vex_m = 0x1;
+
+ vex |= 0x80;
+ }
+
+ if (op & EX86_PREF_66)
+ vex |= 0x1;
+ else if (op & EX86_PREF_F2)
+ vex |= 0x3;
+ else if (op & EX86_PREF_F3)
+ vex |= 0x2;
+
+ op &= ~(EX86_PREF_66 | EX86_PREF_F2 | EX86_PREF_F3);
+
+ if (op & VEX_256)
+ vex |= 0x4;
+
+ vex = U8(vex | ((((op & VEX_SSE2_OPV) ? freg_map[v] : reg_map[v]) ^ 0xf) << 3));
+
+ size = op & ~(sljit_uw)0xff;
+ size |= (vex_m == 0) ? 3 : 4;
+
+ inst = emit_x86_instruction(compiler, size, a, 0, b, immb);
+ FAIL_IF(!inst);
+
+ if (vex_m == 0) {
+ inst[0] = 0xc5;
+ inst[1] = U8(vex | 0x80);
+ inst[2] = U8(op);
+ return SLJIT_SUCCESS;
+ }
+
+ inst[0] = 0xc4;
+ inst[1] = U8(vex_m | 0xe0);
+ inst[2] = vex;
+ inst[3] = U8(op);
+ return SLJIT_SUCCESS;
+}
+
+/* --------------------------------------------------------------------- */
+/* Enter / return */
+/* --------------------------------------------------------------------- */
+
+static sljit_u8* detect_far_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset)
+{
+ sljit_uw type = jump->flags >> TYPE_SHIFT;
+
+ if (type == SLJIT_JUMP) {
+ *code_ptr++ = JMP_i32;
+ } else if (type >= SLJIT_FAST_CALL) {
+ *code_ptr++ = CALL_i32;
+ } else {
+ *code_ptr++ = GROUP_0F;
+ *code_ptr++ = get_jump_code(type);
+ }
+
+ jump->addr = (sljit_uw)code_ptr;
+
+ if (jump->flags & JUMP_ADDR)
+ sljit_unaligned_store_sw(code_ptr, (sljit_sw)(jump->u.target - (jump->addr + 4) - (sljit_uw)executable_offset));
+ else
+ jump->flags |= PATCH_MW;
+ code_ptr += 4;
+
+ return code_ptr;
+}
+
+#define ENTER_TMP_TO_R4 0x00001
+#define ENTER_TMP_TO_S 0x00002
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 word_arg_count, saved_arg_count, float_arg_count;
+ sljit_s32 size, args_size, types, status;
+ sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(options);
+ sljit_u8 *inst;
+#ifdef _WIN32
+ sljit_s32 r2_offset = -1;
+#endif
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+
+ /* Emit ENDBR32 at function entry if needed. */
+ FAIL_IF(emit_endbranch(compiler));
+
+ SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ word_arg_count = 0;
+ status = 0;
+
+ if (options & SLJIT_ENTER_REG_ARG) {
+ args_size = 3 * SSIZE_OF(sw);
+
+ while (arg_types) {
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
+ word_arg_count++;
+ if (word_arg_count >= 4)
+ status |= ENTER_TMP_TO_R4;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ compiler->args_size = 0;
+ } else {
+ types = arg_types;
+ saved_arg_count = 0;
+ float_arg_count = 0;
+ args_size = SSIZE_OF(sw);
+ while (types) {
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ float_arg_count++;
+ FAIL_IF(emit_sse2_load(compiler, 0, float_arg_count, SLJIT_MEM1(SLJIT_SP), args_size));
+ args_size += SSIZE_OF(f64);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ float_arg_count++;
+ FAIL_IF(emit_sse2_load(compiler, 1, float_arg_count, SLJIT_MEM1(SLJIT_SP), args_size));
+ args_size += SSIZE_OF(f32);
+ break;
+ default:
+ word_arg_count++;
+
+ if (!(types & SLJIT_ARG_TYPE_SCRATCH_REG))
+ saved_arg_count++;
+
+ if (word_arg_count == 4) {
+ if (types & SLJIT_ARG_TYPE_SCRATCH_REG) {
+ status |= ENTER_TMP_TO_R4;
+ arg_types &= ~(SLJIT_ARG_FULL_MASK << 3 * SLJIT_ARG_SHIFT);
+ } else if (saved_arg_count == 4) {
+ status |= ENTER_TMP_TO_S;
+ arg_types &= ~(SLJIT_ARG_FULL_MASK << 3 * SLJIT_ARG_SHIFT);
+ }
+ }
+
+ args_size += SSIZE_OF(sw);
+ break;
+ }
+ types >>= SLJIT_ARG_SHIFT;
+ }
+
+ args_size -= SSIZE_OF(sw);
+ compiler->args_size = args_size;
+ }
+
+ size = (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3) - kept_saveds_count;
+ if (!(options & SLJIT_ENTER_REG_ARG))
+ size++;
+
+ if (size != 0) {
+ inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(size + 1));
+ FAIL_IF(!inst);
+
+ INC_SIZE((sljit_uw)size);
+
+ if (!(options & SLJIT_ENTER_REG_ARG))
+ PUSH_REG(reg_map[TMP_REG1]);
+
+ if ((saveds > 2 && kept_saveds_count <= 2) || scratches > 9)
+ PUSH_REG(reg_map[SLJIT_S2]);
+ if ((saveds > 1 && kept_saveds_count <= 1) || scratches > 10)
+ PUSH_REG(reg_map[SLJIT_S1]);
+ if ((saveds > 0 && kept_saveds_count == 0) || scratches > 11)
+ PUSH_REG(reg_map[SLJIT_S0]);
+
+ size *= SSIZE_OF(sw);
+ }
+
+ if (status & (ENTER_TMP_TO_R4 | ENTER_TMP_TO_S))
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), args_size + size);
+
+ size += SSIZE_OF(sw);
+
+ local_size = ((SLJIT_LOCALS_OFFSET_BASE + local_size + size + 0xf) & ~0xf) - size;
+ compiler->local_size = local_size;
+
+ word_arg_count = 0;
+ saved_arg_count = 0;
+ args_size = size;
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ args_size += SSIZE_OF(f64);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ args_size += SSIZE_OF(f32);
+ break;
+ default:
+ word_arg_count++;
+ SLJIT_ASSERT(word_arg_count <= 3 || (word_arg_count == 4 && !(status & (ENTER_TMP_TO_R4 | ENTER_TMP_TO_S))));
+
+ if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) {
+#ifdef _WIN32
+ if (word_arg_count == 3 && local_size > 4 * 4096)
+ r2_offset = local_size + args_size;
+ else
+#endif
+ EMIT_MOV(compiler, word_arg_count, 0, SLJIT_MEM1(SLJIT_SP), args_size);
+
+ } else {
+ EMIT_MOV(compiler, SLJIT_S0 - saved_arg_count, 0, SLJIT_MEM1(SLJIT_SP), args_size);
+ saved_arg_count++;
+ }
+
+ args_size += SSIZE_OF(sw);
+ break;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ SLJIT_ASSERT(SLJIT_LOCALS_OFFSET > 0);
+
+#ifdef _WIN32
+ SLJIT_ASSERT(r2_offset == -1 || local_size > 4 * 4096);
+
+ if (local_size > 4096) {
+ if (local_size <= 4 * 4096) {
+ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096);
+
+ if (local_size > 2 * 4096)
+ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 2);
+ if (local_size > 3 * 4096)
+ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3);
+ }
+ else {
+ if (options & SLJIT_ENTER_REG_ARG) {
+ SLJIT_ASSERT(r2_offset == -1);
+
+ inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(1 + 1));
+ FAIL_IF(!inst);
+ INC_SIZE(1);
+ PUSH_REG(reg_map[SLJIT_R2]);
+
+ local_size -= SSIZE_OF(sw);
+ r2_offset = local_size;
+ }
+
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_IMM, local_size >> 12);
+
+ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096);
+ BINARY_IMM32(SUB, 4096, SLJIT_SP, 0);
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+
+ INC_SIZE(2);
+ inst[0] = LOOP_i8;
+ inst[1] = (sljit_u8)-16;
+ local_size &= 0xfff;
+ }
+ }
+
+ if (local_size > 0) {
+ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -local_size);
+ BINARY_IMM32(SUB, local_size, SLJIT_SP, 0);
+ }
+
+ if (r2_offset != -1)
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), r2_offset);
+
+#else /* !_WIN32 */
+
+ SLJIT_ASSERT(local_size > 0);
+
+ BINARY_IMM32(SUB, local_size, SLJIT_SP, 0);
+
+#endif /* _WIN32 */
+
+ size = SLJIT_LOCALS_OFFSET_BASE - SSIZE_OF(sw);
+ kept_saveds_count = SLJIT_R3 - kept_saveds_count;
+
+ while (saved_arg_count > 3) {
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), size, kept_saveds_count, 0);
+ kept_saveds_count++;
+ size -= SSIZE_OF(sw);
+ saved_arg_count--;
+ }
+
+ if (status & (ENTER_TMP_TO_R4 | ENTER_TMP_TO_S)) {
+ if (status & ENTER_TMP_TO_R4)
+ size = 2 * SSIZE_OF(sw);
+
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), size, TMP_REG1, 0);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 args_size;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ args_size = 0;
+
+ if (!(options & SLJIT_ENTER_REG_ARG)) {
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ args_size += SSIZE_OF(f64);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ args_size += SSIZE_OF(f32);
+ break;
+ default:
+ args_size += SSIZE_OF(sw);
+ break;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+ }
+
+ compiler->args_size = args_size;
+
+ /* [esp+0] for saving temporaries and for function calls. */
+
+ saveds = (1 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3) - SLJIT_KEPT_SAVEDS_COUNT(options)) * SSIZE_OF(sw);
+
+ /* Saving ebp. */
+ if (!(options & SLJIT_ENTER_REG_ARG))
+ saveds += SSIZE_OF(sw);
+
+ compiler->local_size = ((SLJIT_LOCALS_OFFSET_BASE + local_size + saveds + 0xf) & ~0xf) - saveds;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)
+{
+ sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);
+ sljit_s32 local_size, saveds;
+ sljit_uw size;
+ sljit_u8 *inst;
+
+ size = (sljit_uw)((compiler->scratches > 9 ? (compiler->scratches - 9) : 0) +
+ (compiler->saveds <= 3 ? compiler->saveds : 3) - kept_saveds_count);
+
+ local_size = compiler->local_size;
+
+ if (!(compiler->options & SLJIT_ENTER_REG_ARG))
+ size++;
+ else if (is_return_to && size == 0) {
+ local_size += SSIZE_OF(sw);
+ is_return_to = 0;
+ }
+
+ if (local_size > 0)
+ BINARY_IMM32(ADD, local_size, SLJIT_SP, 0);
+
+ if (size == 0)
+ return SLJIT_SUCCESS;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+
+ INC_SIZE(size);
+
+ saveds = compiler->saveds;
+
+ if ((saveds > 0 && kept_saveds_count == 0) || compiler->scratches > 11)
+ POP_REG(reg_map[SLJIT_S0]);
+ if ((saveds > 1 && kept_saveds_count <= 1) || compiler->scratches > 10)
+ POP_REG(reg_map[SLJIT_S1]);
+ if ((saveds > 2 && kept_saveds_count <= 2) || compiler->scratches > 9)
+ POP_REG(reg_map[SLJIT_S2]);
+
+ if (!(compiler->options & SLJIT_ENTER_REG_ARG))
+ POP_REG(reg_map[TMP_REG1]);
+
+ if (is_return_to)
+ BINARY_IMM32(ADD, sizeof(sljit_sw), SLJIT_SP, 0);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ SLJIT_ASSERT(compiler->args_size >= 0);
+ SLJIT_ASSERT(compiler->local_size > 0);
+
+ FAIL_IF(emit_stack_frame_release(compiler, 0));
+
+ return emit_byte(compiler, RET_near);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 src_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));
+
+ if ((src & SLJIT_MEM) || (src > SLJIT_R2 && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ CHECK_EXTRA_REGS(src, srcw, (void)0);
+
+ src_r = (compiler->options & SLJIT_ENTER_REG_ARG) ? TMP_REG1 : SLJIT_R1;
+
+ EMIT_MOV(compiler, src_r, 0, src, srcw);
+ src = src_r;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 1));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
+}
+
+/* --------------------------------------------------------------------- */
+/* Call / return instructions */
+/* --------------------------------------------------------------------- */
+
+static sljit_s32 call_get_stack_size(sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr)
+{
+ sljit_sw stack_size = 0;
+ sljit_s32 word_arg_count = 0;
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ stack_size += SSIZE_OF(f64);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ stack_size += SSIZE_OF(f32);
+ break;
+ default:
+ word_arg_count++;
+ stack_size += SSIZE_OF(sw);
+ break;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ if (word_arg_count_ptr)
+ *word_arg_count_ptr = word_arg_count;
+
+ if (stack_size <= 4 * SSIZE_OF(sw))
+ return 0;
+
+ return ((stack_size - (4 * SSIZE_OF(sw)) + 0xf) & ~0xf);
+}
+
+static sljit_s32 call_with_args(struct sljit_compiler *compiler,
+ sljit_s32 arg_types, sljit_sw stack_size, sljit_s32 word_arg_count, sljit_s32 keep_tmp1)
+{
+ sljit_s32 float_arg_count = 0, arg4_reg = 0, arg_offset;
+ sljit_u8 *inst;
+
+ if (word_arg_count >= 4) {
+ arg4_reg = SLJIT_R0;
+
+ if (!keep_tmp1) {
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), 2 * SSIZE_OF(sw));
+ arg4_reg = TMP_REG1;
+ }
+ }
+
+ if (stack_size > 0)
+ BINARY_IMM32(SUB, stack_size, SLJIT_SP, 0);
+
+ arg_offset = 0;
+ word_arg_count = 0;
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ float_arg_count++;
+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), arg_offset, float_arg_count));
+ arg_offset += SSIZE_OF(f64);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ float_arg_count++;
+ FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), arg_offset, float_arg_count));
+ arg_offset += SSIZE_OF(f32);
+ break;
+ default:
+ word_arg_count++;
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), arg_offset, (word_arg_count >= 4) ? arg4_reg : word_arg_count, 0);
+
+ if (word_arg_count == 1 && arg4_reg == SLJIT_R0)
+ EMIT_MOV(compiler, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), 2 * SSIZE_OF(sw) + stack_size);
+
+ arg_offset += SSIZE_OF(sw);
+ break;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 post_call_with_args(struct sljit_compiler *compiler,
+ sljit_s32 arg_types, sljit_s32 stack_size)
+{
+ sljit_u8 *inst;
+ sljit_s32 single;
+
+ if (stack_size > 0)
+ BINARY_IMM32(ADD, stack_size, SLJIT_SP, 0);
+
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64)
+ return SLJIT_SUCCESS;
+
+ single = ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32);
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);
+ FAIL_IF(!inst);
+ INC_SIZE(3);
+ inst[0] = single ? FSTPS : FSTPD;
+ inst[1] = (0x03 << 3) | 0x04;
+ inst[2] = (0x04 << 3) | reg_map[SLJIT_SP];
+
+ return emit_sse2_load(compiler, single, SLJIT_FR0, SLJIT_MEM1(SLJIT_SP), 0);
+}
+
+static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler,
+ sljit_s32 *extra_space, sljit_s32 arg_types,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_sw args_size, saved_regs_size;
+ sljit_sw types, word_arg_count, float_arg_count;
+ sljit_sw stack_size, prev_stack_size, min_size, offset;
+ sljit_sw word_arg4_offset;
+ sljit_u8 r2_offset = 0;
+ sljit_s32 kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);
+ sljit_u8* inst;
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ CHECK_EXTRA_REGS(src, srcw, (void)0);
+
+ saved_regs_size = (1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0)
+ + (compiler->saveds <= 3 ? compiler->saveds : 3) - kept_saveds_count) * SSIZE_OF(sw);
+
+ word_arg_count = 0;
+ float_arg_count = 0;
+ arg_types >>= SLJIT_ARG_SHIFT;
+ types = 0;
+ args_size = 0;
+
+ while (arg_types != 0) {
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
+
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ args_size += SSIZE_OF(f64);
+ float_arg_count++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ args_size += SSIZE_OF(f32);
+ float_arg_count++;
+ break;
+ default:
+ word_arg_count++;
+ args_size += SSIZE_OF(sw);
+ break;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ if (args_size <= compiler->args_size) {
+ *extra_space = 0;
+ stack_size = args_size + SSIZE_OF(sw) + saved_regs_size;
+
+ offset = stack_size + compiler->local_size;
+
+ if (src != SLJIT_IMM && src != SLJIT_R0) {
+ if (word_arg_count >= 1) {
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0);
+ r2_offset = sizeof(sljit_sw);
+ }
+ EMIT_MOV(compiler, SLJIT_R0, 0, src, srcw);
+ }
+
+ while (types != 0) {
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));
+ float_arg_count--;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ offset -= SSIZE_OF(f32);
+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));
+ float_arg_count--;
+ break;
+ default:
+ switch (word_arg_count) {
+ case 1:
+ offset -= SSIZE_OF(sw);
+ if (r2_offset != 0) {
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), 0);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);
+ } else
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R0, 0);
+ break;
+ case 2:
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R1, 0);
+ break;
+ case 3:
+ offset -= SSIZE_OF(sw);
+ break;
+ case 4:
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), 2 * SSIZE_OF(sw));
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);
+ break;
+ }
+ word_arg_count--;
+ break;
+ }
+ types >>= SLJIT_ARG_SHIFT;
+ }
+
+ return emit_stack_frame_release(compiler, 0);
+ }
+
+ stack_size = args_size + SSIZE_OF(sw);
+
+ if (word_arg_count >= 1 && src != SLJIT_IMM && src != SLJIT_R0) {
+ r2_offset = SSIZE_OF(sw);
+ stack_size += SSIZE_OF(sw);
+ }
+
+ if (word_arg_count >= 3)
+ stack_size += SSIZE_OF(sw);
+
+ prev_stack_size = SSIZE_OF(sw) + saved_regs_size;
+ min_size = prev_stack_size + compiler->local_size;
+
+ word_arg4_offset = 2 * SSIZE_OF(sw);
+
+ if (stack_size > min_size) {
+ BINARY_IMM32(SUB, stack_size - min_size, SLJIT_SP, 0);
+ if (src == SLJIT_MEM1(SLJIT_SP))
+ srcw += stack_size - min_size;
+ word_arg4_offset += stack_size - min_size;
+ }
+ else
+ stack_size = min_size;
+
+ if (word_arg_count >= 3) {
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), r2_offset, SLJIT_R2, 0);
+
+ if (word_arg_count >= 4)
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), word_arg4_offset);
+ }
+
+ if (src != SLJIT_IMM && src != SLJIT_R0) {
+ if (word_arg_count >= 1) {
+ SLJIT_ASSERT(r2_offset == sizeof(sljit_sw));
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0);
+ }
+ EMIT_MOV(compiler, SLJIT_R0, 0, src, srcw);
+ }
+
+ /* Restore saved registers. */
+ offset = stack_size - 2 * SSIZE_OF(sw);
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), offset);
+
+ if (compiler->saveds > 2 || compiler->scratches > 9) {
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), offset);
+ }
+ if ((compiler->saveds > 1 && kept_saveds_count <= 1) || compiler->scratches > 10) {
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_SP), offset);
+ }
+ if ((compiler->saveds > 0 && kept_saveds_count == 0) || compiler->scratches > 11) {
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), offset);
+ }
+
+ /* Copy fourth argument and return address. */
+ offset = stack_size - SSIZE_OF(sw);
+ *extra_space = args_size;
+
+ if (word_arg_count >= 4) {
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);
+ }
+
+ while (types != 0) {
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));
+ float_arg_count--;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ offset -= SSIZE_OF(f32);
+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));
+ float_arg_count--;
+ break;
+ default:
+ switch (word_arg_count) {
+ case 1:
+ offset -= SSIZE_OF(sw);
+ if (r2_offset != 0) {
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), 0);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);
+ } else
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R0, 0);
+ break;
+ case 2:
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R1, 0);
+ break;
+ case 3:
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), r2_offset);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);
+ break;
+ }
+ word_arg_count--;
+ break;
+ }
+ types >>= SLJIT_ARG_SHIFT;
+ }
+
+ SLJIT_ASSERT(offset >= 0);
+
+ if (offset == 0)
+ return SLJIT_SUCCESS;
+
+ BINARY_IMM32(ADD, offset, SLJIT_SP, 0);
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_tail_call_end(struct sljit_compiler *compiler, sljit_s32 extra_space)
+{
+ /* Called when stack consumption cannot be reduced to 0. */
+ sljit_u8 *inst;
+
+ BINARY_IMM32(ADD, extra_space, SLJIT_SP, 0);
+ return emit_byte(compiler, RET_near);
+}
+
+static sljit_s32 tail_call_reg_arg_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
+{
+ sljit_s32 word_arg_count = 0;
+ sljit_s32 kept_saveds_count, offset;
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ while (arg_types) {
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64)
+ word_arg_count++;
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ if (word_arg_count < 4)
+ return SLJIT_SUCCESS;
+
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), 2 * SSIZE_OF(sw));
+
+ kept_saveds_count = SLJIT_KEPT_SAVEDS_COUNT(compiler->options);
+ offset = compiler->local_size + 3 * SSIZE_OF(sw);
+
+ if ((compiler->saveds > 0 && kept_saveds_count == 0) || compiler->scratches > 11)
+ offset += SSIZE_OF(sw);
+ if ((compiler->saveds > 1 && kept_saveds_count <= 1) || compiler->scratches > 10)
+ offset += SSIZE_OF(sw);
+ if ((compiler->saveds > 2 && kept_saveds_count <= 2) || compiler->scratches > 9)
+ offset += SSIZE_OF(sw);
+
+ return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), offset, TMP_REG1, 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types)
+{
+ struct sljit_jump *jump;
+ sljit_sw stack_size = 0;
+ sljit_s32 word_arg_count;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
+
+ if (type & SLJIT_CALL_RETURN) {
+ if ((type & 0xff) == SLJIT_CALL_REG_ARG) {
+ PTR_FAIL_IF(tail_call_reg_arg_with_args(compiler, arg_types));
+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_jump(compiler, SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP));
+ }
+
+ stack_size = type;
+ PTR_FAIL_IF(tail_call_with_args(compiler, &stack_size, arg_types, SLJIT_IMM, 0));
+
+ SLJIT_SKIP_CHECKS(compiler);
+
+ if (stack_size == 0)
+ return sljit_emit_jump(compiler, SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP));
+
+ jump = sljit_emit_jump(compiler, type);
+ PTR_FAIL_IF(jump == NULL);
+
+ PTR_FAIL_IF(emit_tail_call_end(compiler, stack_size));
+ return jump;
+ }
+
+ if ((type & 0xff) == SLJIT_CALL_REG_ARG) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_jump(compiler, type);
+ }
+
+ stack_size = call_get_stack_size(arg_types, &word_arg_count);
+ PTR_FAIL_IF(call_with_args(compiler, arg_types, stack_size, word_arg_count, 0));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ jump = sljit_emit_jump(compiler, type);
+ PTR_FAIL_IF(jump == NULL);
+
+ PTR_FAIL_IF(post_call_with_args(compiler, arg_types, stack_size));
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_sw stack_size = 0;
+ sljit_s32 word_arg_count;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
+
+ if (type & SLJIT_CALL_RETURN) {
+ if ((type & 0xff) == SLJIT_CALL_REG_ARG) {
+ FAIL_IF(tail_call_reg_arg_with_args(compiler, arg_types));
+
+ if ((src & SLJIT_MEM) || (src > SLJIT_R2 && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ CHECK_EXTRA_REGS(src, srcw, (void)0);
+
+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
+ src = TMP_REG1;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 0));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
+ }
+
+ stack_size = type;
+ FAIL_IF(tail_call_with_args(compiler, &stack_size, arg_types, src, srcw));
+
+ if (src != SLJIT_IMM) {
+ src = SLJIT_R0;
+ srcw = 0;
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+
+ if (stack_size == 0)
+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
+
+ FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
+ return emit_tail_call_end(compiler, stack_size);
+ }
+
+ if ((type & 0xff) == SLJIT_CALL_REG_ARG) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, type, src, srcw);
+ }
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ CHECK_EXTRA_REGS(src, srcw, (void)0);
+
+ if (src & SLJIT_MEM) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
+ src = TMP_REG1;
+ srcw = 0;
+ }
+
+ stack_size = call_get_stack_size(arg_types, &word_arg_count);
+ FAIL_IF(call_with_args(compiler, arg_types, stack_size, word_arg_count, src == TMP_REG1));
+
+ if (stack_size > 0 && src == SLJIT_MEM1(SLJIT_SP))
+ srcw += stack_size;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
+
+ return post_call_with_args(compiler, arg_types, stack_size);
+}
+
+static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8* inst;
+
+ if (compiler->options & SLJIT_ENTER_REG_ARG) {
+ if (src == SLJIT_FR0)
+ return SLJIT_SUCCESS;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_fop1(compiler, op, SLJIT_RETURN_FREG, 0, src, srcw);
+ }
+
+ if (FAST_IS_REG(src)) {
+ FAIL_IF(emit_sse2_store(compiler, op & SLJIT_32, SLJIT_MEM1(SLJIT_SP), 0, src));
+
+ src = SLJIT_MEM1(SLJIT_SP);
+ srcw = 0;
+ } else {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ }
+
+ inst = emit_x86_instruction(compiler, 1 | EX86_SSE2_OP1, 0, 0, src, srcw);
+ *inst = (op & SLJIT_32) ? FLDS : FLDL;
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_u8 *inst;
+
+ CHECK_EXTRA_REGS(dst, dstw, (void)0);
+
+ /* Unused dest is possible here. */
+ if (FAST_IS_REG(dst))
+ return emit_byte(compiler, U8(POP_r + reg_map[dst]));
+
+ /* Memory. */
+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = POP_rm;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8 *inst;
+
+ CHECK_EXTRA_REGS(src, srcw, (void)0);
+
+ if (FAST_IS_REG(src)) {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);
+ FAIL_IF(!inst);
+
+ INC_SIZE(1 + 1);
+ PUSH_REG(reg_map[src]);
+ }
+ else {
+ inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
+ FAIL_IF(!inst);
+ inst[0] = GROUP_FF;
+ inst[1] |= PUSH_rm;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
+ INC_SIZE(1);
+ }
+
+ RET();
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 sljit_emit_get_return_address(struct sljit_compiler *compiler,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 options = compiler->options;
+ sljit_s32 saveds = compiler->saveds;
+ sljit_s32 scratches = compiler->scratches;
+
+ saveds = ((scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3) - SLJIT_KEPT_SAVEDS_COUNT(options)) * SSIZE_OF(sw);
+
+ /* Saving ebp. */
+ if (!(options & SLJIT_ENTER_REG_ARG))
+ saveds += SSIZE_OF(sw);
+
+ return emit_mov(compiler, dst, dstw, SLJIT_MEM1(SLJIT_SP), compiler->local_size + saveds);
+}
+
+/* --------------------------------------------------------------------- */
+/* Other operations */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_reg)
+{
+ sljit_s32 dst = dst_reg;
+ sljit_sw dstw = 0;
+ sljit_sw src2w = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ CHECK_EXTRA_REGS(dst, dstw, (void)0);
+ CHECK_EXTRA_REGS(src1, src1w, (void)0);
+ CHECK_EXTRA_REGS(src2_reg, src2w, (void)0);
+
+ if (dst & SLJIT_MEM) {
+ if (src1 == SLJIT_IMM || (!(src1 & SLJIT_MEM) && (src2_reg & SLJIT_MEM))) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ src1 = src2_reg;
+ src1w = src2w;
+ if (!(type & SLJIT_COMPARE_SELECT))
+ type ^= 0x1;
+ } else
+ EMIT_MOV(compiler, TMP_REG1, 0, src2_reg, src2w);
+
+ dst_reg = TMP_REG1;
+ } else if (dst_reg != src2_reg) {
+ if (dst_reg == src1) {
+ src1 = src2_reg;
+ src1w = src2w;
+ if (!(type & SLJIT_COMPARE_SELECT))
+ type ^= 0x1;
+ } else if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
+ EMIT_MOV(compiler, dst_reg, 0, src1, src1w);
+ src1 = src2_reg;
+ src1w = src2w;
+ if (!(type & SLJIT_COMPARE_SELECT))
+ type ^= 0x1;
+ } else
+ EMIT_MOV(compiler, dst_reg, 0, src2_reg, src2w);
+ }
+
+ if (type & SLJIT_COMPARE_SELECT) {
+ if (dst_reg != TMP_REG1 && !FAST_IS_REG(src1)) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ src1 = TMP_REG1;
+ src1w = 0;
+ }
+
+ type ^= 0x1;
+ FAIL_IF(emit_cmp_binary(compiler, dst_reg, 0, src1, src1w));
+ }
+
+ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);
+
+ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV)) {
+ if (SLJIT_UNLIKELY(src1 == SLJIT_IMM)) {
+ if (dst_reg != TMP_REG1) {
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, src1w);
+ src1 = TMP_REG1;
+ src1w = 0;
+ } else {
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, src1w);
+ src1 = SLJIT_MEM1(SLJIT_SP);
+ src1w = 0;
+ }
+ }
+
+ FAIL_IF(emit_groupf(compiler, U8(get_jump_code((sljit_uw)type) - 0x40), dst_reg, src1, src1w));
+ } else
+ FAIL_IF(emit_cmov_generic(compiler, type, dst_reg, src1, src1w));
+
+ if (dst & SLJIT_MEM)
+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_u8* inst;
+ sljit_s32 i, next, reg_idx, offset;
+ sljit_u8 regs[2];
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
+
+ if (!(reg & REG_PAIR_MASK))
+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
+
+ ADJUST_LOCAL_OFFSET(mem, memw);
+
+ regs[0] = U8(REG_PAIR_FIRST(reg));
+ regs[1] = U8(REG_PAIR_SECOND(reg));
+
+ next = SSIZE_OF(sw);
+
+ if (!(type & SLJIT_MEM_STORE) && (regs[0] == (mem & REG_MASK) || regs[0] == OFFS_REG(mem))) {
+ if (regs[1] == (mem & REG_MASK) || regs[1] == OFFS_REG(mem)) {
+ /* None of them are virtual register so TMP_REG1 will not be used. */
+ EMIT_MOV(compiler, TMP_REG1, 0, OFFS_REG(mem), 0);
+
+ if (regs[1] == OFFS_REG(mem))
+ next = -SSIZE_OF(sw);
+
+ mem = (mem & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);
+ } else {
+ next = -SSIZE_OF(sw);
+
+ if (!(mem & OFFS_REG_MASK))
+ memw += SSIZE_OF(sw);
+ }
+ }
+
+ for (i = 0; i < 2; i++) {
+ reg_idx = next > 0 ? i : (i ^ 0x1);
+ reg = regs[reg_idx];
+
+ offset = -1;
+
+ if (reg >= SLJIT_R3 && reg <= SLJIT_S3) {
+ offset = (2 * SSIZE_OF(sw)) + ((reg) - SLJIT_R3) * SSIZE_OF(sw);
+ reg = TMP_REG1;
+
+ if (type & SLJIT_MEM_STORE)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), offset);
+ }
+
+ if ((mem & OFFS_REG_MASK) && (reg_idx == 1)) {
+ inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(1 + 4));
+ FAIL_IF(!inst);
+
+ INC_SIZE(4);
+
+ inst[0] = (type & SLJIT_MEM_STORE) ? MOV_rm_r : MOV_r_rm;
+ inst[1] = 0x44 | U8(reg_map[reg] << 3);
+ inst[2] = U8(memw << 6) | U8(reg_map[OFFS_REG(mem)] << 3) | reg_map[mem & REG_MASK];
+ inst[3] = sizeof(sljit_sw);
+ } else if (type & SLJIT_MEM_STORE) {
+ EMIT_MOV(compiler, mem, memw, reg, 0);
+ } else {
+ EMIT_MOV(compiler, reg, 0, mem, memw);
+ }
+
+ if (!(mem & OFFS_REG_MASK))
+ memw += next;
+
+ if (!(type & SLJIT_MEM_STORE) && offset != -1)
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, TMP_REG1, 0);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG;
+ sljit_u8 *inst, *jump_inst1, *jump_inst2;
+ sljit_uw size1, size2;
+
+ /* Binary representation of 0x80000000. */
+ static const sljit_f64 f64_high_bit = (sljit_f64)0x80000000ul;
+
+ CHECK_EXTRA_REGS(src, srcw, (void)0);
+
+ if (!(op & SLJIT_32)) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
+
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0);
+ FAIL_IF(!inst);
+ inst[1] |= ROL;
+
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0);
+ FAIL_IF(!inst);
+ inst[1] |= SHR;
+
+ FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_PREF_F2 | EX86_SSE2_OP1, dst_r, TMP_REG1, 0));
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(2);
+ inst[0] = U8(get_jump_code(SLJIT_NOT_CARRY) - 0x10);
+
+ size1 = compiler->size;
+ FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_PREF_F2 | EX86_SSE2, dst_r, SLJIT_MEM0(), (sljit_sw)&f64_high_bit));
+
+ inst[1] = U8(compiler->size - size1);
+
+ if (dst_r == TMP_FREG)
+ return emit_sse2_store(compiler, 0, dst, dstw, TMP_FREG);
+ return SLJIT_SUCCESS;
+ }
+
+ if (!FAST_IS_REG(src)) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
+ src = TMP_REG1;
+ }
+
+ BINARY_IMM32(CMP, 0, src, 0);
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(2);
+ inst[0] = JL_i8;
+ jump_inst1 = inst;
+
+ size1 = compiler->size;
+
+ FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, src, 0));
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(2);
+ inst[0] = JMP_i8;
+ jump_inst2 = inst;
+
+ size2 = compiler->size;
+
+ jump_inst1[1] = U8(size2 - size1);
+
+ if (src != TMP_REG1)
+ EMIT_MOV(compiler, TMP_REG1, 0, src, 0);
+
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0);
+ FAIL_IF(!inst);
+ inst[1] |= SHR;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(2);
+ inst[0] = JNC_i8;
+ jump_inst1 = inst;
+
+ size1 = compiler->size;
+
+ BINARY_IMM32(OR, 1, TMP_REG1, 0);
+ jump_inst1[1] = U8(compiler->size - size1);
+
+ FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, TMP_REG1, 0));
+ FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, dst_r, 0));
+
+ jump_inst2[1] = U8(compiler->size - size2);
+
+ if (dst_r == TMP_FREG)
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f32 value)
+{
+ sljit_u8 *inst;
+ union {
+ sljit_s32 imm;
+ sljit_f32 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset32(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm != 0)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm);
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+
+ inst[0] = GROUP_66;
+ inst[1] = GROUP_0F;
+
+ if (u.imm == 0) {
+ inst[2] = PXOR_x_xm;
+ inst[3] = U8(freg_map[freg] | (freg_map[freg] << 3) | MOD_REG);
+ } else {
+ inst[2] = MOVD_x_rm;
+ inst[3] = U8(reg_map[TMP_REG1] | (freg_map[freg] << 3) | MOD_REG);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value)
+{
+ sljit_u8 *inst;
+ union {
+ sljit_s32 imm[2];
+ sljit_f64 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset64(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm[0] == 0) {
+ if (u.imm[1] == 0)
+ return emit_groupf(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2, freg, freg, 0);
+
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm[1]);
+ } else {
+ SLJIT_ASSERT(cpu_feature_list != 0);
+
+ if (!(cpu_feature_list & CPU_FEATURE_SSE41) && u.imm[1] != 0 && u.imm[0] != u.imm[1]) {
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, u.imm[0]);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_sw), SLJIT_IMM, u.imm[1]);
+
+ return emit_groupf(compiler, MOVLPD_x_m | EX86_SSE2, freg, SLJIT_MEM1(SLJIT_SP), 0);
+ }
+
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm[0]);
+ }
+
+ FAIL_IF(emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, freg, TMP_REG1, 0));
+
+ if (u.imm[1] == 0)
+ return SLJIT_SUCCESS;
+
+ if (u.imm[0] == 0) {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+
+ inst[0] = GROUP_0F;
+ inst[1] = SHUFPS_x_xm;
+ inst[2] = U8(MOD_REG | (freg_map[freg] << 3) | freg_map[freg]);
+ inst[3] = 0x51;
+ return SLJIT_SUCCESS;
+ }
+
+ if (u.imm[0] != u.imm[1]) {
+ SLJIT_ASSERT(cpu_feature_list & CPU_FEATURE_SSE41);
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm[1]);
+
+ FAIL_IF(emit_groupf_ext(compiler, PINSRD_x_rm_i8 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2_OP1, freg, TMP_REG1, 0));
+ return emit_byte(compiler, 1);
+ }
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);
+ FAIL_IF(!inst);
+ INC_SIZE(3);
+
+ inst[0] = GROUP_0F;
+ inst[1] = UNPCKLPS_x_xm;
+ inst[2] = U8(MOD_REG | (freg_map[freg] << 3) | freg_map[freg]);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg)
+{
+ sljit_u8 *inst;
+ sljit_s32 reg2;
+ sljit_sw regw, reg2w;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
+
+ regw = 0;
+ reg2 = 0;
+ reg2w = 0;
+
+ SLJIT_ASSERT(cpu_feature_list != 0);
+
+ if (!(op & SLJIT_32) && (cpu_feature_list & CPU_FEATURE_SSE41)) {
+ if (reg & REG_PAIR_MASK) {
+ reg2 = REG_PAIR_FIRST(reg);
+ reg = REG_PAIR_SECOND(reg);
+
+ CHECK_EXTRA_REGS(reg, regw, (void)0);
+
+ FAIL_IF(emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x)
+ | EX86_PREF_66 | EX86_SSE2_OP1, freg, reg, regw));
+ } else
+ reg2 = reg;
+
+ CHECK_EXTRA_REGS(reg2, reg2w, (void)0);
+
+ FAIL_IF(emit_groupf_ext(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? PINSRD_x_rm_i8 : PEXTRD_rm_x_i8)
+ | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2_OP1, freg, reg2, reg2w));
+ return emit_byte(compiler, 1);
+ }
+
+ if (reg & REG_PAIR_MASK) {
+ reg2 = REG_PAIR_SECOND(reg);
+ reg = REG_PAIR_FIRST(reg);
+
+ if (reg == reg2)
+ reg = 0;
+
+ CHECK_EXTRA_REGS(reg2, reg2w, (void)0);
+ }
+
+ CHECK_EXTRA_REGS(reg, regw, (void)0);
+
+ if (op & SLJIT_32)
+ return emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x)
+ | EX86_PREF_66 | EX86_SSE2_OP1, freg, reg, regw);
+
+ if (op == SLJIT_COPY_FROM_F64) {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 5);
+ FAIL_IF(!inst);
+ INC_SIZE(5);
+
+ inst[0] = GROUP_66;
+ inst[1] = GROUP_0F;
+ inst[2] = PSHUFD_x_xm;
+ inst[3] = U8(MOD_REG | (TMP_FREG << 3) | freg_map[freg]);
+ inst[4] = 1;
+ } else if (reg != 0)
+ FAIL_IF(emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, TMP_FREG, reg, regw));
+
+ if (reg2 != 0)
+ FAIL_IF(emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x)
+ | EX86_PREF_66 | EX86_SSE2_OP1, freg, reg2, reg2w));
+
+ if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);
+ FAIL_IF(!inst);
+ INC_SIZE(3);
+
+ inst[0] = GROUP_0F;
+ inst[1] = UNPCKLPS_x_xm;
+ inst[2] = U8(MOD_REG | (freg_map[freg] << 3) | freg_map[reg == 0 ? freg : TMP_FREG]);
+ } else
+ FAIL_IF(emit_groupf(compiler, MOVD_rm_x | EX86_PREF_66 | EX86_SSE2_OP1, TMP_FREG, reg, regw));
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler)
+{
+ sljit_sw size;
+
+ /* Don't adjust shadow stack if it isn't enabled. */
+ if (!cpu_has_shadow_stack())
+ return SLJIT_SUCCESS;
+
+ SLJIT_ASSERT(compiler->args_size >= 0);
+ SLJIT_ASSERT(compiler->local_size > 0);
+
+ size = compiler->local_size;
+ size += (1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0)
+ + (compiler->saveds <= 3 ? compiler->saveds : 3)) * SSIZE_OF(sw);
+
+ return adjust_shadow_stack(compiler, SLJIT_MEM1(SLJIT_SP), size);
+}
diff --git a/deps/sljit/sljit_src/sljitNativeX86_64.c b/deps/sljit/sljit_src/sljitNativeX86_64.c
new file mode 100644
index 0000000..0a2f59d
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativeX86_64.c
@@ -0,0 +1,1430 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* x86 64-bit arch dependent functions. */
+
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
+static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
+{
+ sljit_u8 *inst;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw));
+ FAIL_IF(!inst);
+ INC_SIZE(2 + sizeof(sljit_sw));
+ inst[0] = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
+ inst[1] = U8(MOV_r_i32 | reg_lmap[reg]);
+ sljit_unaligned_store_sw(inst + 2, imm);
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_do_imm32(struct sljit_compiler *compiler, sljit_u8 rex, sljit_u8 opcode, sljit_sw imm)
+{
+ sljit_u8 *inst;
+ sljit_uw length = (rex ? 2 : 1) + sizeof(sljit_s32);
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + length);
+ FAIL_IF(!inst);
+ INC_SIZE(length);
+ if (rex)
+ *inst++ = rex;
+ *inst++ = opcode;
+ sljit_unaligned_store_s32(inst, (sljit_s32)imm);
+ return SLJIT_SUCCESS;
+}
+
+static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw size,
+ /* The register or immediate operand. */
+ sljit_s32 a, sljit_sw imma,
+ /* The general operand (not immediate). */
+ sljit_s32 b, sljit_sw immb)
+{
+ sljit_u8 *inst;
+ sljit_u8 *buf_ptr;
+ sljit_u8 rex = 0;
+ sljit_u8 reg_lmap_b;
+ sljit_uw flags = size;
+ sljit_uw inst_size;
+
+ /* The immediate operand must be 32 bit. */
+ SLJIT_ASSERT(a != SLJIT_IMM || compiler->mode32 || IS_HALFWORD(imma));
+ /* Both cannot be switched on. */
+ SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
+ /* Size flags not allowed for typed instructions. */
+ SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);
+ /* Both size flags cannot be switched on. */
+ SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
+ /* SSE2 and immediate is not possible. */
+ SLJIT_ASSERT(a != SLJIT_IMM || !(flags & EX86_SSE2));
+ SLJIT_ASSERT(((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))
+ & ((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0);
+ SLJIT_ASSERT((flags & (EX86_VEX_EXT | EX86_REX)) != EX86_VEX_EXT);
+
+ size &= 0xf;
+ /* The mod r/m byte is always present. */
+ inst_size = size + 1;
+
+ if (!compiler->mode32 && !(flags & EX86_NO_REXW))
+ rex |= REX_W;
+ else if (flags & EX86_REX)
+ rex |= REX;
+
+ if (flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))
+ inst_size++;
+
+ /* Calculate size of b. */
+ if (b & SLJIT_MEM) {
+ if (!(b & OFFS_REG_MASK) && NOT_HALFWORD(immb)) {
+ PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));
+ immb = 0;
+ if (b & REG_MASK)
+ b |= TO_OFFS_REG(TMP_REG2);
+ else
+ b |= TMP_REG2;
+ }
+
+ if (!(b & REG_MASK))
+ inst_size += 1 + sizeof(sljit_s32); /* SIB byte required to avoid RIP based addressing. */
+ else {
+ if (immb != 0 && !(b & OFFS_REG_MASK)) {
+ /* Immediate operand. */
+ if (immb <= 127 && immb >= -128)
+ inst_size += sizeof(sljit_s8);
+ else
+ inst_size += sizeof(sljit_s32);
+ } else if (reg_lmap[b & REG_MASK] == 5) {
+ /* Swap registers if possible. */
+ if ((b & OFFS_REG_MASK) && (immb & 0x3) == 0 && reg_lmap[OFFS_REG(b)] != 5)
+ b = SLJIT_MEM | OFFS_REG(b) | TO_OFFS_REG(b & REG_MASK);
+ else
+ inst_size += sizeof(sljit_s8);
+ }
+
+ if (reg_map[b & REG_MASK] >= 8)
+ rex |= REX_B;
+
+ if (reg_lmap[b & REG_MASK] == 4 && !(b & OFFS_REG_MASK))
+ b |= TO_OFFS_REG(SLJIT_SP);
+
+ if (b & OFFS_REG_MASK) {
+ inst_size += 1; /* SIB byte. */
+ if (reg_map[OFFS_REG(b)] >= 8)
+ rex |= REX_X;
+ }
+ }
+ } else if (!(flags & EX86_SSE2_OP2)) {
+ if (reg_map[b] >= 8)
+ rex |= REX_B;
+ } else if (freg_map[b] >= 8)
+ rex |= REX_B;
+
+ if ((flags & EX86_VEX_EXT) && (rex & 0x3)) {
+ SLJIT_ASSERT(size == 2);
+ size++;
+ inst_size++;
+ }
+
+ if (a == SLJIT_IMM) {
+ if (flags & EX86_BIN_INS) {
+ if (imma <= 127 && imma >= -128) {
+ inst_size += sizeof(sljit_s8);
+ flags |= EX86_BYTE_ARG;
+ } else
+ inst_size += sizeof(sljit_s32);
+ } else if (flags & EX86_SHIFT_INS) {
+ SLJIT_ASSERT(imma <= (compiler->mode32 ? 0x1f : 0x3f));
+ if (imma != 1) {
+ inst_size += sizeof(sljit_s8);
+ flags |= EX86_BYTE_ARG;
+ }
+ } else if (flags & EX86_BYTE_ARG)
+ inst_size += sizeof(sljit_s8);
+ else if (flags & EX86_HALF_ARG)
+ inst_size += sizeof(sljit_s16);
+ else
+ inst_size += sizeof(sljit_s32);
+ } else {
+ SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
+ /* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */
+ if (!(flags & EX86_SSE2_OP1)) {
+ if (reg_map[a] >= 8)
+ rex |= REX_R;
+ }
+ else if (freg_map[a] >= 8)
+ rex |= REX_R;
+ }
+
+ if (rex)
+ inst_size++;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);
+ PTR_FAIL_IF(!inst);
+
+ /* Encoding prefixes. */
+ INC_SIZE(inst_size);
+ if (flags & EX86_PREF_F2)
+ *inst++ = 0xf2;
+ else if (flags & EX86_PREF_F3)
+ *inst++ = 0xf3;
+ else if (flags & EX86_PREF_66)
+ *inst++ = 0x66;
+
+ /* Rex is always the last prefix. */
+ if (rex)
+ *inst++ = rex;
+
+ buf_ptr = inst + size;
+
+ /* Encode mod/rm byte. */
+ if (!(flags & EX86_SHIFT_INS)) {
+ if ((flags & EX86_BIN_INS) && a == SLJIT_IMM)
+ *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
+
+ if (a == SLJIT_IMM)
+ *buf_ptr = 0;
+ else if (!(flags & EX86_SSE2_OP1))
+ *buf_ptr = U8(reg_lmap[a] << 3);
+ else
+ *buf_ptr = U8(freg_lmap[a] << 3);
+ } else {
+ if (a == SLJIT_IMM) {
+ if (imma == 1)
+ *inst = GROUP_SHIFT_1;
+ else
+ *inst = GROUP_SHIFT_N;
+ } else
+ *inst = GROUP_SHIFT_CL;
+ *buf_ptr = 0;
+ }
+
+ if (!(b & SLJIT_MEM)) {
+ *buf_ptr = U8(*buf_ptr | MOD_REG | (!(flags & EX86_SSE2_OP2) ? reg_lmap[b] : freg_lmap[b]));
+ buf_ptr++;
+ } else if (b & REG_MASK) {
+ reg_lmap_b = reg_lmap[b & REG_MASK];
+
+ if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) {
+ if (immb != 0 || reg_lmap_b == 5) {
+ if (immb <= 127 && immb >= -128)
+ *buf_ptr |= 0x40;
+ else
+ *buf_ptr |= 0x80;
+ }
+
+ if (!(b & OFFS_REG_MASK))
+ *buf_ptr++ |= reg_lmap_b;
+ else {
+ buf_ptr[0] |= 0x04;
+ buf_ptr[1] = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3));
+ buf_ptr += 2;
+ }
+
+ if (immb != 0 || reg_lmap_b == 5) {
+ if (immb <= 127 && immb >= -128)
+ *buf_ptr++ = U8(immb); /* 8 bit displacement. */
+ else {
+ sljit_unaligned_store_s32(buf_ptr, (sljit_s32)immb); /* 32 bit displacement. */
+ buf_ptr += sizeof(sljit_s32);
+ }
+ }
+ } else {
+ if (reg_lmap_b == 5)
+ *buf_ptr |= 0x40;
+
+ buf_ptr[0] |= 0x04;
+ buf_ptr[1] = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6));
+ buf_ptr += 2;
+
+ if (reg_lmap_b == 5)
+ *buf_ptr++ = 0;
+ }
+ } else {
+ buf_ptr[0] |= 0x04;
+ buf_ptr[1] = 0x25;
+ buf_ptr += 2;
+ sljit_unaligned_store_s32(buf_ptr, (sljit_s32)immb); /* 32 bit displacement. */
+ buf_ptr += sizeof(sljit_s32);
+ }
+
+ if (a == SLJIT_IMM) {
+ if (flags & EX86_BYTE_ARG)
+ *buf_ptr = U8(imma);
+ else if (flags & EX86_HALF_ARG)
+ sljit_unaligned_store_s16(buf_ptr, (sljit_s16)imma);
+ else if (!(flags & EX86_SHIFT_INS))
+ sljit_unaligned_store_s32(buf_ptr, (sljit_s32)imma);
+ }
+
+ return inst;
+}
+
+static sljit_s32 emit_vex_instruction(struct sljit_compiler *compiler, sljit_uw op,
+ /* The first and second register operand. */
+ sljit_s32 a, sljit_s32 v,
+ /* The general operand (not immediate). */
+ sljit_s32 b, sljit_sw immb)
+{
+ sljit_u8 *inst;
+ sljit_u8 vex = 0;
+ sljit_u8 vex_m = 0;
+ sljit_uw size;
+
+ SLJIT_ASSERT(((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))
+ & ((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0);
+
+ op |= EX86_REX;
+
+ if (op & VEX_OP_0F38)
+ vex_m = 0x2;
+ else if (op & VEX_OP_0F3A)
+ vex_m = 0x3;
+
+ if ((op & VEX_W) || ((op & VEX_AUTO_W) && !compiler->mode32)) {
+ if (vex_m == 0)
+ vex_m = 0x1;
+
+ vex |= 0x80;
+ }
+
+ if (op & EX86_PREF_66)
+ vex |= 0x1;
+ else if (op & EX86_PREF_F2)
+ vex |= 0x3;
+ else if (op & EX86_PREF_F3)
+ vex |= 0x2;
+
+ op &= ~(EX86_PREF_66 | EX86_PREF_F2 | EX86_PREF_F3);
+
+ if (op & VEX_256)
+ vex |= 0x4;
+
+ vex = U8(vex | ((((op & VEX_SSE2_OPV) ? freg_map[v] : reg_map[v]) ^ 0xf) << 3));
+
+ size = op & ~(sljit_uw)0xff;
+ size |= (vex_m == 0) ? (EX86_VEX_EXT | 2) : 3;
+
+ inst = emit_x86_instruction(compiler, size, a, 0, b, immb);
+ FAIL_IF(!inst);
+
+ SLJIT_ASSERT((inst[-1] & 0xf0) == REX);
+
+ /* If X or B is present in REX prefix. */
+ if (vex_m == 0 && inst[-1] & 0x3)
+ vex_m = 0x1;
+
+ if (vex_m == 0) {
+ vex |= U8(((inst[-1] >> 2) ^ 0x1) << 7);
+
+ inst[-1] = 0xc5;
+ inst[0] = vex;
+ inst[1] = U8(op);
+ return SLJIT_SUCCESS;
+ }
+
+ vex_m |= U8((inst[-1] ^ 0x7) << 5);
+ inst[-1] = 0xc4;
+ inst[0] = vex_m;
+ inst[1] = vex;
+ inst[2] = U8(op);
+ return SLJIT_SUCCESS;
+}
+
+/* --------------------------------------------------------------------- */
+/* Enter / return */
+/* --------------------------------------------------------------------- */
+
+static sljit_u8* detect_far_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr)
+{
+ sljit_uw type = jump->flags >> TYPE_SHIFT;
+
+ int short_addr = ((jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR)) == JUMP_ADDR) && (jump->u.target <= 0xffffffff);
+
+ /* The relative jump below specialized for this case. */
+ SLJIT_ASSERT(reg_map[TMP_REG2] >= 8 && TMP_REG2 != SLJIT_TMP_DEST_REG);
+
+ if (type < SLJIT_JUMP) {
+ /* Invert type. */
+ code_ptr[0] = U8(get_jump_code(type ^ 0x1) - 0x10);
+ code_ptr[1] = short_addr ? (6 + 3) : (10 + 3);
+ code_ptr += 2;
+ }
+
+ code_ptr[0] = short_addr ? REX_B : (REX_W | REX_B);
+ code_ptr[1] = MOV_r_i32 | reg_lmap[TMP_REG2];
+ code_ptr += 2;
+ jump->addr = (sljit_uw)code_ptr;
+
+ if (!(jump->flags & JUMP_ADDR))
+ jump->flags |= PATCH_MD;
+ else if (short_addr)
+ sljit_unaligned_store_s32(code_ptr, (sljit_s32)jump->u.target);
+ else
+ sljit_unaligned_store_sw(code_ptr, (sljit_sw)jump->u.target);
+
+ code_ptr += short_addr ? sizeof(sljit_s32) : sizeof(sljit_sw);
+
+ code_ptr[0] = REX_B;
+ code_ptr[1] = GROUP_FF;
+ code_ptr[2] = U8(MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2]);
+
+ return code_ptr + 3;
+}
+
+static sljit_u8* generate_mov_addr_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset)
+{
+ sljit_uw addr;
+ sljit_sw diff;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_ASSERT(((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f) <= 10);
+ if (jump->flags & JUMP_ADDR)
+ addr = jump->u.target;
+ else
+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + jump->u.label->size;
+
+ if (addr > 0xffffffffl) {
+ diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+
+ if (diff <= HALFWORD_MAX && diff >= HALFWORD_MIN) {
+ SLJIT_ASSERT(((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f) >= 7);
+ code_ptr -= SSIZE_OF(s32) - 1;
+
+ SLJIT_ASSERT((code_ptr[-3 - SSIZE_OF(s32)] & 0xf8) == REX_W);
+ SLJIT_ASSERT((code_ptr[-2 - SSIZE_OF(s32)] & 0xf8) == MOV_r_i32);
+
+ code_ptr[-3 - SSIZE_OF(s32)] = U8(REX_W | ((code_ptr[-3 - SSIZE_OF(s32)] & 0x1) << 2));
+ code_ptr[-1 - SSIZE_OF(s32)] = U8(((code_ptr[-2 - SSIZE_OF(s32)] & 0x7) << 3) | 0x5);
+ code_ptr[-2 - SSIZE_OF(s32)] = LEA_r_m;
+
+ jump->flags |= PATCH_MW;
+ return code_ptr;
+ }
+
+ jump->flags |= PATCH_MD;
+ return code_ptr;
+ }
+
+ code_ptr -= 2 + sizeof(sljit_uw);
+
+ SLJIT_ASSERT((code_ptr[0] & 0xf8) == REX_W);
+ SLJIT_ASSERT((code_ptr[1] & 0xf8) == MOV_r_i32);
+
+ if ((code_ptr[0] & 0x07) != 0) {
+ SLJIT_ASSERT(((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f) >= 6);
+ code_ptr[0] = U8(code_ptr[0] & ~0x08);
+ code_ptr += 2 + sizeof(sljit_s32);
+ } else {
+ SLJIT_ASSERT(((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f) >= 5);
+ code_ptr[0] = code_ptr[1];
+ code_ptr += 1 + sizeof(sljit_s32);
+ }
+
+ return code_ptr;
+}
+
+#ifdef _WIN64
+typedef struct {
+ sljit_sw regs[2];
+} sljit_sse2_reg;
+#endif /* _WIN64 */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_uw size;
+ sljit_s32 word_arg_count = 0;
+ sljit_s32 saved_arg_count = SLJIT_KEPT_SAVEDS_COUNT(options);
+ sljit_s32 saved_regs_size, tmp, i;
+#ifdef _WIN64
+ sljit_s32 fscratches;
+ sljit_s32 fsaveds;
+ sljit_s32 saved_float_regs_size;
+ sljit_s32 saved_float_regs_offset = 0;
+ sljit_s32 float_arg_count = 0;
+#endif /* _WIN64 */
+ sljit_u8 *inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+#ifdef _WIN64
+ saveds = ENTER_GET_REGS(saveds);
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+#endif /* _WIN64 */
+
+ if (options & SLJIT_ENTER_REG_ARG)
+ arg_types = 0;
+
+ /* Emit ENDBR64 at function entry if needed. */
+ FAIL_IF(emit_endbranch(compiler));
+
+ compiler->mode32 = 0;
+
+ /* Including the return address saved by the call instruction. */
+ saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - saved_arg_count, 1);
+
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
+ size = reg_map[i] >= 8 ? 2 : 1;
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+ INC_SIZE(size);
+ if (reg_map[i] >= 8)
+ *inst++ = REX_B;
+ PUSH_REG(reg_lmap[i]);
+ }
+
+ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ size = reg_map[i] >= 8 ? 2 : 1;
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+ INC_SIZE(size);
+ if (reg_map[i] >= 8)
+ *inst++ = REX_B;
+ PUSH_REG(reg_lmap[i]);
+ }
+
+#ifdef _WIN64
+ local_size += SLJIT_LOCALS_OFFSET;
+ saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg);
+
+ if (saved_float_regs_size > 0) {
+ saved_float_regs_offset = ((local_size + 0xf) & ~0xf);
+ local_size = saved_float_regs_offset + saved_float_regs_size;
+ }
+#else /* !_WIN64 */
+ SLJIT_ASSERT(SLJIT_LOCALS_OFFSET == 0);
+#endif /* _WIN64 */
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ while (arg_types > 0) {
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
+ tmp = 0;
+#ifndef _WIN64
+ switch (word_arg_count) {
+ case 0:
+ tmp = SLJIT_R2;
+ break;
+ case 1:
+ tmp = SLJIT_R1;
+ break;
+ case 2:
+ tmp = TMP_REG1;
+ break;
+ default:
+ tmp = SLJIT_R3;
+ break;
+ }
+#else /* !_WIN64 */
+ switch (word_arg_count + float_arg_count) {
+ case 0:
+ tmp = SLJIT_R3;
+ break;
+ case 1:
+ tmp = SLJIT_R1;
+ break;
+ case 2:
+ tmp = SLJIT_R2;
+ break;
+ default:
+ tmp = TMP_REG1;
+ break;
+ }
+#endif /* _WIN64 */
+ if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) {
+ if (tmp != SLJIT_R0 + word_arg_count)
+ EMIT_MOV(compiler, SLJIT_R0 + word_arg_count, 0, tmp, 0);
+ } else {
+ EMIT_MOV(compiler, SLJIT_S0 - saved_arg_count, 0, tmp, 0);
+ saved_arg_count++;
+ }
+ word_arg_count++;
+ } else {
+#ifdef _WIN64
+ SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
+ float_arg_count++;
+ if (float_arg_count != float_arg_count + word_arg_count)
+ FAIL_IF(emit_sse2_load(compiler, (arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32,
+ float_arg_count, float_arg_count + word_arg_count, 0));
+#endif /* _WIN64 */
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ local_size = ((local_size + saved_regs_size + 0xf) & ~0xf) - saved_regs_size;
+ compiler->local_size = local_size;
+
+#ifdef _WIN64
+ if (local_size > 0) {
+ if (local_size <= 4 * 4096) {
+ if (local_size > 4096)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096);
+ if (local_size > 2 * 4096)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 2);
+ if (local_size > 3 * 4096)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3);
+ }
+ else {
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, local_size >> 12);
+
+ EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_MEM1(SLJIT_SP), -4096);
+ BINARY_IMM32(SUB, 4096, SLJIT_SP, 0);
+ BINARY_IMM32(SUB, 1, TMP_REG1, 0);
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+
+ INC_SIZE(2);
+ inst[0] = JNE_i8;
+ inst[1] = (sljit_u8)-21;
+ local_size &= 0xfff;
+ }
+
+ if (local_size > 0)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -local_size);
+ }
+#endif /* _WIN64 */
+
+ if (local_size > 0)
+ BINARY_IMM32(SUB, local_size, SLJIT_SP, 0);
+
+#ifdef _WIN64
+ if (saved_float_regs_size > 0) {
+ compiler->mode32 = 1;
+
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ FAIL_IF(emit_groupf(compiler, MOVAPS_xm_x | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset));
+ saved_float_regs_offset += 16;
+ }
+
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ FAIL_IF(emit_groupf(compiler, MOVAPS_xm_x | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset));
+ saved_float_regs_offset += 16;
+ }
+ }
+#endif /* _WIN64 */
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types,
+ sljit_s32 scratches, sljit_s32 saveds, sljit_s32 local_size)
+{
+ sljit_s32 saved_regs_size;
+#ifdef _WIN64
+ sljit_s32 fscratches;
+ sljit_s32 fsaveds;
+ sljit_s32 saved_float_regs_size;
+#endif /* _WIN64 */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, local_size);
+
+ scratches = ENTER_GET_REGS(scratches);
+
+#ifdef _WIN64
+ saveds = ENTER_GET_REGS(saveds);
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+
+ local_size += SLJIT_LOCALS_OFFSET;
+ saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg);
+
+ if (saved_float_regs_size > 0)
+ local_size = ((local_size + 0xf) & ~0xf) + saved_float_regs_size;
+#else /* !_WIN64 */
+ SLJIT_ASSERT(SLJIT_LOCALS_OFFSET == 0);
+#endif /* _WIN64 */
+
+ /* Including the return address saved by the call instruction. */
+ saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds - SLJIT_KEPT_SAVEDS_COUNT(options), 1);
+ compiler->local_size = ((local_size + saved_regs_size + 0xf) & ~0xf) - saved_regs_size;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 is_return_to)
+{
+ sljit_uw size;
+ sljit_s32 local_size, i, tmp;
+ sljit_u8 *inst;
+#ifdef _WIN64
+ sljit_s32 saved_float_regs_offset;
+ sljit_s32 fscratches = compiler->fscratches;
+ sljit_s32 fsaveds = compiler->fsaveds;
+#endif /* _WIN64 */
+
+#ifdef _WIN64
+ saved_float_regs_offset = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg);
+
+ if (saved_float_regs_offset > 0) {
+ compiler->mode32 = 1;
+ saved_float_regs_offset = (compiler->local_size - saved_float_regs_offset) & ~0xf;
+
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ FAIL_IF(emit_groupf(compiler, MOVAPS_x_xm | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset));
+ saved_float_regs_offset += 16;
+ }
+
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ FAIL_IF(emit_groupf(compiler, MOVAPS_x_xm | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset));
+ saved_float_regs_offset += 16;
+ }
+
+ compiler->mode32 = 0;
+ }
+#endif /* _WIN64 */
+
+ local_size = compiler->local_size;
+
+ if (is_return_to && compiler->scratches < SLJIT_FIRST_SAVED_REG && (compiler->saveds == SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ local_size += SSIZE_OF(sw);
+ is_return_to = 0;
+ }
+
+ if (local_size > 0)
+ BINARY_IMM32(ADD, local_size, SLJIT_SP, 0);
+
+ tmp = compiler->scratches;
+ for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
+ size = reg_map[i] >= 8 ? 2 : 1;
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+ INC_SIZE(size);
+ if (reg_map[i] >= 8)
+ *inst++ = REX_B;
+ POP_REG(reg_lmap[i]);
+ }
+
+ tmp = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options);
+ for (i = SLJIT_S0 + 1 - compiler->saveds; i <= tmp; i++) {
+ size = reg_map[i] >= 8 ? 2 : 1;
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+ INC_SIZE(size);
+ if (reg_map[i] >= 8)
+ *inst++ = REX_B;
+ POP_REG(reg_lmap[i]);
+ }
+
+ if (is_return_to)
+ BINARY_IMM32(ADD, sizeof(sljit_sw), SLJIT_SP, 0);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ compiler->mode32 = 0;
+
+ FAIL_IF(emit_stack_frame_release(compiler, 0));
+ return emit_byte(compiler, RET_near);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_to(compiler, src, srcw));
+
+ compiler->mode32 = 0;
+
+ if ((src & SLJIT_MEM) || (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options)))) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);
+ src = TMP_REG2;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 1));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
+}
+
+/* --------------------------------------------------------------------- */
+/* Call / return instructions */
+/* --------------------------------------------------------------------- */
+
+#ifndef _WIN64
+
+static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr)
+{
+ sljit_s32 src = src_ptr ? (*src_ptr) : 0;
+ sljit_s32 word_arg_count = 0;
+
+ SLJIT_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R3] == 1 && reg_map[TMP_REG1] == 2);
+ SLJIT_ASSERT(!(src & SLJIT_MEM));
+
+ /* Remove return value. */
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ while (arg_types) {
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64)
+ word_arg_count++;
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ if (word_arg_count == 0)
+ return SLJIT_SUCCESS;
+
+ if (word_arg_count >= 3 || src == SLJIT_R2) {
+ if (src == SLJIT_R2)
+ *src_ptr = TMP_REG1;
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R2, 0);
+ }
+
+ return emit_mov(compiler, SLJIT_R2, 0, SLJIT_R0, 0);
+}
+
+#else
+
+static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr)
+{
+ sljit_s32 src = src_ptr ? (*src_ptr) : 0;
+ sljit_s32 arg_count = 0;
+ sljit_s32 word_arg_count = 0;
+ sljit_s32 float_arg_count = 0;
+ sljit_s32 types = 0;
+ sljit_s32 data_trandfer = 0;
+ static sljit_u8 word_arg_regs[5] = { 0, SLJIT_R3, SLJIT_R1, SLJIT_R2, TMP_REG1 };
+
+ SLJIT_ASSERT(reg_map[SLJIT_R3] == 1 && reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R2] == 8 && reg_map[TMP_REG1] == 9);
+ SLJIT_ASSERT(!(src & SLJIT_MEM));
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ while (arg_types) {
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
+
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ case SLJIT_ARG_TYPE_F32:
+ arg_count++;
+ float_arg_count++;
+
+ if (arg_count != float_arg_count)
+ data_trandfer = 1;
+ break;
+ default:
+ arg_count++;
+ word_arg_count++;
+
+ if (arg_count != word_arg_count || arg_count != word_arg_regs[arg_count]) {
+ data_trandfer = 1;
+
+ if (src == word_arg_regs[arg_count]) {
+ EMIT_MOV(compiler, TMP_REG2, 0, src, 0);
+ *src_ptr = TMP_REG2;
+ }
+ }
+ break;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ if (!data_trandfer)
+ return SLJIT_SUCCESS;
+
+ while (types) {
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (arg_count != float_arg_count)
+ FAIL_IF(emit_sse2_load(compiler, 0, arg_count, float_arg_count, 0));
+ arg_count--;
+ float_arg_count--;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (arg_count != float_arg_count)
+ FAIL_IF(emit_sse2_load(compiler, 1, arg_count, float_arg_count, 0));
+ arg_count--;
+ float_arg_count--;
+ break;
+ default:
+ if (arg_count != word_arg_count || arg_count != word_arg_regs[arg_count])
+ EMIT_MOV(compiler, word_arg_regs[arg_count], 0, word_arg_count, 0);
+ arg_count--;
+ word_arg_count--;
+ break;
+ }
+
+ types >>= SLJIT_ARG_SHIFT;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+#endif
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types)
+{
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
+
+ compiler->mode32 = 0;
+
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)
+ PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
+
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0));
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_jump(compiler, type);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 arg_types,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
+
+ compiler->mode32 = 0;
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);
+ src = TMP_REG2;
+ }
+
+ if (type & SLJIT_CALL_RETURN) {
+ if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
+ EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);
+ src = TMP_REG2;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler, 0));
+ }
+
+ if ((type & 0xff) != SLJIT_CALL_REG_ARG)
+ FAIL_IF(call_with_args(compiler, arg_types, &src));
+
+ if (type & SLJIT_CALL_RETURN)
+ type = SLJIT_JUMP;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_ijump(compiler, type, src, srcw);
+}
+
+static sljit_s32 emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_u8 *inst;
+
+ if (FAST_IS_REG(dst)) {
+ if (reg_map[dst] < 8)
+ return emit_byte(compiler, U8(POP_r + reg_lmap[dst]));
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(2);
+ *inst++ = REX_B;
+ POP_REG(reg_lmap[dst]);
+ return SLJIT_SUCCESS;
+ }
+
+ /* REX_W is not necessary (src is not immediate). */
+ compiler->mode32 = 1;
+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = POP_rm;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8 *inst;
+
+ if (FAST_IS_REG(src)) {
+ if (reg_map[src] < 8) {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);
+ FAIL_IF(!inst);
+
+ INC_SIZE(1 + 1);
+ PUSH_REG(reg_lmap[src]);
+ }
+ else {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + 1);
+ FAIL_IF(!inst);
+
+ INC_SIZE(2 + 1);
+ *inst++ = REX_B;
+ PUSH_REG(reg_lmap[src]);
+ }
+ }
+ else {
+ /* REX_W is not necessary (src is not immediate). */
+ compiler->mode32 = 1;
+ inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
+ FAIL_IF(!inst);
+ inst[0] = GROUP_FF;
+ inst[1] |= PUSH_rm;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
+ INC_SIZE(1);
+ }
+
+ RET();
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 sljit_emit_get_return_address(struct sljit_compiler *compiler,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 saved_regs_size;
+
+ compiler->mode32 = 0;
+ saved_regs_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 0);
+ return emit_mov(compiler, dst, dstw, SLJIT_MEM1(SLJIT_SP), compiler->local_size + saved_regs_size);
+}
+
+/* --------------------------------------------------------------------- */
+/* Other operations */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_reg)
+{
+ sljit_u8* inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+ compiler->mode32 = type & SLJIT_32;
+
+ if (type & SLJIT_COMPARE_SELECT) {
+ if (!FAST_IS_REG(src1)) {
+ EMIT_MOV(compiler, TMP_REG2, 0, src1, src1w);
+ src1 = TMP_REG2;
+ src1w = 0;
+ }
+
+ inst = emit_x86_instruction(compiler, 1, src1, 0, src2_reg, 0);
+ FAIL_IF(!inst);
+ *inst = CMP_r_rm;
+ }
+
+ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);
+
+ if (dst_reg != src2_reg) {
+ if (dst_reg == src1) {
+ src1 = src2_reg;
+ src1w = 0;
+ type ^= 0x1;
+ } else if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
+ EMIT_MOV(compiler, dst_reg, 0, src1, src1w);
+ src1 = src2_reg;
+ src1w = 0;
+ type ^= 0x1;
+ } else
+ EMIT_MOV(compiler, dst_reg, 0, src2_reg, 0);
+ }
+
+ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV)) {
+ if (SLJIT_UNLIKELY(src1 == SLJIT_IMM)) {
+ EMIT_MOV(compiler, TMP_REG2, 0, src1, src1w);
+ src1 = TMP_REG2;
+ src1w = 0;
+ }
+
+ return emit_groupf(compiler, U8(get_jump_code((sljit_uw)type) - 0x40), dst_reg, src1, src1w);
+ }
+
+ return emit_cmov_generic(compiler, type, dst_reg, src1, src1w);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ sljit_u8* inst;
+ sljit_s32 i, next, reg_idx;
+ sljit_u8 regs[2];
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
+
+ if (!(reg & REG_PAIR_MASK))
+ return sljit_emit_mem_unaligned(compiler, type, reg, mem, memw);
+
+ ADJUST_LOCAL_OFFSET(mem, memw);
+
+ compiler->mode32 = 0;
+
+ if ((mem & REG_MASK) == 0) {
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, memw);
+
+ mem = SLJIT_MEM1(TMP_REG1);
+ memw = 0;
+ } else if (!(mem & OFFS_REG_MASK) && ((memw < HALFWORD_MIN) || (memw > HALFWORD_MAX - SSIZE_OF(sw)))) {
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, memw);
+
+ mem = SLJIT_MEM2(mem & REG_MASK, TMP_REG1);
+ memw = 0;
+ }
+
+ regs[0] = U8(REG_PAIR_FIRST(reg));
+ regs[1] = U8(REG_PAIR_SECOND(reg));
+
+ next = SSIZE_OF(sw);
+
+ if (!(type & SLJIT_MEM_STORE) && (regs[0] == (mem & REG_MASK) || regs[0] == OFFS_REG(mem))) {
+ if (regs[1] == (mem & REG_MASK) || regs[1] == OFFS_REG(mem)) {
+ /* Base and offset cannot be TMP_REG1. */
+ EMIT_MOV(compiler, TMP_REG1, 0, OFFS_REG(mem), 0);
+
+ if (regs[1] == OFFS_REG(mem))
+ next = -SSIZE_OF(sw);
+
+ mem = (mem & ~OFFS_REG_MASK) | TO_OFFS_REG(TMP_REG1);
+ } else {
+ next = -SSIZE_OF(sw);
+
+ if (!(mem & OFFS_REG_MASK))
+ memw += SSIZE_OF(sw);
+ }
+ }
+
+ for (i = 0; i < 2; i++) {
+ reg_idx = next > 0 ? i : (i ^ 0x1);
+ reg = regs[reg_idx];
+
+ if ((mem & OFFS_REG_MASK) && (reg_idx == 1)) {
+ inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(1 + 5));
+ FAIL_IF(!inst);
+
+ INC_SIZE(5);
+
+ inst[0] = U8(REX_W | ((reg_map[reg] >= 8) ? REX_R : 0) | ((reg_map[mem & REG_MASK] >= 8) ? REX_B : 0) | ((reg_map[OFFS_REG(mem)] >= 8) ? REX_X : 0));
+ inst[1] = (type & SLJIT_MEM_STORE) ? MOV_rm_r : MOV_r_rm;
+ inst[2] = 0x44 | U8(reg_lmap[reg] << 3);
+ inst[3] = U8(memw << 6) | U8(reg_lmap[OFFS_REG(mem)] << 3) | reg_lmap[mem & REG_MASK];
+ inst[4] = sizeof(sljit_sw);
+ } else if (type & SLJIT_MEM_STORE) {
+ EMIT_MOV(compiler, mem, memw, reg, 0);
+ } else {
+ EMIT_MOV(compiler, reg, 0, mem, memw);
+ }
+
+ if (!(mem & OFFS_REG_MASK))
+ memw += next;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8* inst;
+ sljit_s32 dst_r;
+
+ compiler->mode32 = 0;
+
+ if (src == SLJIT_IMM) {
+ if (FAST_IS_REG(dst)) {
+ if (!sign || ((sljit_u32)srcw <= 0x7fffffff))
+ return emit_do_imm32(compiler, reg_map[dst] <= 7 ? 0 : REX_B, U8(MOV_r_i32 | reg_lmap[dst]), srcw);
+
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_i32;
+ return SLJIT_SUCCESS;
+ }
+ compiler->mode32 = 1;
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_i32;
+ compiler->mode32 = 0;
+ return SLJIT_SUCCESS;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if ((dst & SLJIT_MEM) && FAST_IS_REG(src))
+ dst_r = src;
+ else {
+ if (sign) {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst = MOVSXD_r_rm;
+ } else {
+ compiler->mode32 = 1;
+ EMIT_MOV(compiler, dst_r, 0, src, srcw);
+ compiler->mode32 = 0;
+ }
+ }
+
+ if (dst & SLJIT_MEM) {
+ compiler->mode32 = 1;
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_r;
+ compiler->mode32 = 0;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG;
+ sljit_u8 *inst, *jump_inst1, *jump_inst2;
+ sljit_uw size1, size2;
+
+ compiler->mode32 = 0;
+
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {
+ if (src != SLJIT_IMM) {
+ compiler->mode32 = 1;
+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
+ compiler->mode32 = 0;
+ } else
+ FAIL_IF(emit_do_imm32(compiler, reg_map[TMP_REG1] <= 7 ? 0 : REX_B, U8(MOV_r_i32 | reg_lmap[TMP_REG1]), srcw));
+
+ FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, TMP_REG1, 0));
+
+ compiler->mode32 = 1;
+
+ if (dst_r == TMP_FREG)
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
+ return SLJIT_SUCCESS;
+ }
+
+ if (!FAST_IS_REG(src)) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
+ src = TMP_REG1;
+ }
+
+ BINARY_IMM32(CMP, 0, src, 0);
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(2);
+ inst[0] = JL_i8;
+ jump_inst1 = inst;
+
+ size1 = compiler->size;
+
+ compiler->mode32 = 0;
+ FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, src, 0));
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(2);
+ inst[0] = JMP_i8;
+ jump_inst2 = inst;
+
+ size2 = compiler->size;
+
+ jump_inst1[1] = U8(size2 - size1);
+
+ if (src != TMP_REG1)
+ EMIT_MOV(compiler, TMP_REG1, 0, src, 0);
+
+ EMIT_MOV(compiler, TMP_REG2, 0, src, 0);
+
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0);
+ FAIL_IF(!inst);
+ inst[1] |= SHR;
+
+ compiler->mode32 = 1;
+ BINARY_IMM32(AND, 1, TMP_REG2, 0);
+
+ compiler->mode32 = 0;
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG2, 0);
+ FAIL_IF(!inst);
+ inst[0] = OR_r_rm;
+
+ FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, TMP_REG1, 0));
+ compiler->mode32 = 1;
+ FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, dst_r, 0));
+
+ jump_inst2[1] = U8(compiler->size - size2);
+
+ if (dst_r == TMP_FREG)
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 sljit_emit_fset(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_u8 rex, sljit_s32 is_zero)
+{
+ sljit_u8 *inst;
+ sljit_u32 size;
+
+ if (is_zero) {
+ rex = freg_map[freg] >= 8 ? (REX_R | REX_B) : 0;
+ } else {
+ if (freg_map[freg] >= 8)
+ rex |= REX_R;
+ if (reg_map[TMP_REG1] >= 8)
+ rex |= REX_B;
+ }
+
+ size = (rex != 0) ? 5 : 4;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+ INC_SIZE(size);
+
+ *inst++ = GROUP_66;
+ if (rex != 0)
+ *inst++ = rex;
+ inst[0] = GROUP_0F;
+
+ if (is_zero) {
+ inst[1] = PXOR_x_xm;
+ inst[2] = U8(freg_lmap[freg] | (freg_lmap[freg] << 3) | MOD_REG);
+ } else {
+ inst[1] = MOVD_x_rm;
+ inst[2] = U8(reg_lmap[TMP_REG1] | (freg_lmap[freg] << 3) | MOD_REG);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f32 value)
+{
+ union {
+ sljit_s32 imm;
+ sljit_f32 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset32(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm != 0) {
+ compiler->mode32 = 1;
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm);
+ }
+
+ return sljit_emit_fset(compiler, freg, 0, u.imm == 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
+ sljit_s32 freg, sljit_f64 value)
+{
+ union {
+ sljit_sw imm;
+ sljit_f64 value;
+ } u;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fset64(compiler, freg, value));
+
+ u.value = value;
+
+ if (u.imm != 0) {
+ compiler->mode32 = 0;
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm);
+ }
+
+ return sljit_emit_fset(compiler, freg, REX_W, u.imm == 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 freg, sljit_s32 reg)
+{
+ sljit_u8 *inst;
+ sljit_u32 size;
+ sljit_u8 rex = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
+
+ if (!(op & SLJIT_32))
+ rex = REX_W;
+
+ if (freg_map[freg] >= 8)
+ rex |= REX_R;
+
+ if (reg_map[reg] >= 8)
+ rex |= REX_B;
+
+ size = (rex != 0) ? 5 : 4;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+ INC_SIZE(size);
+
+ *inst++ = GROUP_66;
+ if (rex != 0)
+ *inst++ = rex;
+ inst[0] = GROUP_0F;
+ inst[1] = GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x;
+ inst[2] = U8(reg_lmap[reg] | (freg_lmap[freg] << 3) | MOD_REG);
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler)
+{
+ sljit_s32 tmp, size;
+
+ /* Don't adjust shadow stack if it isn't enabled. */
+ if (!cpu_has_shadow_stack())
+ return SLJIT_SUCCESS;
+
+ size = compiler->local_size;
+ tmp = compiler->scratches;
+ if (tmp >= SLJIT_FIRST_SAVED_REG)
+ size += (tmp - SLJIT_FIRST_SAVED_REG + 1) * SSIZE_OF(sw);
+ tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
+ if (SLJIT_S0 >= tmp)
+ size += (SLJIT_S0 - tmp + 1) * SSIZE_OF(sw);
+
+ return adjust_shadow_stack(compiler, SLJIT_MEM1(SLJIT_SP), size);
+}
diff --git a/deps/sljit/sljit_src/sljitNativeX86_common.c b/deps/sljit/sljit_src/sljitNativeX86_common.c
new file mode 100644
index 0000000..840443f
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitNativeX86_common.c
@@ -0,0 +1,5445 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
+{
+ return "x86" SLJIT_CPUINFO;
+}
+
+/*
+ 32b register indexes:
+ 0 - EAX
+ 1 - ECX
+ 2 - EDX
+ 3 - EBX
+ 4 - ESP
+ 5 - EBP
+ 6 - ESI
+ 7 - EDI
+*/
+
+/*
+ 64b register indexes:
+ 0 - RAX
+ 1 - RCX
+ 2 - RDX
+ 3 - RBX
+ 4 - RSP
+ 5 - RBP
+ 6 - RSI
+ 7 - RDI
+ 8 - R8 - From now on REX prefix is required
+ 9 - R9
+ 10 - R10
+ 11 - R11
+ 12 - R12
+ 13 - R13
+ 14 - R14
+ 15 - R15
+*/
+
+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
+#define TMP_FREG (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = {
+ 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 5, 7, 6, 4, 3
+};
+
+static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 0
+};
+
+#define CHECK_EXTRA_REGS(p, w, do) \
+ if (p >= SLJIT_R3 && p <= SLJIT_S3) { \
+ w = (2 * SSIZE_OF(sw)) + ((p) - SLJIT_R3) * SSIZE_OF(sw); \
+ p = SLJIT_MEM1(SLJIT_SP); \
+ do; \
+ }
+
+#else /* SLJIT_CONFIG_X86_32 */
+
+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
+
+/* Note: r12 & 0x7 == 0b100, which decoded as SIB byte present
+ Note: avoid to use r12 and r13 for memory addressing
+ therefore r12 is better to be a higher saved register. */
+#ifndef _WIN64
+/* Args: rdi(=7), rsi(=6), rdx(=2), rcx(=1), r8, r9. Scratches: rax(=0), r10, r11 */
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = {
+ 0, 0, 6, 7, 1, 8, 11, 10, 12, 5, 13, 14, 15, 3, 4, 2, 9
+};
+/* low-map. reg_map & 0x7. */
+static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {
+ 0, 0, 6, 7, 1, 0, 3, 2, 4, 5, 5, 6, 7, 3, 4, 2, 1
+};
+#else
+/* Args: rcx(=1), rdx(=2), r8, r9. Scratches: rax(=0), r10, r11 */
+static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = {
+ 0, 0, 2, 8, 1, 11, 12, 5, 13, 14, 15, 7, 6, 3, 4, 9, 10
+};
+/* low-map. reg_map & 0x7. */
+static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {
+ 0, 0, 2, 0, 1, 3, 4, 5, 5, 6, 7, 7, 6, 3, 4, 1, 2
+};
+#endif
+
+/* Args: xmm0-xmm3 */
+static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2] = {
+ 0, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 4
+};
+/* low-map. freg_map & 0x7. */
+static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2] = {
+ 0, 0, 1, 2, 3, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 4
+};
+
+#define REX_W 0x48
+#define REX_R 0x44
+#define REX_X 0x42
+#define REX_B 0x41
+#define REX 0x40
+
+#ifndef _WIN64
+#define HALFWORD_MAX 0x7fffffffl
+#define HALFWORD_MIN -0x80000000l
+#else
+#define HALFWORD_MAX 0x7fffffffll
+#define HALFWORD_MIN -0x80000000ll
+#endif
+
+#define IS_HALFWORD(x) ((x) <= HALFWORD_MAX && (x) >= HALFWORD_MIN)
+#define NOT_HALFWORD(x) ((x) > HALFWORD_MAX || (x) < HALFWORD_MIN)
+
+#define CHECK_EXTRA_REGS(p, w, do)
+
+#endif /* SLJIT_CONFIG_X86_32 */
+
+#define U8(v) ((sljit_u8)(v))
+
+/* Size flags for emit_x86_instruction: */
+#define EX86_BIN_INS ((sljit_uw)0x000010)
+#define EX86_SHIFT_INS ((sljit_uw)0x000020)
+#define EX86_BYTE_ARG ((sljit_uw)0x000040)
+#define EX86_HALF_ARG ((sljit_uw)0x000080)
+/* Size flags for both emit_x86_instruction and emit_vex_instruction: */
+#define EX86_REX ((sljit_uw)0x000100)
+#define EX86_NO_REXW ((sljit_uw)0x000200)
+#define EX86_PREF_66 ((sljit_uw)0x000400)
+#define EX86_PREF_F2 ((sljit_uw)0x000800)
+#define EX86_PREF_F3 ((sljit_uw)0x001000)
+#define EX86_SSE2_OP1 ((sljit_uw)0x002000)
+#define EX86_SSE2_OP2 ((sljit_uw)0x004000)
+#define EX86_SSE2 (EX86_SSE2_OP1 | EX86_SSE2_OP2)
+#define EX86_VEX_EXT ((sljit_uw)0x008000)
+/* Op flags for emit_vex_instruction: */
+#define VEX_OP_0F38 ((sljit_uw)0x010000)
+#define VEX_OP_0F3A ((sljit_uw)0x020000)
+#define VEX_SSE2_OPV ((sljit_uw)0x040000)
+#define VEX_AUTO_W ((sljit_uw)0x080000)
+#define VEX_W ((sljit_uw)0x100000)
+#define VEX_256 ((sljit_uw)0x200000)
+
+#define EX86_SELECT_66(op) (((op) & SLJIT_32) ? 0 : EX86_PREF_66)
+#define EX86_SELECT_F2_F3(op) (((op) & SLJIT_32) ? EX86_PREF_F3 : EX86_PREF_F2)
+
+/* --------------------------------------------------------------------- */
+/* Instruction forms */
+/* --------------------------------------------------------------------- */
+
+#define ADD (/* BINARY */ 0 << 3)
+#define ADD_EAX_i32 0x05
+#define ADD_r_rm 0x03
+#define ADD_rm_r 0x01
+#define ADDSD_x_xm 0x58
+#define ADC (/* BINARY */ 2 << 3)
+#define ADC_EAX_i32 0x15
+#define ADC_r_rm 0x13
+#define ADC_rm_r 0x11
+#define AND (/* BINARY */ 4 << 3)
+#define AND_EAX_i32 0x25
+#define AND_r_rm 0x23
+#define AND_rm_r 0x21
+#define ANDPD_x_xm 0x54
+#define BSR_r_rm (/* GROUP_0F */ 0xbd)
+#define BSF_r_rm (/* GROUP_0F */ 0xbc)
+#define BSWAP_r (/* GROUP_0F */ 0xc8)
+#define CALL_i32 0xe8
+#define CALL_rm (/* GROUP_FF */ 2 << 3)
+#define CDQ 0x99
+#define CMOVE_r_rm (/* GROUP_0F */ 0x44)
+#define CMP (/* BINARY */ 7 << 3)
+#define CMP_EAX_i32 0x3d
+#define CMP_r_rm 0x3b
+#define CMP_rm_r 0x39
+#define CMPS_x_xm 0xc2
+#define CMPXCHG_rm_r 0xb1
+#define CMPXCHG_rm8_r 0xb0
+#define CVTPD2PS_x_xm 0x5a
+#define CVTPS2PD_x_xm 0x5a
+#define CVTSI2SD_x_rm 0x2a
+#define CVTTSD2SI_r_xm 0x2c
+#define DIV (/* GROUP_F7 */ 6 << 3)
+#define DIVSD_x_xm 0x5e
+#define EXTRACTPS_x_xm 0x17
+#define FLDS 0xd9
+#define FLDL 0xdd
+#define FSTPS 0xd9
+#define FSTPD 0xdd
+#define INSERTPS_x_xm 0x21
+#define INT3 0xcc
+#define IDIV (/* GROUP_F7 */ 7 << 3)
+#define IMUL (/* GROUP_F7 */ 5 << 3)
+#define IMUL_r_rm (/* GROUP_0F */ 0xaf)
+#define IMUL_r_rm_i8 0x6b
+#define IMUL_r_rm_i32 0x69
+#define JL_i8 0x7c
+#define JE_i8 0x74
+#define JNC_i8 0x73
+#define JNE_i8 0x75
+#define JMP_i8 0xeb
+#define JMP_i32 0xe9
+#define JMP_rm (/* GROUP_FF */ 4 << 3)
+#define LEA_r_m 0x8d
+#define LOOP_i8 0xe2
+#define LZCNT_r_rm (/* GROUP_F3 */ /* GROUP_0F */ 0xbd)
+#define MOV_r_rm 0x8b
+#define MOV_r_i32 0xb8
+#define MOV_rm_r 0x89
+#define MOV_rm_i32 0xc7
+#define MOV_rm8_i8 0xc6
+#define MOV_rm8_r8 0x88
+#define MOVAPS_x_xm 0x28
+#define MOVAPS_xm_x 0x29
+#define MOVD_x_rm 0x6e
+#define MOVD_rm_x 0x7e
+#define MOVDDUP_x_xm 0x12
+#define MOVDQA_x_xm 0x6f
+#define MOVDQA_xm_x 0x7f
+#define MOVDQU_x_xm 0x6f
+#define MOVHLPS_x_x 0x12
+#define MOVHPD_m_x 0x17
+#define MOVHPD_x_m 0x16
+#define MOVLHPS_x_x 0x16
+#define MOVLPD_m_x 0x13
+#define MOVLPD_x_m 0x12
+#define MOVMSKPS_r_x (/* GROUP_0F */ 0x50)
+#define MOVQ_x_xm (/* GROUP_0F */ 0x7e)
+#define MOVSD_x_xm 0x10
+#define MOVSD_xm_x 0x11
+#define MOVSHDUP_x_xm 0x16
+#define MOVSXD_r_rm 0x63
+#define MOVSX_r_rm8 (/* GROUP_0F */ 0xbe)
+#define MOVSX_r_rm16 (/* GROUP_0F */ 0xbf)
+#define MOVUPS_x_xm 0x10
+#define MOVZX_r_rm8 (/* GROUP_0F */ 0xb6)
+#define MOVZX_r_rm16 (/* GROUP_0F */ 0xb7)
+#define MUL (/* GROUP_F7 */ 4 << 3)
+#define MULSD_x_xm 0x59
+#define NEG_rm (/* GROUP_F7 */ 3 << 3)
+#define NOP 0x90
+#define NOT_rm (/* GROUP_F7 */ 2 << 3)
+#define OR (/* BINARY */ 1 << 3)
+#define OR_r_rm 0x0b
+#define OR_EAX_i32 0x0d
+#define OR_rm_r 0x09
+#define OR_rm8_r8 0x08
+#define ORPD_x_xm 0x56
+#define PACKSSWB_x_xm (/* GROUP_0F */ 0x63)
+#define PAND_x_xm 0xdb
+#define PCMPEQD_x_xm 0x76
+#define PINSRB_x_rm_i8 0x20
+#define PINSRW_x_rm_i8 0xc4
+#define PINSRD_x_rm_i8 0x22
+#define PEXTRB_rm_x_i8 0x14
+#define PEXTRW_rm_x_i8 0x15
+#define PEXTRD_rm_x_i8 0x16
+#define PMOVMSKB_r_x (/* GROUP_0F */ 0xd7)
+#define PMOVSXBD_x_xm 0x21
+#define PMOVSXBQ_x_xm 0x22
+#define PMOVSXBW_x_xm 0x20
+#define PMOVSXDQ_x_xm 0x25
+#define PMOVSXWD_x_xm 0x23
+#define PMOVSXWQ_x_xm 0x24
+#define PMOVZXBD_x_xm 0x31
+#define PMOVZXBQ_x_xm 0x32
+#define PMOVZXBW_x_xm 0x30
+#define PMOVZXDQ_x_xm 0x35
+#define PMOVZXWD_x_xm 0x33
+#define PMOVZXWQ_x_xm 0x34
+#define POP_r 0x58
+#define POP_rm 0x8f
+#define POPF 0x9d
+#define POR_x_xm 0xeb
+#define PREFETCH 0x18
+#define PSHUFB_x_xm 0x00
+#define PSHUFD_x_xm 0x70
+#define PSHUFLW_x_xm 0x70
+#define PSRLDQ_x 0x73
+#define PSLLD_x_i8 0x72
+#define PSLLQ_x_i8 0x73
+#define PUSH_i32 0x68
+#define PUSH_r 0x50
+#define PUSH_rm (/* GROUP_FF */ 6 << 3)
+#define PUSHF 0x9c
+#define PXOR_x_xm 0xef
+#define ROL (/* SHIFT */ 0 << 3)
+#define ROR (/* SHIFT */ 1 << 3)
+#define RET_near 0xc3
+#define RET_i16 0xc2
+#define SBB (/* BINARY */ 3 << 3)
+#define SBB_EAX_i32 0x1d
+#define SBB_r_rm 0x1b
+#define SBB_rm_r 0x19
+#define SAR (/* SHIFT */ 7 << 3)
+#define SHL (/* SHIFT */ 4 << 3)
+#define SHLD (/* GROUP_0F */ 0xa5)
+#define SHRD (/* GROUP_0F */ 0xad)
+#define SHR (/* SHIFT */ 5 << 3)
+#define SHUFPS_x_xm 0xc6
+#define SUB (/* BINARY */ 5 << 3)
+#define SUB_EAX_i32 0x2d
+#define SUB_r_rm 0x2b
+#define SUB_rm_r 0x29
+#define SUBSD_x_xm 0x5c
+#define TEST_EAX_i32 0xa9
+#define TEST_rm_r 0x85
+#define TZCNT_r_rm (/* GROUP_F3 */ /* GROUP_0F */ 0xbc)
+#define UCOMISD_x_xm 0x2e
+#define UNPCKLPD_x_xm 0x14
+#define UNPCKLPS_x_xm 0x14
+#define VBROADCASTSD_x_xm 0x19
+#define VBROADCASTSS_x_xm 0x18
+#define VEXTRACTF128_x_ym 0x19
+#define VEXTRACTI128_x_ym 0x39
+#define VINSERTF128_y_y_xm 0x18
+#define VINSERTI128_y_y_xm 0x38
+#define VPBROADCASTB_x_xm 0x78
+#define VPBROADCASTD_x_xm 0x58
+#define VPBROADCASTQ_x_xm 0x59
+#define VPBROADCASTW_x_xm 0x79
+#define VPERMPD_y_ym 0x01
+#define VPERMQ_y_ym 0x00
+#define XCHG_EAX_r 0x90
+#define XCHG_r_rm 0x87
+#define XOR (/* BINARY */ 6 << 3)
+#define XOR_EAX_i32 0x35
+#define XOR_r_rm 0x33
+#define XOR_rm_r 0x31
+#define XORPD_x_xm 0x57
+
+#define GROUP_0F 0x0f
+#define GROUP_66 0x66
+#define GROUP_F3 0xf3
+#define GROUP_F7 0xf7
+#define GROUP_FF 0xff
+#define GROUP_BINARY_81 0x81
+#define GROUP_BINARY_83 0x83
+#define GROUP_SHIFT_1 0xd1
+#define GROUP_SHIFT_N 0xc1
+#define GROUP_SHIFT_CL 0xd3
+#define GROUP_LOCK 0xf0
+
+#define MOD_REG 0xc0
+#define MOD_DISP8 0x40
+
+#define INC_SIZE(s) (*inst++ = U8(s), compiler->size += (s))
+
+#define PUSH_REG(r) (*inst++ = U8(PUSH_r + (r)))
+#define POP_REG(r) (*inst++ = U8(POP_r + (r)))
+#define RET() (*inst++ = RET_near)
+#define RET_I16(n) (*inst++ = RET_i16, *inst++ = U8(n), *inst++ = 0)
+
+#define SLJIT_INST_LABEL 255
+#define SLJIT_INST_JUMP 254
+#define SLJIT_INST_MOV_ADDR 253
+#define SLJIT_INST_CONST 252
+
+/* Multithreading does not affect these static variables, since they store
+ built-in CPU features. Therefore they can be overwritten by different threads
+ if they detect the CPU features in the same time. */
+#define CPU_FEATURE_DETECTED 0x001
+#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
+#define CPU_FEATURE_SSE2 0x002
+#endif
+#define CPU_FEATURE_SSE41 0x004
+#define CPU_FEATURE_LZCNT 0x008
+#define CPU_FEATURE_TZCNT 0x010
+#define CPU_FEATURE_CMOV 0x020
+#define CPU_FEATURE_AVX 0x040
+#define CPU_FEATURE_AVX2 0x080
+#define CPU_FEATURE_OSXSAVE 0x100
+
+static sljit_u32 cpu_feature_list = 0;
+
+#ifdef _WIN32_WCE
+#include
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+#include
+#elif defined(__INTEL_COMPILER)
+#include
+#endif
+
+#if (defined(_MSC_VER) && _MSC_VER >= 1400) || defined(__INTEL_COMPILER) \
+ || (defined(__INTEL_LLVM_COMPILER) && defined(__XSAVE__))
+#include
+#endif
+
+/******************************************************/
+/* Unaligned-store functions */
+/******************************************************/
+
+static SLJIT_INLINE void sljit_unaligned_store_s16(void *addr, sljit_s16 value)
+{
+ SLJIT_MEMCPY(addr, &value, sizeof(value));
+}
+
+static SLJIT_INLINE void sljit_unaligned_store_s32(void *addr, sljit_s32 value)
+{
+ SLJIT_MEMCPY(addr, &value, sizeof(value));
+}
+
+static SLJIT_INLINE void sljit_unaligned_store_sw(void *addr, sljit_sw value)
+{
+ SLJIT_MEMCPY(addr, &value, sizeof(value));
+}
+
+/******************************************************/
+/* Utility functions */
+/******************************************************/
+
+static void execute_cpu_id(sljit_u32 info[4])
+{
+#if (defined(_MSC_VER) && _MSC_VER >= 1400) \
+ || (defined(__INTEL_COMPILER) && __INTEL_COMPILER == 2021 && __INTEL_COMPILER_UPDATE >= 7)
+
+ __cpuidex((int*)info, (int)info[0], (int)info[2]);
+
+#elif (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1900)
+
+ __get_cpuid_count(info[0], info[2], info, info + 1, info + 2, info + 3);
+
+#elif (defined(_MSC_VER) || defined(__INTEL_COMPILER)) \
+ && (defined(SLJIT_CONFIG_X86_32) && SLJIT_CONFIG_X86_32)
+
+ /* Intel syntax. */
+ __asm {
+ mov esi, info
+ mov eax, [esi]
+ mov ecx, [esi + 8]
+ cpuid
+ mov [esi], eax
+ mov [esi + 4], ebx
+ mov [esi + 8], ecx
+ mov [esi + 12], edx
+ }
+
+#else
+
+ __asm__ __volatile__ (
+ "cpuid\n"
+ : "=a" (info[0]), "=b" (info[1]), "=c" (info[2]), "=d" (info[3])
+ : "0" (info[0]), "2" (info[2])
+ );
+
+#endif
+}
+
+static sljit_u32 execute_get_xcr0_low(void)
+{
+ sljit_u32 xcr0;
+
+#if (defined(_MSC_VER) && _MSC_VER >= 1400) || defined(__INTEL_COMPILER) \
+ || (defined(__INTEL_LLVM_COMPILER) && defined(__XSAVE__))
+
+ xcr0 = (sljit_u32)_xgetbv(0);
+
+#elif defined(__TINYC__)
+
+ __asm__ (
+ "xorl %%ecx, %%ecx\n"
+ ".byte 0x0f\n"
+ ".byte 0x01\n"
+ ".byte 0xd0\n"
+ : "=a" (xcr0)
+ :
+#if defined(SLJIT_CONFIG_X86_32) && SLJIT_CONFIG_X86_32
+ : "ecx", "edx"
+#else /* !SLJIT_CONFIG_X86_32 */
+ : "rcx", "rdx"
+#endif /* SLJIT_CONFIG_X86_32 */
+ );
+
+#elif (defined(__INTEL_LLVM_COMPILER) && __INTEL_LLVM_COMPILER < 20220100) \
+ || (defined(__clang__) && __clang_major__ < 14) \
+ || (defined(__GNUC__) && __GNUC__ < 3) \
+ || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+
+ /* AT&T syntax. */
+ __asm__ (
+ "xorl %%ecx, %%ecx\n"
+ "xgetbv\n"
+ : "=a" (xcr0)
+ :
+#if defined(SLJIT_CONFIG_X86_32) && SLJIT_CONFIG_X86_32
+ : "ecx", "edx"
+#else /* !SLJIT_CONFIG_X86_32 */
+ : "rcx", "rdx"
+#endif /* SLJIT_CONFIG_X86_32 */
+ );
+
+#elif defined(_MSC_VER)
+
+ /* Intel syntax. */
+ __asm {
+ xor ecx, ecx
+ xgetbv
+ mov xcr0, eax
+ }
+
+#else
+
+ __asm__ (
+ "xor{l %%ecx, %%ecx | ecx, ecx}\n"
+ "xgetbv\n"
+ : "=a" (xcr0)
+ :
+#if defined(SLJIT_CONFIG_X86_32) && SLJIT_CONFIG_X86_32
+ : "ecx", "edx"
+#else /* !SLJIT_CONFIG_X86_32 */
+ : "rcx", "rdx"
+#endif /* SLJIT_CONFIG_X86_32 */
+ );
+
+#endif
+ return xcr0;
+}
+
+static void get_cpu_features(void)
+{
+ sljit_u32 feature_list = CPU_FEATURE_DETECTED;
+ sljit_u32 info[4] = {0};
+ sljit_u32 max_id;
+
+ execute_cpu_id(info);
+ max_id = info[0];
+
+ if (max_id >= 7) {
+ info[0] = 7;
+ info[2] = 0;
+ execute_cpu_id(info);
+
+ if (info[1] & 0x8)
+ feature_list |= CPU_FEATURE_TZCNT;
+ if (info[1] & 0x20)
+ feature_list |= CPU_FEATURE_AVX2;
+ }
+
+ if (max_id >= 1) {
+ info[0] = 1;
+#if defined(SLJIT_CONFIG_X86_32) && SLJIT_CONFIG_X86_32
+ /* Winchip 2 and Cyrix MII bugs */
+ info[1] = info[2] = 0;
+#endif
+ execute_cpu_id(info);
+
+ if (info[2] & 0x80000)
+ feature_list |= CPU_FEATURE_SSE41;
+ if (info[2] & 0x8000000)
+ feature_list |= CPU_FEATURE_OSXSAVE;
+ if (info[2] & 0x10000000)
+ feature_list |= CPU_FEATURE_AVX;
+#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
+ if (info[3] & 0x4000000)
+ feature_list |= CPU_FEATURE_SSE2;
+#endif
+ if (info[3] & 0x8000)
+ feature_list |= CPU_FEATURE_CMOV;
+ }
+
+ info[0] = 0x80000000;
+ execute_cpu_id(info);
+ max_id = info[0];
+
+ if (max_id >= 0x80000001) {
+ info[0] = 0x80000001;
+ execute_cpu_id(info);
+
+ if (info[2] & 0x20)
+ feature_list |= CPU_FEATURE_LZCNT;
+ }
+
+ if ((feature_list & CPU_FEATURE_OSXSAVE) && (execute_get_xcr0_low() & 0x4) == 0)
+ feature_list &= ~(sljit_u32)(CPU_FEATURE_AVX | CPU_FEATURE_AVX2);
+
+ cpu_feature_list = feature_list;
+}
+
+static sljit_u8 get_jump_code(sljit_uw type)
+{
+ switch (type) {
+ case SLJIT_EQUAL:
+ case SLJIT_ATOMIC_STORED:
+ case SLJIT_F_EQUAL:
+ case SLJIT_UNORDERED_OR_EQUAL:
+ return 0x84 /* je */;
+
+ case SLJIT_NOT_EQUAL:
+ case SLJIT_ATOMIC_NOT_STORED:
+ case SLJIT_F_NOT_EQUAL:
+ case SLJIT_ORDERED_NOT_EQUAL:
+ return 0x85 /* jne */;
+
+ case SLJIT_LESS:
+ case SLJIT_CARRY:
+ case SLJIT_F_LESS:
+ case SLJIT_UNORDERED_OR_LESS:
+ case SLJIT_UNORDERED_OR_GREATER:
+ return 0x82 /* jc */;
+
+ case SLJIT_GREATER_EQUAL:
+ case SLJIT_NOT_CARRY:
+ case SLJIT_F_GREATER_EQUAL:
+ case SLJIT_ORDERED_GREATER_EQUAL:
+ case SLJIT_ORDERED_LESS_EQUAL:
+ return 0x83 /* jae */;
+
+ case SLJIT_GREATER:
+ case SLJIT_F_GREATER:
+ case SLJIT_ORDERED_LESS:
+ case SLJIT_ORDERED_GREATER:
+ return 0x87 /* jnbe */;
+
+ case SLJIT_LESS_EQUAL:
+ case SLJIT_F_LESS_EQUAL:
+ case SLJIT_UNORDERED_OR_GREATER_EQUAL:
+ case SLJIT_UNORDERED_OR_LESS_EQUAL:
+ return 0x86 /* jbe */;
+
+ case SLJIT_SIG_LESS:
+ return 0x8c /* jl */;
+
+ case SLJIT_SIG_GREATER_EQUAL:
+ return 0x8d /* jnl */;
+
+ case SLJIT_SIG_GREATER:
+ return 0x8f /* jnle */;
+
+ case SLJIT_SIG_LESS_EQUAL:
+ return 0x8e /* jle */;
+
+ case SLJIT_OVERFLOW:
+ return 0x80 /* jo */;
+
+ case SLJIT_NOT_OVERFLOW:
+ return 0x81 /* jno */;
+
+ case SLJIT_UNORDERED:
+ case SLJIT_ORDERED_EQUAL: /* NaN. */
+ return 0x8a /* jp */;
+
+ case SLJIT_ORDERED:
+ case SLJIT_UNORDERED_OR_NOT_EQUAL: /* Not NaN. */
+ return 0x8b /* jpo */;
+ }
+ return 0;
+}
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+static sljit_u8* detect_far_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset);
+#else /* !SLJIT_CONFIG_X86_32 */
+static sljit_u8* detect_far_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr);
+static sljit_u8* generate_mov_addr_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset);
+#endif /* SLJIT_CONFIG_X86_32 */
+
+static sljit_u8* detect_near_jump_type(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset)
+{
+ sljit_uw type = jump->flags >> TYPE_SHIFT;
+ sljit_s32 short_jump;
+ sljit_uw label_addr;
+ sljit_uw jump_addr;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ sljit_uw rel_size;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ jump_addr = (sljit_uw)code_ptr;
+ if (!(jump->flags & JUMP_ADDR)) {
+ label_addr = (sljit_uw)(code + jump->u.label->size);
+
+ if (jump->u.label->size > jump->addr)
+ jump_addr = (sljit_uw)(code + jump->addr);
+ } else
+ label_addr = jump->u.target - (sljit_uw)executable_offset;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ rel_size = (type < SLJIT_JUMP) ? 6 : 5;
+ if ((sljit_sw)(label_addr - (jump_addr + rel_size)) > HALFWORD_MAX || (sljit_sw)(label_addr - (jump_addr + rel_size)) < HALFWORD_MIN)
+ return detect_far_jump_type(jump, code_ptr);
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ short_jump = (sljit_sw)(label_addr - (jump_addr + 2)) >= -0x80 && (sljit_sw)(label_addr - (jump_addr + 2)) <= 0x7f;
+
+ if (type == SLJIT_JUMP) {
+ if (short_jump)
+ *code_ptr++ = JMP_i8;
+ else
+ *code_ptr++ = JMP_i32;
+ } else if (type > SLJIT_JUMP) {
+ short_jump = 0;
+ *code_ptr++ = CALL_i32;
+ } else if (short_jump) {
+ *code_ptr++ = U8(get_jump_code(type) - 0x10);
+ } else {
+ *code_ptr++ = GROUP_0F;
+ *code_ptr++ = get_jump_code(type);
+ }
+
+ jump->addr = (sljit_uw)code_ptr;
+
+ if (short_jump) {
+ jump->flags |= PATCH_MB;
+ code_ptr += sizeof(sljit_s8);
+ } else {
+ jump->flags |= PATCH_MW;
+ code_ptr += sizeof(sljit_s32);
+ }
+
+ return code_ptr;
+}
+
+static void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executable_offset)
+{
+ sljit_uw flags = jump->flags;
+ sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
+ sljit_uw jump_addr = jump->addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ if (SLJIT_UNLIKELY(flags & JUMP_MOV_ADDR)) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ sljit_unaligned_store_sw((void*)(jump_addr - sizeof(sljit_sw)), (sljit_sw)addr);
+#else /* SLJIT_CONFIG_X86_32 */
+ if (flags & PATCH_MD) {
+ SLJIT_ASSERT(addr > HALFWORD_MAX);
+ sljit_unaligned_store_sw((void*)(jump_addr - sizeof(sljit_sw)), (sljit_sw)addr);
+ return;
+ }
+
+ if (flags & PATCH_MW) {
+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET((sljit_u8*)jump_addr, executable_offset);
+ SLJIT_ASSERT((sljit_sw)addr <= HALFWORD_MAX && (sljit_sw)addr >= HALFWORD_MIN);
+ } else {
+ SLJIT_ASSERT(addr <= HALFWORD_MAX);
+ }
+ sljit_unaligned_store_s32((void*)(jump_addr - sizeof(sljit_s32)), (sljit_s32)addr);
+#endif /* !SLJIT_CONFIG_X86_32 */
+ return;
+ }
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (SLJIT_UNLIKELY(flags & PATCH_MD)) {
+ SLJIT_ASSERT(!(flags & JUMP_ADDR));
+ sljit_unaligned_store_sw((void*)jump_addr, (sljit_sw)addr);
+ return;
+ }
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET((sljit_u8*)jump_addr, executable_offset);
+
+ if (flags & PATCH_MB) {
+ addr -= sizeof(sljit_s8);
+ SLJIT_ASSERT((sljit_sw)addr <= 0x7f && (sljit_sw)addr >= -0x80);
+ *(sljit_u8*)jump_addr = U8(addr);
+ return;
+ } else if (flags & PATCH_MW) {
+ addr -= sizeof(sljit_s32);
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ sljit_unaligned_store_sw((void*)jump_addr, (sljit_sw)addr);
+#else /* !SLJIT_CONFIG_X86_32 */
+ SLJIT_ASSERT((sljit_sw)addr <= HALFWORD_MAX && (sljit_sw)addr >= HALFWORD_MIN);
+ sljit_unaligned_store_s32((void*)jump_addr, (sljit_s32)addr);
+#endif /* SLJIT_CONFIG_X86_32 */
+ }
+}
+
+static sljit_u8 *process_extended_label(sljit_u8 *code_ptr, struct sljit_extended_label *ext_label)
+{
+ sljit_uw mask;
+ sljit_u8 *ptr = code_ptr;
+
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ mask = ext_label->data;
+
+ code_ptr = (sljit_u8*)(((sljit_uw)code_ptr + mask) & ~mask);
+
+ while (ptr < code_ptr)
+ *ptr++ = NOP;
+
+ return code_ptr;
+}
+
+static void reduce_code_size(struct sljit_compiler *compiler)
+{
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ sljit_uw next_label_size;
+ sljit_uw next_jump_addr;
+ sljit_uw next_min_addr;
+ sljit_uw size_reduce = 0;
+ sljit_sw diff;
+ sljit_uw type;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ sljit_uw size_reduce_max;
+#endif /* SLJIT_DEBUG */
+
+ label = compiler->labels;
+ jump = compiler->jumps;
+
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+
+ while (1) {
+ next_min_addr = next_label_size;
+ if (next_jump_addr < next_min_addr)
+ next_min_addr = next_jump_addr;
+
+ if (next_min_addr == SLJIT_MAX_ADDRESS)
+ break;
+
+ if (next_min_addr == next_label_size) {
+ label->size -= size_reduce;
+
+ label = label->next;
+ next_label_size = SLJIT_GET_NEXT_SIZE(label);
+ }
+
+ if (next_min_addr != next_jump_addr)
+ continue;
+
+ jump->addr -= size_reduce;
+ if (!(jump->flags & JUMP_MOV_ADDR)) {
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ size_reduce_max = size_reduce + (((jump->flags >> TYPE_SHIFT) < SLJIT_JUMP) ? CJUMP_MAX_SIZE : JUMP_MAX_SIZE);
+#endif /* SLJIT_DEBUG */
+
+ if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {
+ if (jump->flags & JUMP_ADDR) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (jump->u.target <= 0xffffffffl)
+ size_reduce += sizeof(sljit_s32);
+#endif /* SLJIT_CONFIG_X86_64 */
+ } else {
+ /* Unit size: instruction. */
+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
+ if (jump->u.label->size > jump->addr) {
+ SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);
+ diff -= (sljit_sw)size_reduce;
+ }
+ type = jump->flags >> TYPE_SHIFT;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (type == SLJIT_JUMP) {
+ if (diff <= 0x7f + 2 && diff >= -0x80 + 2)
+ size_reduce += JUMP_MAX_SIZE - 2;
+ else if (diff <= HALFWORD_MAX + 5 && diff >= HALFWORD_MIN + 5)
+ size_reduce += JUMP_MAX_SIZE - 5;
+ } else if (type < SLJIT_JUMP) {
+ if (diff <= 0x7f + 2 && diff >= -0x80 + 2)
+ size_reduce += CJUMP_MAX_SIZE - 2;
+ else if (diff <= HALFWORD_MAX + 6 && diff >= HALFWORD_MIN + 6)
+ size_reduce += CJUMP_MAX_SIZE - 6;
+ } else {
+ if (diff <= HALFWORD_MAX + 5 && diff >= HALFWORD_MIN + 5)
+ size_reduce += JUMP_MAX_SIZE - 5;
+ }
+#else /* !SLJIT_CONFIG_X86_64 */
+ if (type == SLJIT_JUMP) {
+ if (diff <= 0x7f + 2 && diff >= -0x80 + 2)
+ size_reduce += JUMP_MAX_SIZE - 2;
+ } else if (type < SLJIT_JUMP) {
+ if (diff <= 0x7f + 2 && diff >= -0x80 + 2)
+ size_reduce += CJUMP_MAX_SIZE - 2;
+ }
+#endif /* SLJIT_CONFIG_X86_64 */
+ }
+ }
+
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ jump->flags |= (size_reduce_max - size_reduce) << JUMP_SIZE_SHIFT;
+#endif /* SLJIT_DEBUG */
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ } else {
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ size_reduce_max = size_reduce + 10;
+#endif /* SLJIT_DEBUG */
+
+ if (!(jump->flags & JUMP_ADDR)) {
+ diff = (sljit_sw)jump->u.label->size - (sljit_sw)(jump->addr - 3);
+
+ if (diff <= HALFWORD_MAX && diff >= HALFWORD_MIN)
+ size_reduce += 3;
+ } else if (jump->u.target <= 0xffffffffl)
+ size_reduce += (jump->flags & MOV_ADDR_HI) ? 4 : 5;
+
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ jump->flags |= (size_reduce_max - size_reduce) << JUMP_SIZE_SHIFT;
+#endif /* SLJIT_DEBUG */
+#endif /* SLJIT_CONFIG_X86_64 */
+ }
+
+ jump = jump->next;
+ next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
+ }
+
+ compiler->size -= size_reduce;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
+{
+ struct sljit_memory_fragment *buf;
+ sljit_u8 *code;
+ sljit_u8 *code_ptr;
+ sljit_u8 *buf_ptr;
+ sljit_u8 *buf_end;
+ sljit_u8 len;
+ sljit_sw executable_offset;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ sljit_uw addr;
+#endif /* SLJIT_DEBUG */
+
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
+
+ reduce_code_size(compiler);
+
+ /* Second code generation pass. */
+ code = (sljit_u8*)allocate_executable_memory(compiler->size, options, exec_allocator_data, &executable_offset);
+ PTR_FAIL_WITH_EXEC_IF(code);
+
+ reverse_buf(compiler);
+ buf = compiler->buf;
+
+ code_ptr = code;
+ label = compiler->labels;
+ jump = compiler->jumps;
+ const_ = compiler->consts;
+
+ do {
+ buf_ptr = buf->memory;
+ buf_end = buf_ptr + buf->used_size;
+ do {
+ len = *buf_ptr++;
+ SLJIT_ASSERT(len > 0);
+ if (len < SLJIT_INST_CONST) {
+ /* The code is already generated. */
+ SLJIT_MEMCPY(code_ptr, buf_ptr, len);
+ code_ptr += len;
+ buf_ptr += len;
+ } else {
+ switch (len) {
+ case SLJIT_INST_LABEL:
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
+ label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ label->size = (sljit_uw)(code_ptr - code);
+ label = label->next;
+ break;
+ case SLJIT_INST_JUMP:
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ addr = (sljit_uw)code_ptr;
+#endif /* SLJIT_DEBUG */
+ if (!(jump->flags & SLJIT_REWRITABLE_JUMP))
+ code_ptr = detect_near_jump_type(jump, code_ptr, code, executable_offset);
+ else {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ code_ptr = detect_far_jump_type(jump, code_ptr, executable_offset);
+#else /* !SLJIT_CONFIG_X86_32 */
+ code_ptr = detect_far_jump_type(jump, code_ptr);
+#endif /* SLJIT_CONFIG_X86_32 */
+ }
+
+ SLJIT_ASSERT((sljit_uw)code_ptr - addr <= ((jump->flags >> JUMP_SIZE_SHIFT) & 0xff));
+ jump = jump->next;
+ break;
+ case SLJIT_INST_MOV_ADDR:
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ code_ptr = generate_mov_addr_code(jump, code_ptr, code, executable_offset);
+#endif /* SLJIT_CONFIG_X86_64 */
+ jump->addr = (sljit_uw)code_ptr;
+ jump = jump->next;
+ break;
+ default:
+ SLJIT_ASSERT(len == SLJIT_INST_CONST);
+ const_->addr = (sljit_uw)code_ptr;
+ const_ = const_->next;
+ break;
+ }
+ }
+ } while (buf_ptr < buf_end);
+
+ SLJIT_ASSERT(buf_ptr == buf_end);
+ buf = buf->next;
+ } while (buf);
+
+ SLJIT_ASSERT(!label);
+ SLJIT_ASSERT(!jump);
+ SLJIT_ASSERT(!const_);
+ SLJIT_ASSERT(code_ptr <= code + compiler->size);
+
+ jump = compiler->jumps;
+ while (jump) {
+ generate_jump_or_mov_addr(jump, executable_offset);
+ jump = jump->next;
+ }
+
+ compiler->error = SLJIT_ERR_COMPILED;
+ compiler->executable_offset = executable_offset;
+ compiler->executable_size = (sljit_uw)(code_ptr - code);
+
+ code = (sljit_u8*)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+
+ SLJIT_UPDATE_WX_FLAGS(code, (sljit_u8*)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset), 1);
+ return (void*)code;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
+{
+ switch (feature_type) {
+ case SLJIT_HAS_FPU:
+#ifdef SLJIT_IS_FPU_AVAILABLE
+ return (SLJIT_IS_FPU_AVAILABLE) != 0;
+#elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
+ if (cpu_feature_list == 0)
+ get_cpu_features();
+ return (cpu_feature_list & CPU_FEATURE_SSE2) != 0;
+#else /* SLJIT_DETECT_SSE2 */
+ return 1;
+#endif /* SLJIT_DETECT_SSE2 */
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ case SLJIT_HAS_VIRTUAL_REGISTERS:
+ return 1;
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ case SLJIT_HAS_CLZ:
+ if (cpu_feature_list == 0)
+ get_cpu_features();
+
+ return (cpu_feature_list & CPU_FEATURE_LZCNT) ? 1 : 2;
+
+ case SLJIT_HAS_CTZ:
+ if (cpu_feature_list == 0)
+ get_cpu_features();
+
+ return (cpu_feature_list & CPU_FEATURE_TZCNT) ? 1 : 2;
+
+ case SLJIT_HAS_CMOV:
+ if (cpu_feature_list == 0)
+ get_cpu_features();
+ return (cpu_feature_list & CPU_FEATURE_CMOV) != 0;
+
+ case SLJIT_HAS_REV:
+ case SLJIT_HAS_ROT:
+ case SLJIT_HAS_PREFETCH:
+ case SLJIT_HAS_COPY_F32:
+ case SLJIT_HAS_COPY_F64:
+ case SLJIT_HAS_ATOMIC:
+ return 1;
+
+ case SLJIT_HAS_MEMORY_BARRIER:
+#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
+ if (cpu_feature_list == 0)
+ get_cpu_features();
+ return (cpu_feature_list & CPU_FEATURE_SSE2) != 0;
+#endif
+ return 1;
+
+#if !(defined SLJIT_IS_FPU_AVAILABLE) || SLJIT_IS_FPU_AVAILABLE
+ case SLJIT_HAS_AVX:
+ if (cpu_feature_list == 0)
+ get_cpu_features();
+ return (cpu_feature_list & CPU_FEATURE_AVX) != 0;
+ case SLJIT_HAS_AVX2:
+ if (cpu_feature_list == 0)
+ get_cpu_features();
+ return (cpu_feature_list & CPU_FEATURE_AVX2) != 0;
+ case SLJIT_HAS_SIMD:
+ if (cpu_feature_list == 0)
+ get_cpu_features();
+ return (cpu_feature_list & CPU_FEATURE_SSE41) != 0;
+#endif /* SLJIT_IS_FPU_AVAILABLE */
+ default:
+ return 0;
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
+{
+ switch (type) {
+ case SLJIT_ORDERED_EQUAL:
+ case SLJIT_UNORDERED_OR_NOT_EQUAL:
+ return 2;
+ }
+
+ return 0;
+}
+
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
+#define BINARY_OPCODE(opcode) (((opcode ## _EAX_i32) << 24) | ((opcode ## _r_rm) << 16) | ((opcode ## _rm_r) << 8) | (opcode))
+
+#define BINARY_IMM32(op_imm, immw, arg, argw) \
+ do { \
+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
+ FAIL_IF(!inst); \
+ *(inst + 1) |= (op_imm); \
+ } while (0)
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+
+#define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \
+ do { \
+ if (IS_HALFWORD(immw) || compiler->mode32) { \
+ BINARY_IMM32(op_imm, immw, arg, argw); \
+ } \
+ else { \
+ FAIL_IF(emit_load_imm64(compiler, FAST_IS_REG(arg) ? TMP_REG2 : TMP_REG1, immw)); \
+ inst = emit_x86_instruction(compiler, 1, FAST_IS_REG(arg) ? TMP_REG2 : TMP_REG1, 0, arg, argw); \
+ FAIL_IF(!inst); \
+ *inst = (op_mr); \
+ } \
+ } while (0)
+
+#define BINARY_EAX_IMM(op_eax_imm, immw) \
+ FAIL_IF(emit_do_imm32(compiler, (!compiler->mode32) ? REX_W : 0, (op_eax_imm), immw))
+
+#else /* !SLJIT_CONFIG_X86_64 */
+
+#define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \
+ BINARY_IMM32(op_imm, immw, arg, argw)
+
+#define BINARY_EAX_IMM(op_eax_imm, immw) \
+ FAIL_IF(emit_do_imm(compiler, (op_eax_imm), immw))
+
+#endif /* SLJIT_CONFIG_X86_64 */
+
+static sljit_s32 emit_byte(struct sljit_compiler *compiler, sljit_u8 byte)
+{
+ sljit_u8 *inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
+ INC_SIZE(1);
+ *inst = byte;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_mov(struct sljit_compiler *compiler,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw);
+
+#define EMIT_MOV(compiler, dst, dstw, src, srcw) \
+ FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
+
+static sljit_s32 emit_groupf(struct sljit_compiler *compiler,
+ sljit_uw op,
+ sljit_s32 dst, sljit_s32 src, sljit_sw srcw);
+
+static sljit_s32 emit_groupf_ext(struct sljit_compiler *compiler,
+ sljit_uw op,
+ sljit_s32 dst, sljit_s32 src, sljit_sw srcw);
+
+static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler,
+ sljit_s32 single, sljit_s32 dst, sljit_sw dstw, sljit_s32 src);
+
+static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler,
+ sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw);
+
+static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w);
+
+static sljit_s32 emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src, sljit_sw srcw);
+
+static SLJIT_INLINE sljit_s32 emit_endbranch(struct sljit_compiler *compiler)
+{
+#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)
+ /* Emit endbr32/endbr64 when CET is enabled. */
+ sljit_u8 *inst;
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+ inst[0] = GROUP_F3;
+ inst[1] = GROUP_0F;
+ inst[2] = 0x1e;
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ inst[3] = 0xfb;
+#else /* !SLJIT_CONFIG_X86_32 */
+ inst[3] = 0xfa;
+#endif /* SLJIT_CONFIG_X86_32 */
+#else /* !SLJIT_CONFIG_X86_CET */
+ SLJIT_UNUSED_ARG(compiler);
+#endif /* SLJIT_CONFIG_X86_CET */
+ return SLJIT_SUCCESS;
+}
+
+#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)
+
+static SLJIT_INLINE sljit_s32 emit_rdssp(struct sljit_compiler *compiler, sljit_s32 reg)
+{
+ sljit_u8 *inst;
+ sljit_s32 size;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ size = 5;
+#else
+ size = 4;
+#endif
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+ INC_SIZE(size);
+ *inst++ = GROUP_F3;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B);
+#endif
+ inst[0] = GROUP_0F;
+ inst[1] = 0x1e;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ inst[2] = U8(MOD_REG | (0x1 << 3) | reg_lmap[reg]);
+#else
+ inst[2] = U8(MOD_REG | (0x1 << 3) | reg_map[reg]);
+#endif
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 emit_incssp(struct sljit_compiler *compiler, sljit_s32 reg)
+{
+ sljit_u8 *inst;
+ sljit_s32 size;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ size = 5;
+#else
+ size = 4;
+#endif
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+ INC_SIZE(size);
+ *inst++ = GROUP_F3;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B);
+#endif
+ inst[0] = GROUP_0F;
+ inst[1] = 0xae;
+ inst[2] = (0x3 << 6) | (0x5 << 3) | (reg_map[reg] & 0x7);
+ return SLJIT_SUCCESS;
+}
+
+#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */
+
+static SLJIT_INLINE sljit_s32 cpu_has_shadow_stack(void)
+{
+#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)
+ return _get_ssp() != 0;
+#else /* !SLJIT_CONFIG_X86_CET || !__SHSTK__ */
+ return 0;
+#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */
+}
+
+static SLJIT_INLINE sljit_s32 adjust_shadow_stack(struct sljit_compiler *compiler,
+ sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)
+ sljit_u8 *inst, *jz_after_cmp_inst;
+ sljit_uw size_jz_after_cmp_inst;
+
+ sljit_uw size_before_rdssp_inst = compiler->size;
+
+ /* Generate "RDSSP TMP_REG1". */
+ FAIL_IF(emit_rdssp(compiler, TMP_REG1));
+
+ /* Load return address on shadow stack into TMP_REG1. */
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(TMP_REG1), 0);
+
+ /* Compare return address against TMP_REG1. */
+ FAIL_IF(emit_cmp_binary (compiler, TMP_REG1, 0, src, srcw));
+
+ /* Generate JZ to skip shadow stack ajdustment when shadow
+ stack matches normal stack. */
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(2);
+ *inst++ = get_jump_code(SLJIT_EQUAL) - 0x10;
+ size_jz_after_cmp_inst = compiler->size;
+ jz_after_cmp_inst = inst;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ /* REX_W is not necessary. */
+ compiler->mode32 = 1;
+#endif
+ /* Load 1 into TMP_REG1. */
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 1);
+
+ /* Generate "INCSSP TMP_REG1". */
+ FAIL_IF(emit_incssp(compiler, TMP_REG1));
+
+ /* Jump back to "RDSSP TMP_REG1" to check shadow stack again. */
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(2);
+ inst[0] = JMP_i8;
+ inst[1] = size_before_rdssp_inst - compiler->size;
+
+ *jz_after_cmp_inst = compiler->size - size_jz_after_cmp_inst;
+#else /* !SLJIT_CONFIG_X86_CET || !__SHSTK__ */
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(src);
+ SLJIT_UNUSED_ARG(srcw);
+#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */
+ return SLJIT_SUCCESS;
+}
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+#include "sljitNativeX86_32.c"
+#else
+#include "sljitNativeX86_64.c"
+#endif
+
+static sljit_s32 emit_mov(struct sljit_compiler *compiler,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8* inst;
+
+ if (FAST_IS_REG(src)) {
+ inst = emit_x86_instruction(compiler, 1, src, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_r;
+ return SLJIT_SUCCESS;
+ }
+
+ if (src == SLJIT_IMM) {
+ if (FAST_IS_REG(dst)) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw);
+#else
+ if (!compiler->mode32) {
+ if (NOT_HALFWORD(srcw))
+ return emit_load_imm64(compiler, dst, srcw);
+ }
+ else
+ return emit_do_imm32(compiler, (reg_map[dst] >= 8) ? REX_B : 0, U8(MOV_r_i32 | reg_lmap[dst]), srcw);
+#endif
+ }
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (!compiler->mode32 && NOT_HALFWORD(srcw)) {
+ /* Immediate to memory move. Only SLJIT_MOV operation copies
+ an immediate directly into memory so TMP_REG1 can be used. */
+ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw));
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_r;
+ return SLJIT_SUCCESS;
+ }
+#endif
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_i32;
+ return SLJIT_SUCCESS;
+ }
+ if (FAST_IS_REG(dst)) {
+ inst = emit_x86_instruction(compiler, 1, dst, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst = MOV_r_rm;
+ return SLJIT_SUCCESS;
+ }
+
+ /* Memory to memory move. Only SLJIT_MOV operation copies
+ data from memory to memory so TMP_REG1 can be used. */
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src, srcw);
+ FAIL_IF(!inst);
+ *inst = MOV_r_rm;
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_r;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_reg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8* inst;
+ sljit_uw size;
+
+ SLJIT_ASSERT(type >= SLJIT_EQUAL && type <= SLJIT_ORDERED_LESS_EQUAL);
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(2);
+ inst[0] = U8(get_jump_code((sljit_uw)type ^ 0x1) - 0x10);
+
+ size = compiler->size;
+ EMIT_MOV(compiler, dst_reg, 0, src, srcw);
+
+ inst[1] = U8(compiler->size - size);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
+{
+ sljit_u8 *inst;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ sljit_uw size;
+#endif
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op0(compiler, op));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_BREAKPOINT:
+ return emit_byte(compiler, INT3);
+ case SLJIT_NOP:
+ return emit_byte(compiler, NOP);
+ case SLJIT_LMUL_UW:
+ case SLJIT_LMUL_SW:
+ case SLJIT_DIVMOD_UW:
+ case SLJIT_DIVMOD_SW:
+ case SLJIT_DIV_UW:
+ case SLJIT_DIV_SW:
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+#ifdef _WIN64
+ SLJIT_ASSERT(
+ reg_map[SLJIT_R0] == 0
+ && reg_map[SLJIT_R1] == 2
+ && reg_map[TMP_REG1] > 7);
+#else
+ SLJIT_ASSERT(
+ reg_map[SLJIT_R0] == 0
+ && reg_map[SLJIT_R1] < 7
+ && reg_map[TMP_REG1] == 2);
+#endif
+ compiler->mode32 = op & SLJIT_32;
+#endif
+ SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
+
+ op = GET_OPCODE(op);
+ if ((op | 0x2) == SLJIT_DIV_UW) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0);
+ inst = emit_x86_instruction(compiler, 1, SLJIT_R1, 0, SLJIT_R1, 0);
+#else
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG1, 0);
+#endif
+ FAIL_IF(!inst);
+ *inst = XOR_r_rm;
+ }
+
+ if ((op | 0x2) == SLJIT_DIV_SW) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0);
+#endif
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ FAIL_IF(emit_byte(compiler, CDQ));
+#else
+ if (!compiler->mode32) {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(2);
+ inst[0] = REX_W;
+ inst[1] = CDQ;
+ } else
+ FAIL_IF(emit_byte(compiler, CDQ));
+#endif
+ }
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(2);
+ inst[0] = GROUP_F7;
+ inst[1] = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]);
+#else /* !SLJIT_CONFIG_X86_32 */
+#ifdef _WIN64
+ size = (!compiler->mode32 || op >= SLJIT_DIVMOD_UW) ? 3 : 2;
+#else /* !_WIN64 */
+ size = (!compiler->mode32) ? 3 : 2;
+#endif /* _WIN64 */
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+ INC_SIZE(size);
+#ifdef _WIN64
+ if (!compiler->mode32)
+ *inst++ = REX_W | ((op >= SLJIT_DIVMOD_UW) ? REX_B : 0);
+ else if (op >= SLJIT_DIVMOD_UW)
+ *inst++ = REX_B;
+ inst[0] = GROUP_F7;
+ inst[1] = MOD_REG | ((op >= SLJIT_DIVMOD_UW) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]);
+#else /* !_WIN64 */
+ if (!compiler->mode32)
+ *inst++ = REX_W;
+ inst[0] = GROUP_F7;
+ inst[1] = MOD_REG | reg_map[SLJIT_R1];
+#endif /* _WIN64 */
+#endif /* SLJIT_CONFIG_X86_32 */
+ switch (op) {
+ case SLJIT_LMUL_UW:
+ inst[1] |= MUL;
+ break;
+ case SLJIT_LMUL_SW:
+ inst[1] |= IMUL;
+ break;
+ case SLJIT_DIVMOD_UW:
+ case SLJIT_DIV_UW:
+ inst[1] |= DIV;
+ break;
+ case SLJIT_DIVMOD_SW:
+ case SLJIT_DIV_SW:
+ inst[1] |= IDIV;
+ break;
+ }
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64)
+ if (op <= SLJIT_DIVMOD_SW)
+ EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
+#else
+ if (op >= SLJIT_DIV_UW)
+ EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
+#endif
+ break;
+ case SLJIT_MEMORY_BARRIER:
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);
+ FAIL_IF(!inst);
+ INC_SIZE(3);
+ inst[0] = GROUP_0F;
+ inst[1] = 0xae;
+ inst[2] = 0xf0;
+ return SLJIT_SUCCESS;
+ case SLJIT_ENDBR:
+ return emit_endbranch(compiler);
+ case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
+ return skip_frames_before_return(compiler);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8* inst;
+ sljit_s32 dst_r;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+#endif
+
+ if (src == SLJIT_IMM) {
+ if (FAST_IS_REG(dst)) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw);
+#else
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_i32;
+ return SLJIT_SUCCESS;
+#endif
+ }
+ inst = emit_x86_instruction(compiler, 1 | EX86_BYTE_ARG | EX86_NO_REXW, SLJIT_IMM, srcw, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm8_i8;
+ return SLJIT_SUCCESS;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if ((dst & SLJIT_MEM) && FAST_IS_REG(src)) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if (reg_map[src] >= 4) {
+ SLJIT_ASSERT(dst_r == TMP_REG1);
+ EMIT_MOV(compiler, TMP_REG1, 0, src, 0);
+ } else
+ dst_r = src;
+#else
+ dst_r = src;
+#endif
+ } else {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if (FAST_IS_REG(src) && reg_map[src] >= 4) {
+ /* Both src and dst are registers. */
+ SLJIT_ASSERT(FAST_IS_REG(dst));
+
+ if (src == dst && !sign) {
+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 0xff, dst, 0);
+ FAIL_IF(!inst);
+ *(inst + 1) |= AND;
+ return SLJIT_SUCCESS;
+ }
+
+ EMIT_MOV(compiler, TMP_REG1, 0, src, 0);
+ src = TMP_REG1;
+ srcw = 0;
+ }
+#endif /* !SLJIT_CONFIG_X86_32 */
+
+ /* src can be memory addr or reg_map[src] < 4 on x86_32 architectures. */
+ FAIL_IF(emit_groupf(compiler, sign ? MOVSX_r_rm8 : MOVZX_r_rm8, dst_r, src, srcw));
+ }
+
+ if (dst & SLJIT_MEM) {
+ inst = emit_x86_instruction(compiler, 1 | EX86_REX | EX86_NO_REXW, dst_r, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm8_r8;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8* inst;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 1;
+#endif
+
+ inst = emit_x86_instruction(compiler, 2, 0, 0, src, srcw);
+ FAIL_IF(!inst);
+ inst[0] = GROUP_0F;
+ inst[1] = PREFETCH;
+
+ if (op == SLJIT_PREFETCH_L1)
+ inst[2] |= (1 << 3);
+ else if (op == SLJIT_PREFETCH_L2)
+ inst[2] |= (2 << 3);
+ else if (op == SLJIT_PREFETCH_L3)
+ inst[2] |= (3 << 3);
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_mov_half(struct sljit_compiler *compiler, sljit_s32 sign,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8* inst;
+ sljit_s32 dst_r;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+#endif
+
+ if (src == SLJIT_IMM) {
+ if (FAST_IS_REG(dst)) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw);
+#else
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_i32;
+ return SLJIT_SUCCESS;
+#endif
+ }
+ inst = emit_x86_instruction(compiler, 1 | EX86_HALF_ARG | EX86_NO_REXW | EX86_PREF_66, SLJIT_IMM, srcw, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_i32;
+ return SLJIT_SUCCESS;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if ((dst & SLJIT_MEM) && FAST_IS_REG(src))
+ dst_r = src;
+ else
+ FAIL_IF(emit_groupf(compiler, sign ? MOVSX_r_rm16 : MOVZX_r_rm16, dst_r, src, srcw));
+
+ if (dst & SLJIT_MEM) {
+ inst = emit_x86_instruction(compiler, 1 | EX86_NO_REXW | EX86_PREF_66, dst_r, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = MOV_rm_r;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_unary(struct sljit_compiler *compiler, sljit_u8 opcode,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8* inst;
+
+ if (dst == src && dstw == srcw) {
+ /* Same input and output */
+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
+ FAIL_IF(!inst);
+ inst[0] = GROUP_F7;
+ inst[1] |= opcode;
+ return SLJIT_SUCCESS;
+ }
+
+ if (FAST_IS_REG(dst)) {
+ EMIT_MOV(compiler, dst, 0, src, srcw);
+ inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0);
+ FAIL_IF(!inst);
+ inst[0] = GROUP_F7;
+ inst[1] |= opcode;
+ return SLJIT_SUCCESS;
+ }
+
+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
+ inst = emit_x86_instruction(compiler, 1, 0, 0, TMP_REG1, 0);
+ FAIL_IF(!inst);
+ inst[0] = GROUP_F7;
+ inst[1] |= opcode;
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
+ return SLJIT_SUCCESS;
+}
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+static const sljit_sw emit_clz_arg = 32 + 31;
+static const sljit_sw emit_ctz_arg = 32;
+#endif
+
+static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 is_clz,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8* inst;
+ sljit_s32 dst_r;
+ sljit_sw max;
+
+ SLJIT_ASSERT(cpu_feature_list != 0);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (is_clz ? (cpu_feature_list & CPU_FEATURE_LZCNT) : (cpu_feature_list & CPU_FEATURE_TZCNT)) {
+ FAIL_IF(emit_groupf(compiler, (is_clz ? LZCNT_r_rm : TZCNT_r_rm) | EX86_PREF_F3, dst_r, src, srcw));
+
+ if (dst & SLJIT_MEM)
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
+ return SLJIT_SUCCESS;
+ }
+
+ FAIL_IF(emit_groupf(compiler, is_clz ? BSR_r_rm : BSF_r_rm, dst_r, src, srcw));
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ max = is_clz ? (32 + 31) : 32;
+
+ if (cpu_feature_list & CPU_FEATURE_CMOV) {
+ if (dst_r != TMP_REG1) {
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, max);
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG1, 0);
+ }
+ else
+ inst = emit_x86_instruction(compiler, 2, dst_r, 0, SLJIT_MEM0(), is_clz ? (sljit_sw)&emit_clz_arg : (sljit_sw)&emit_ctz_arg);
+
+ FAIL_IF(!inst);
+ inst[0] = GROUP_0F;
+ inst[1] = CMOVE_r_rm;
+ }
+ else
+ FAIL_IF(emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, max));
+
+ if (is_clz) {
+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0);
+ FAIL_IF(!inst);
+ *(inst + 1) |= XOR;
+ }
+#else
+ if (is_clz)
+ max = compiler->mode32 ? (32 + 31) : (64 + 63);
+ else
+ max = compiler->mode32 ? 32 : 64;
+
+ if (cpu_feature_list & CPU_FEATURE_CMOV) {
+ EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, max);
+ FAIL_IF(emit_groupf(compiler, CMOVE_r_rm, dst_r, TMP_REG2, 0));
+ } else
+ FAIL_IF(emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, max));
+
+ if (is_clz) {
+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, max >> 1, dst_r, 0);
+ FAIL_IF(!inst);
+ *(inst + 1) |= XOR;
+ }
+#endif
+
+ if (dst & SLJIT_MEM)
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_bswap(struct sljit_compiler *compiler,
+ sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8 *inst;
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ sljit_uw size;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ sljit_u8 rex = 0;
+#else /* !SLJIT_CONFIG_X86_64 */
+ sljit_s32 dst_is_ereg = op & SLJIT_32;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (op == SLJIT_REV_U32 || op == SLJIT_REV_S32)
+ compiler->mode32 = 1;
+#else /* !SLJIT_CONFIG_X86_64 */
+ op &= ~SLJIT_32;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (src != dst_r) {
+ /* Only the lower 16 bit is read for eregs. */
+ if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16)
+ FAIL_IF(emit_mov_half(compiler, 0, dst_r, 0, src, srcw));
+ else
+ EMIT_MOV(compiler, dst_r, 0, src, srcw);
+ }
+
+ size = 2;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (!compiler->mode32)
+ rex = REX_W;
+
+ if (reg_map[dst_r] >= 8)
+ rex |= REX_B;
+
+ if (rex != 0)
+ size++;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+ INC_SIZE(size);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (rex != 0)
+ *inst++ = rex;
+
+ inst[0] = GROUP_0F;
+ inst[1] = BSWAP_r | reg_lmap[dst_r];
+#else /* !SLJIT_CONFIG_X86_64 */
+ inst[0] = GROUP_0F;
+ inst[1] = BSWAP_r | reg_map[dst_r];
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ size = compiler->mode32 ? 16 : 48;
+#else /* !SLJIT_CONFIG_X86_64 */
+ size = 16;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, (sljit_sw)size, dst_r, 0);
+ FAIL_IF(!inst);
+ if (op == SLJIT_REV_U16)
+ inst[1] |= SHR;
+ else
+ inst[1] |= SAR;
+ }
+
+ if (dst & SLJIT_MEM) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if (dst_is_ereg)
+ op = SLJIT_REV;
+#endif /* SLJIT_CONFIG_X86_32 */
+ if (op == SLJIT_REV_U16 || op == SLJIT_REV_S16)
+ return emit_mov_half(compiler, 0, dst, dstw, TMP_REG1, 0);
+
+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
+ }
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (op == SLJIT_REV_S32) {
+ compiler->mode32 = 0;
+ inst = emit_x86_instruction(compiler, 1, dst, 0, dst, 0);
+ FAIL_IF(!inst);
+ *inst = MOVSXD_r_rm;
+ }
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ sljit_s32 dst_is_ereg = 0;
+#else /* !SLJIT_CONFIG_X86_32 */
+ sljit_s32 op_flags = GET_ALL_FLAGS(op);
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1);
+ CHECK_EXTRA_REGS(src, srcw, (void)0);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = op_flags & SLJIT_32;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ op = GET_OPCODE(op);
+
+ if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (FAST_IS_REG(src) && src == dst) {
+ if (!TYPE_CAST_NEEDED(op))
+ return SLJIT_SUCCESS;
+ }
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (op_flags & SLJIT_32) {
+ if (src & SLJIT_MEM) {
+ if (op == SLJIT_MOV_S32)
+ op = SLJIT_MOV_U32;
+ }
+ else if (src == SLJIT_IMM) {
+ if (op == SLJIT_MOV_U32)
+ op = SLJIT_MOV_S32;
+ }
+ }
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (src == SLJIT_IMM) {
+ switch (op) {
+ case SLJIT_MOV_U8:
+ srcw = (sljit_u8)srcw;
+ break;
+ case SLJIT_MOV_S8:
+ srcw = (sljit_s8)srcw;
+ break;
+ case SLJIT_MOV_U16:
+ srcw = (sljit_u16)srcw;
+ break;
+ case SLJIT_MOV_S16:
+ srcw = (sljit_s16)srcw;
+ break;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ case SLJIT_MOV_U32:
+ srcw = (sljit_u32)srcw;
+ break;
+ case SLJIT_MOV_S32:
+ srcw = (sljit_s32)srcw;
+ break;
+#endif /* SLJIT_CONFIG_X86_64 */
+ }
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if (SLJIT_UNLIKELY(dst_is_ereg))
+ return emit_mov(compiler, dst, dstw, src, srcw);
+#endif /* SLJIT_CONFIG_X86_32 */
+ }
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if (SLJIT_UNLIKELY(dst_is_ereg) && (!(op == SLJIT_MOV || op == SLJIT_MOV_U32 || op == SLJIT_MOV_S32 || op == SLJIT_MOV_P) || (src & SLJIT_MEM))) {
+ SLJIT_ASSERT(dst == SLJIT_MEM1(SLJIT_SP));
+ dst = TMP_REG1;
+ }
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ switch (op) {
+ case SLJIT_MOV:
+ case SLJIT_MOV_P:
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+#endif /* SLJIT_CONFIG_X86_32 */
+ EMIT_MOV(compiler, dst, dstw, src, srcw);
+ break;
+ case SLJIT_MOV_U8:
+ FAIL_IF(emit_mov_byte(compiler, 0, dst, dstw, src, srcw));
+ break;
+ case SLJIT_MOV_S8:
+ FAIL_IF(emit_mov_byte(compiler, 1, dst, dstw, src, srcw));
+ break;
+ case SLJIT_MOV_U16:
+ FAIL_IF(emit_mov_half(compiler, 0, dst, dstw, src, srcw));
+ break;
+ case SLJIT_MOV_S16:
+ FAIL_IF(emit_mov_half(compiler, 1, dst, dstw, src, srcw));
+ break;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ case SLJIT_MOV_U32:
+ FAIL_IF(emit_mov_int(compiler, 0, dst, dstw, src, srcw));
+ break;
+ case SLJIT_MOV_S32:
+ FAIL_IF(emit_mov_int(compiler, 1, dst, dstw, src, srcw));
+ break;
+ case SLJIT_MOV32:
+ compiler->mode32 = 1;
+ EMIT_MOV(compiler, dst, dstw, src, srcw);
+ compiler->mode32 = 0;
+ break;
+#endif /* SLJIT_CONFIG_X86_64 */
+ }
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if (SLJIT_UNLIKELY(dst_is_ereg) && dst == TMP_REG1)
+ return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), dstw, TMP_REG1, 0);
+#endif /* SLJIT_CONFIG_X86_32 */
+ return SLJIT_SUCCESS;
+ }
+
+ switch (op) {
+ case SLJIT_CLZ:
+ case SLJIT_CTZ:
+ return emit_clz_ctz(compiler, (op == SLJIT_CLZ), dst, dstw, src, srcw);
+ case SLJIT_REV:
+ case SLJIT_REV_U16:
+ case SLJIT_REV_S16:
+ case SLJIT_REV_U32:
+ case SLJIT_REV_S32:
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if (dst_is_ereg)
+ op |= SLJIT_32;
+#endif /* SLJIT_CONFIG_X86_32 */
+ return emit_bswap(compiler, op, dst, dstw, src, srcw);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler,
+ sljit_u32 op_types,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_u8* inst;
+ sljit_u8 op_eax_imm = U8(op_types >> 24);
+ sljit_u8 op_rm = U8((op_types >> 16) & 0xff);
+ sljit_u8 op_mr = U8((op_types >> 8) & 0xff);
+ sljit_u8 op_imm = U8(op_types & 0xff);
+
+ if (dst == src1 && dstw == src1w) {
+ if (src2 == SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
+#else
+ if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128)) {
+#endif
+ BINARY_EAX_IMM(op_eax_imm, src2w);
+ }
+ else {
+ BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);
+ }
+ }
+ else if (FAST_IS_REG(dst)) {
+ inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
+ }
+ else if (FAST_IS_REG(src2)) {
+ /* Special exception for sljit_emit_op_flags. */
+ inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = op_mr;
+ }
+ else {
+ EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = op_mr;
+ }
+ return SLJIT_SUCCESS;
+ }
+
+ /* Only for cumulative operations. */
+ if (dst == src2 && dstw == src2w) {
+ if (src1 == SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if ((dst == SLJIT_R0) && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
+#else
+ if ((dst == SLJIT_R0) && (src1w > 127 || src1w < -128)) {
+#endif
+ BINARY_EAX_IMM(op_eax_imm, src1w);
+ }
+ else {
+ BINARY_IMM(op_imm, op_mr, src1w, dst, dstw);
+ }
+ }
+ else if (FAST_IS_REG(dst)) {
+ inst = emit_x86_instruction(compiler, 1, dst, dstw, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
+ }
+ else if (FAST_IS_REG(src1)) {
+ inst = emit_x86_instruction(compiler, 1, src1, src1w, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = op_mr;
+ }
+ else {
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = op_mr;
+ }
+ return SLJIT_SUCCESS;
+ }
+
+ /* General version. */
+ if (FAST_IS_REG(dst)) {
+ EMIT_MOV(compiler, dst, 0, src1, src1w);
+ if (src2 == SLJIT_IMM) {
+ BINARY_IMM(op_imm, op_mr, src2w, dst, 0);
+ }
+ else {
+ inst = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
+ }
+ }
+ else {
+ /* This version requires less memory writing. */
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ if (src2 == SLJIT_IMM) {
+ BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);
+ }
+ else {
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
+ }
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler,
+ sljit_u32 op_types,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_u8* inst;
+ sljit_u8 op_eax_imm = U8(op_types >> 24);
+ sljit_u8 op_rm = U8((op_types >> 16) & 0xff);
+ sljit_u8 op_mr = U8((op_types >> 8) & 0xff);
+ sljit_u8 op_imm = U8(op_types & 0xff);
+
+ if (dst == src1 && dstw == src1w) {
+ if (src2 == SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
+#else
+ if ((dst == SLJIT_R0) && (src2w > 127 || src2w < -128)) {
+#endif
+ BINARY_EAX_IMM(op_eax_imm, src2w);
+ }
+ else {
+ BINARY_IMM(op_imm, op_mr, src2w, dst, dstw);
+ }
+ }
+ else if (FAST_IS_REG(dst)) {
+ inst = emit_x86_instruction(compiler, 1, dst, dstw, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
+ }
+ else if (FAST_IS_REG(src2)) {
+ inst = emit_x86_instruction(compiler, 1, src2, src2w, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = op_mr;
+ }
+ else {
+ EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = op_mr;
+ }
+ return SLJIT_SUCCESS;
+ }
+
+ /* General version. */
+ if (FAST_IS_REG(dst) && dst != src2) {
+ EMIT_MOV(compiler, dst, 0, src1, src1w);
+ if (src2 == SLJIT_IMM) {
+ BINARY_IMM(op_imm, op_mr, src2w, dst, 0);
+ }
+ else {
+ inst = emit_x86_instruction(compiler, 1, dst, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
+ }
+ }
+ else {
+ /* This version requires less memory writing. */
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ if (src2 == SLJIT_IMM) {
+ BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);
+ }
+ else {
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = op_rm;
+ }
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_mul(struct sljit_compiler *compiler,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_u8* inst;
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ /* Register destination. */
+ if (dst_r == src1 && src2 != SLJIT_IMM) {
+ FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, src2, src2w));
+ } else if (dst_r == src2 && src1 != SLJIT_IMM) {
+ FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, src1, src1w));
+ } else if (src1 == SLJIT_IMM) {
+ if (src2 == SLJIT_IMM) {
+ EMIT_MOV(compiler, dst_r, 0, SLJIT_IMM, src2w);
+ src2 = dst_r;
+ src2w = 0;
+ }
+
+ if (src1w <= 127 && src1w >= -128) {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = IMUL_r_rm_i8;
+
+ FAIL_IF(emit_byte(compiler, U8(src1w)));
+ }
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ else {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = IMUL_r_rm_i32;
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+ sljit_unaligned_store_sw(inst, src1w);
+ }
+#else
+ else if (IS_HALFWORD(src1w)) {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = IMUL_r_rm_i32;
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+ sljit_unaligned_store_s32(inst, (sljit_s32)src1w);
+ }
+ else {
+ if (dst_r != src2)
+ EMIT_MOV(compiler, dst_r, 0, src2, src2w);
+ FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w));
+ FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, TMP_REG2, 0));
+ }
+#endif
+ }
+ else if (src2 == SLJIT_IMM) {
+ /* Note: src1 is NOT immediate. */
+
+ if (src2w <= 127 && src2w >= -128) {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = IMUL_r_rm_i8;
+
+ FAIL_IF(emit_byte(compiler, U8(src2w)));
+ }
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ else {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = IMUL_r_rm_i32;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+ sljit_unaligned_store_sw(inst, src2w);
+ }
+#else
+ else if (IS_HALFWORD(src2w)) {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = IMUL_r_rm_i32;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
+ FAIL_IF(!inst);
+ INC_SIZE(4);
+ sljit_unaligned_store_s32(inst, (sljit_s32)src2w);
+ } else {
+ if (dst_r != src1)
+ EMIT_MOV(compiler, dst_r, 0, src1, src1w);
+ FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
+ FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, TMP_REG2, 0));
+ }
+#endif
+ } else {
+ /* Neither argument is immediate. */
+ if (ADDRESSING_DEPENDS_ON(src2, dst_r))
+ dst_r = TMP_REG1;
+ EMIT_MOV(compiler, dst_r, 0, src1, src1w);
+ FAIL_IF(emit_groupf(compiler, IMUL_r_rm, dst_r, src2, src2w));
+ }
+
+ if (dst & SLJIT_MEM)
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_lea_binary(struct sljit_compiler *compiler,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_u8* inst;
+ sljit_s32 dst_r, done = 0;
+
+ /* These cases better be left to handled by normal way. */
+ if (dst == src1 && dstw == src1w)
+ return SLJIT_ERR_UNSUPPORTED;
+ if (dst == src2 && dstw == src2w)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (FAST_IS_REG(src1)) {
+ if (FAST_IS_REG(src2)) {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), 0);
+ FAIL_IF(!inst);
+ *inst = LEA_r_m;
+ done = 1;
+ }
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (src2 == SLJIT_IMM && (compiler->mode32 || IS_HALFWORD(src2w))) {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), (sljit_s32)src2w);
+#else
+ if (src2 == SLJIT_IMM) {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src1), src2w);
+#endif
+ FAIL_IF(!inst);
+ *inst = LEA_r_m;
+ done = 1;
+ }
+ }
+ else if (FAST_IS_REG(src2)) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (src1 == SLJIT_IMM && (compiler->mode32 || IS_HALFWORD(src1w))) {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), (sljit_s32)src1w);
+#else
+ if (src1 == SLJIT_IMM) {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM1(src2), src1w);
+#endif
+ FAIL_IF(!inst);
+ *inst = LEA_r_m;
+ done = 1;
+ }
+ }
+
+ if (done) {
+ if (dst_r == TMP_REG1)
+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
+ return SLJIT_SUCCESS;
+ }
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
+static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_u8* inst;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (src1 == SLJIT_R0 && src2 == SLJIT_IMM && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
+#else
+ if (src1 == SLJIT_R0 && src2 == SLJIT_IMM && (src2w > 127 || src2w < -128)) {
+#endif
+ BINARY_EAX_IMM(CMP_EAX_i32, src2w);
+ return SLJIT_SUCCESS;
+ }
+
+ if (FAST_IS_REG(src1)) {
+ if (src2 == SLJIT_IMM) {
+ BINARY_IMM(CMP, CMP_rm_r, src2w, src1, 0);
+ }
+ else {
+ inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = CMP_r_rm;
+ }
+ return SLJIT_SUCCESS;
+ }
+
+ if (FAST_IS_REG(src2) && src1 != SLJIT_IMM) {
+ inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = CMP_rm_r;
+ return SLJIT_SUCCESS;
+ }
+
+ if (src2 == SLJIT_IMM) {
+ if (src1 == SLJIT_IMM) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ src1 = TMP_REG1;
+ src1w = 0;
+ }
+ BINARY_IMM(CMP, CMP_rm_r, src2w, src1, src1w);
+ }
+ else {
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = CMP_r_rm;
+ }
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_test_binary(struct sljit_compiler *compiler,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_u8* inst;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (src1 == SLJIT_R0 && src2 == SLJIT_IMM && (src2w > 127 || src2w < -128) && (compiler->mode32 || IS_HALFWORD(src2w))) {
+#else
+ if (src1 == SLJIT_R0 && src2 == SLJIT_IMM && (src2w > 127 || src2w < -128)) {
+#endif
+ BINARY_EAX_IMM(TEST_EAX_i32, src2w);
+ return SLJIT_SUCCESS;
+ }
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (src2 == SLJIT_R0 && src1 == SLJIT_IMM && (src1w > 127 || src1w < -128) && (compiler->mode32 || IS_HALFWORD(src1w))) {
+#else
+ if (src2 == SLJIT_R0 && src1 == SLJIT_IMM && (src1w > 127 || src1w < -128)) {
+#endif
+ BINARY_EAX_IMM(TEST_EAX_i32, src1w);
+ return SLJIT_SUCCESS;
+ }
+
+ if (src1 != SLJIT_IMM) {
+ if (src2 == SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (IS_HALFWORD(src2w) || compiler->mode32) {
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = GROUP_F7;
+ } else {
+ FAIL_IF(emit_load_imm64(compiler, FAST_IS_REG(src1) ? TMP_REG2 : TMP_REG1, src2w));
+ inst = emit_x86_instruction(compiler, 1, FAST_IS_REG(src1) ? TMP_REG2 : TMP_REG1, 0, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = TEST_rm_r;
+ }
+#else
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = GROUP_F7;
+#endif
+ return SLJIT_SUCCESS;
+ }
+ else if (FAST_IS_REG(src1)) {
+ inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = TEST_rm_r;
+ return SLJIT_SUCCESS;
+ }
+ }
+
+ if (src2 != SLJIT_IMM) {
+ if (src1 == SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (IS_HALFWORD(src1w) || compiler->mode32) {
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = GROUP_F7;
+ }
+ else {
+ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, src1w));
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = TEST_rm_r;
+ }
+#else
+ inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = GROUP_F7;
+#endif
+ return SLJIT_SUCCESS;
+ }
+ else if (FAST_IS_REG(src2)) {
+ inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = TEST_rm_r;
+ return SLJIT_SUCCESS;
+ }
+ }
+
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ if (src2 == SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (IS_HALFWORD(src2w) || compiler->mode32) {
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REG1, 0);
+ FAIL_IF(!inst);
+ *inst = GROUP_F7;
+ }
+ else {
+ FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w));
+ inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, TMP_REG1, 0);
+ FAIL_IF(!inst);
+ *inst = TEST_rm_r;
+ }
+#else
+ inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, TMP_REG1, 0);
+ FAIL_IF(!inst);
+ *inst = GROUP_F7;
+#endif
+ }
+ else {
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
+ FAIL_IF(!inst);
+ *inst = TEST_rm_r;
+ }
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_shift(struct sljit_compiler *compiler,
+ sljit_u8 mode,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ sljit_s32 mode32;
+#endif
+ sljit_u8* inst;
+
+ if (src2 == SLJIT_IMM || src2 == SLJIT_PREF_SHIFT_REG) {
+ if (dst == src1 && dstw == src1w) {
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, dstw);
+ FAIL_IF(!inst);
+ inst[1] |= mode;
+ return SLJIT_SUCCESS;
+ }
+ if (dst == SLJIT_PREF_SHIFT_REG && src2 == SLJIT_PREF_SHIFT_REG) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
+ FAIL_IF(!inst);
+ inst[1] |= mode;
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
+ return SLJIT_SUCCESS;
+ }
+ if (FAST_IS_REG(dst)) {
+ EMIT_MOV(compiler, dst, 0, src1, src1w);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, dst, 0);
+ FAIL_IF(!inst);
+ inst[1] |= mode;
+ return SLJIT_SUCCESS;
+ }
+
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REG1, 0);
+ FAIL_IF(!inst);
+ inst[1] |= mode;
+ EMIT_MOV(compiler, dst, dstw, TMP_REG1, 0);
+ return SLJIT_SUCCESS;
+ }
+
+ if (dst == SLJIT_PREF_SHIFT_REG) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
+ FAIL_IF(!inst);
+ inst[1] |= mode;
+ return emit_mov(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
+ }
+
+ if (FAST_IS_REG(dst) && dst != src2 && dst != TMP_REG1 && !ADDRESSING_DEPENDS_ON(src2, dst)) {
+ if (src1 != dst)
+ EMIT_MOV(compiler, dst, 0, src1, src1w);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ mode32 = compiler->mode32;
+ compiler->mode32 = 0;
+#endif
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = mode32;
+#endif
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, dst, 0);
+ FAIL_IF(!inst);
+ inst[1] |= mode;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+#endif
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = mode32;
+#endif
+ return SLJIT_SUCCESS;
+ }
+
+ /* This case is complex since ecx itself may be used for
+ addressing, and this case must be supported as well. */
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0);
+#else /* !SLJIT_CONFIG_X86_32 */
+ mode32 = compiler->mode32;
+ compiler->mode32 = 0;
+ EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_PREF_SHIFT_REG, 0);
+ compiler->mode32 = mode32;
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src2, src2w);
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
+ FAIL_IF(!inst);
+ inst[1] |= mode;
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, SLJIT_MEM1(SLJIT_SP), 0);
+#else
+ compiler->mode32 = 0;
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);
+ compiler->mode32 = mode32;
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ if (dst != TMP_REG1)
+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_shift_with_flags(struct sljit_compiler *compiler,
+ sljit_u8 mode, sljit_s32 set_flags,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ /* The CPU does not set flags if the shift count is 0. */
+ if (src2 == SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ src2w &= compiler->mode32 ? 0x1f : 0x3f;
+#else /* !SLJIT_CONFIG_X86_64 */
+ src2w &= 0x1f;
+#endif /* SLJIT_CONFIG_X86_64 */
+ if (src2w != 0)
+ return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);
+
+ if (!set_flags)
+ return emit_mov(compiler, dst, dstw, src1, src1w);
+ /* OR dst, src, 0 */
+ return emit_cum_binary(compiler, BINARY_OPCODE(OR),
+ dst, dstw, src1, src1w, SLJIT_IMM, 0);
+ }
+
+ if (!set_flags)
+ return emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w);
+
+ if (!FAST_IS_REG(dst))
+ FAIL_IF(emit_cmp_binary(compiler, src1, src1w, SLJIT_IMM, 0));
+
+ FAIL_IF(emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w));
+
+ if (FAST_IS_REG(dst))
+ return emit_cmp_binary(compiler, dst, dstw, SLJIT_IMM, 0);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ CHECK_EXTRA_REGS(dst, dstw, (void)0);
+ CHECK_EXTRA_REGS(src1, src1w, (void)0);
+ CHECK_EXTRA_REGS(src2, src2w, (void)0);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = op & SLJIT_32;
+#endif
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD:
+ if (!HAS_FLAGS(op)) {
+ if (emit_lea_binary(compiler, dst, dstw, src1, src1w, src2, src2w) != SLJIT_ERR_UNSUPPORTED)
+ return compiler->error;
+ }
+ return emit_cum_binary(compiler, BINARY_OPCODE(ADD),
+ dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_ADDC:
+ return emit_cum_binary(compiler, BINARY_OPCODE(ADC),
+ dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_SUB:
+ if (src1 == SLJIT_IMM && src1w == 0)
+ return emit_unary(compiler, NEG_rm, dst, dstw, src2, src2w);
+
+ if (!HAS_FLAGS(op)) {
+ if (src2 == SLJIT_IMM && emit_lea_binary(compiler, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED)
+ return compiler->error;
+ if (FAST_IS_REG(dst) && src2 == dst) {
+ FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), dst, 0, dst, 0, src1, src1w));
+ return emit_unary(compiler, NEG_rm, dst, 0, dst, 0);
+ }
+ }
+
+ return emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
+ dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_SUBC:
+ return emit_non_cum_binary(compiler, BINARY_OPCODE(SBB),
+ dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_MUL:
+ return emit_mul(compiler, dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_AND:
+ return emit_cum_binary(compiler, BINARY_OPCODE(AND),
+ dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_OR:
+ return emit_cum_binary(compiler, BINARY_OPCODE(OR),
+ dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_XOR:
+ if (!HAS_FLAGS(op)) {
+ if (src2 == SLJIT_IMM && src2w == -1)
+ return emit_unary(compiler, NOT_rm, dst, dstw, src1, src1w);
+ if (src1 == SLJIT_IMM && src1w == -1)
+ return emit_unary(compiler, NOT_rm, dst, dstw, src2, src2w);
+ }
+
+ return emit_cum_binary(compiler, BINARY_OPCODE(XOR),
+ dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_SHL:
+ case SLJIT_MSHL:
+ return emit_shift_with_flags(compiler, SHL, HAS_FLAGS(op),
+ dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_LSHR:
+ case SLJIT_MLSHR:
+ return emit_shift_with_flags(compiler, SHR, HAS_FLAGS(op),
+ dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_ASHR:
+ case SLJIT_MASHR:
+ return emit_shift_with_flags(compiler, SAR, HAS_FLAGS(op),
+ dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_ROTL:
+ return emit_shift_with_flags(compiler, ROL, 0,
+ dst, dstw, src1, src1w, src2, src2w);
+ case SLJIT_ROTR:
+ return emit_shift_with_flags(compiler, ROR, 0,
+ dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 opcode = GET_OPCODE(op);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+ if (opcode != SLJIT_SUB && opcode != SLJIT_AND) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
+ }
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ CHECK_EXTRA_REGS(src1, src1w, (void)0);
+ CHECK_EXTRA_REGS(src2, src2w, (void)0);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = op & SLJIT_32;
+#endif
+
+ if (opcode == SLJIT_SUB)
+ return emit_cmp_binary(compiler, src1, src1w, src2, src2w);
+
+ return emit_test_binary(compiler, src1, src1w, src2, src2w);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_u8* inst;
+ sljit_sw dstw = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2r(compiler, op, dst_reg, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ CHECK_EXTRA_REGS(dst_reg, dstw, (void)0);
+ CHECK_EXTRA_REGS(src1, src1w, (void)0);
+ CHECK_EXTRA_REGS(src2, src2w, (void)0);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = op & SLJIT_32;
+#endif
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MULADD:
+ FAIL_IF(emit_mul(compiler, TMP_REG1, 0, src1, src1w, src2, src2w));
+ inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, dst_reg, dstw);
+ FAIL_IF(!inst);
+ *inst = ADD_rm_r;
+ return SLJIT_SUCCESS;
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 src1_reg,
+ sljit_s32 src2_reg,
+ sljit_s32 src3, sljit_sw src3w)
+{
+ sljit_s32 is_rotate, is_left, move_src1;
+ sljit_u8* inst;
+ sljit_sw src1w = 0;
+ sljit_sw dstw = 0;
+ /* The whole register must be saved even for 32 bit operations. */
+ sljit_u8 restore_ecx = 0;
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ sljit_sw src2w = 0;
+ sljit_s32 restore_sp4 = 0;
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_shift_into(compiler, op, dst_reg, src1_reg, src2_reg, src3, src3w));
+ ADJUST_LOCAL_OFFSET(src3, src3w);
+
+ CHECK_EXTRA_REGS(dst_reg, dstw, (void)0);
+ CHECK_EXTRA_REGS(src3, src3w, (void)0);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = op & SLJIT_32;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (src3 == SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ src3w &= 0x1f;
+#else /* !SLJIT_CONFIG_X86_32 */
+ src3w &= (op & SLJIT_32) ? 0x1f : 0x3f;
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ if (src3w == 0)
+ return SLJIT_SUCCESS;
+ }
+
+ is_left = (GET_OPCODE(op) == SLJIT_SHL || GET_OPCODE(op) == SLJIT_MSHL);
+
+ is_rotate = (src1_reg == src2_reg);
+ CHECK_EXTRA_REGS(src1_reg, src1w, (void)0);
+ CHECK_EXTRA_REGS(src2_reg, src2w, (void)0);
+
+ if (is_rotate)
+ return emit_shift(compiler, is_left ? ROL : ROR, dst_reg, dstw, src1_reg, src1w, src3, src3w);
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if (src2_reg & SLJIT_MEM) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src2_reg, src2w);
+ src2_reg = TMP_REG1;
+ }
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ if (dst_reg == SLJIT_PREF_SHIFT_REG && src3 != SLJIT_IMM && (src3 != SLJIT_PREF_SHIFT_REG || src1_reg != SLJIT_PREF_SHIFT_REG)) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ EMIT_MOV(compiler, TMP_REG1, 0, src1_reg, src1w);
+ src1_reg = TMP_REG1;
+ src1w = 0;
+#else /* !SLJIT_CONFIG_X86_64 */
+ if (src2_reg != TMP_REG1) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src1_reg, src1w);
+ src1_reg = TMP_REG1;
+ src1w = 0;
+ } else if ((src1_reg & SLJIT_MEM) || src1_reg == SLJIT_PREF_SHIFT_REG) {
+ restore_sp4 = (src3 == SLJIT_R0) ? SLJIT_R1 : SLJIT_R0;
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), restore_sp4, 0);
+ EMIT_MOV(compiler, restore_sp4, 0, src1_reg, src1w);
+ src1_reg = restore_sp4;
+ src1w = 0;
+ } else {
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), src1_reg, 0);
+ restore_sp4 = src1_reg;
+ }
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (src3 != SLJIT_PREF_SHIFT_REG)
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src3, src3w);
+ } else {
+ if (src2_reg == SLJIT_PREF_SHIFT_REG && src3 != SLJIT_IMM && src3 != SLJIT_PREF_SHIFT_REG) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+#endif /* SLJIT_CONFIG_X86_64 */
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = op & SLJIT_32;
+#endif /* SLJIT_CONFIG_X86_64 */
+ src2_reg = TMP_REG1;
+ restore_ecx = 1;
+ }
+
+ move_src1 = 0;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (dst_reg != src1_reg) {
+ if (dst_reg != src3) {
+ EMIT_MOV(compiler, dst_reg, 0, src1_reg, src1w);
+ src1_reg = dst_reg;
+ src1w = 0;
+ } else
+ move_src1 = 1;
+ }
+#else /* !SLJIT_CONFIG_X86_64 */
+ if (dst_reg & SLJIT_MEM) {
+ if (src2_reg != TMP_REG1) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src1_reg, src1w);
+ src1_reg = TMP_REG1;
+ src1w = 0;
+ } else if ((src1_reg & SLJIT_MEM) || src1_reg == SLJIT_PREF_SHIFT_REG) {
+ restore_sp4 = (src3 == SLJIT_R0) ? SLJIT_R1 : SLJIT_R0;
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), restore_sp4, 0);
+ EMIT_MOV(compiler, restore_sp4, 0, src1_reg, src1w);
+ src1_reg = restore_sp4;
+ src1w = 0;
+ } else {
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32), src1_reg, 0);
+ restore_sp4 = src1_reg;
+ }
+ } else if (dst_reg != src1_reg) {
+ if (dst_reg != src3) {
+ EMIT_MOV(compiler, dst_reg, 0, src1_reg, src1w);
+ src1_reg = dst_reg;
+ src1w = 0;
+ } else
+ move_src1 = 1;
+ }
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (src3 != SLJIT_IMM && src3 != SLJIT_PREF_SHIFT_REG) {
+ if (!restore_ecx) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0);
+ compiler->mode32 = op & SLJIT_32;
+ restore_ecx = 1;
+#else /* !SLJIT_CONFIG_X86_64 */
+ if (src1_reg != TMP_REG1 && src2_reg != TMP_REG1) {
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0);
+ restore_ecx = 1;
+ } else {
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_PREF_SHIFT_REG, 0);
+ restore_ecx = 2;
+ }
+#endif /* SLJIT_CONFIG_X86_64 */
+ }
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, src3, src3w);
+ }
+
+ if (move_src1) {
+ EMIT_MOV(compiler, dst_reg, 0, src1_reg, src1w);
+ src1_reg = dst_reg;
+ src1w = 0;
+ }
+ }
+
+ inst = emit_x86_instruction(compiler, 2, src2_reg, 0, src1_reg, src1w);
+ FAIL_IF(!inst);
+ inst[0] = GROUP_0F;
+
+ if (src3 == SLJIT_IMM) {
+ inst[1] = U8((is_left ? SHLD : SHRD) - 1);
+
+ /* Immediate argument is added separately. */
+ FAIL_IF(emit_byte(compiler, U8(src3w)));
+ } else
+ inst[1] = U8(is_left ? SHLD : SHRD);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (restore_ecx) {
+ compiler->mode32 = 0;
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
+ }
+
+ if (src1_reg != dst_reg) {
+ compiler->mode32 = op & SLJIT_32;
+ return emit_mov(compiler, dst_reg, dstw, src1_reg, 0);
+ }
+#else /* !SLJIT_CONFIG_X86_64 */
+ if (restore_ecx)
+ EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, restore_ecx == 1 ? TMP_REG1 : SLJIT_MEM1(SLJIT_SP), 0);
+
+ if (src1_reg != dst_reg)
+ EMIT_MOV(compiler, dst_reg, dstw, src1_reg, 0);
+
+ if (restore_sp4)
+ return emit_mov(compiler, restore_sp4, 0, SLJIT_MEM1(SLJIT_SP), sizeof(sljit_s32));
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r;
+ int use_lea = 0;
+ sljit_u8* inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);
+
+ if (src2 == SLJIT_IMM) {
+ src2w = (sljit_sw)((sljit_uw)src2w << shift_arg);
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ CHECK_EXTRA_REGS(dst, dstw, (void)0);
+ CHECK_EXTRA_REGS(src1, src1w, (void)0);
+ CHECK_EXTRA_REGS(src2, src2w, (void)0);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+#endif
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (shift_arg <= 3) {
+ use_lea = 1;
+ if (!FAST_IS_REG(src2)) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);
+ src2 = TMP_REG1;
+ }
+
+ if (!FAST_IS_REG(src1)) {
+ EMIT_MOV(compiler, src2 == TMP_REG1 ? TMP_REG2 : TMP_REG1, 0, src1, src1w);
+ src1 = src2 == TMP_REG1 ? TMP_REG2 : TMP_REG1;
+ }
+ }
+#else /* !SLJIT_CONFIG_X86_64 */
+ if (shift_arg <= 3 && (FAST_IS_REG(src1) || (FAST_IS_REG(src2) && src2 != TMP_REG1))) {
+ use_lea = 1;
+ if (!FAST_IS_REG(src2)) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);
+ src2 = TMP_REG1;
+ }
+
+ if (!FAST_IS_REG(src1)) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ src1 = TMP_REG1;
+ }
+ }
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (use_lea) {
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), shift_arg);
+ FAIL_IF(!inst);
+ *inst = LEA_r_m;
+
+ if (!FAST_IS_REG(dst))
+ return emit_mov(compiler, dst, dstw, dst_r, 0);
+
+ return SLJIT_SUCCESS;
+ }
+
+ if ((op & SLJIT_SRC2_UNDEFINED) != 0 && FAST_IS_REG(src2) && src1 != src2)
+ dst_r = src2;
+ else {
+ dst_r = FAST_IS_REG(dst) && (dst != src1) ? dst : TMP_REG1;
+
+ if (src2 != dst_r) {
+ EMIT_MOV(compiler, dst_r, 0, src2, src2w);
+ }
+ }
+
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, shift_arg, dst_r, 0);
+ FAIL_IF(!inst);
+ inst[1] |= SHL;
+
+ if (dst == src1 && dstw == src1w) {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = ADD_rm_r;
+ return SLJIT_SUCCESS;
+ }
+
+ if (FAST_IS_REG(dst) && FAST_IS_REG(src1)) {
+ inst = emit_x86_instruction(compiler, 1, dst, 0, SLJIT_MEM2(src1, dst_r), 0);
+ FAIL_IF(!inst);
+ *inst = LEA_r_m;
+ return SLJIT_SUCCESS;
+ }
+
+ if (src1 == SLJIT_IMM) {
+ BINARY_IMM(ADD, ADD_rm_r, src1w, dst_r, 0);
+ } else {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = ADD_r_rm;
+ }
+
+ if (dst != dst_r)
+ return emit_mov(compiler, dst, dstw, dst_r, 0);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ CHECK_EXTRA_REGS(src, srcw, (void)0);
+
+ switch (op) {
+ case SLJIT_FAST_RETURN:
+ return emit_fast_return(compiler, src, srcw);
+ case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
+ /* Don't adjust shadow stack if it isn't enabled. */
+ if (!cpu_has_shadow_stack ())
+ return SLJIT_SUCCESS;
+ return adjust_shadow_stack(compiler, src, srcw);
+ case SLJIT_PREFETCH_L1:
+ case SLJIT_PREFETCH_L2:
+ case SLJIT_PREFETCH_L3:
+ case SLJIT_PREFETCH_ONCE:
+ return emit_prefetch(compiler, op, src, srcw);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_dst(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ CHECK_EXTRA_REGS(dst, dstw, (void)0);
+
+ switch (op) {
+ case SLJIT_FAST_ENTER:
+ return emit_fast_enter(compiler, dst, dstw);
+ case SLJIT_GET_RETURN_ADDRESS:
+ return sljit_emit_get_return_address(compiler, dst, dstw);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 type, sljit_s32 reg)
+{
+ CHECK_REG_INDEX(check_sljit_get_register_index(type, reg));
+
+ if (type == SLJIT_GP_REGISTER) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if (reg >= SLJIT_R3 && reg <= SLJIT_R8)
+ return -1;
+#endif /* SLJIT_CONFIG_X86_32 */
+ return reg_map[reg];
+ }
+
+ if (type != SLJIT_FLOAT_REGISTER && type != SLJIT_SIMD_REG_128 && type != SLJIT_SIMD_REG_256 && type != SLJIT_SIMD_REG_512)
+ return -1;
+
+ return freg_map[reg];
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
+ void *instruction, sljit_u32 size)
+{
+ sljit_u8 *inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+ INC_SIZE(size);
+ SLJIT_MEMCPY(inst, instruction, size);
+ return SLJIT_SUCCESS;
+}
+
+/* --------------------------------------------------------------------- */
+/* Floating point operators */
+/* --------------------------------------------------------------------- */
+
+/* Alignment(3) + 4 * 16 bytes. */
+static sljit_u32 sse2_data[3 + (4 * 4)];
+static sljit_u32 *sse2_buffer;
+
+static void init_compiler(void)
+{
+ get_cpu_features();
+
+ /* Align to 16 bytes. */
+ sse2_buffer = (sljit_u32*)(((sljit_uw)sse2_data + 15) & ~(sljit_uw)0xf);
+
+ /* Single precision constants (each constant is 16 byte long). */
+ sse2_buffer[0] = 0x80000000;
+ sse2_buffer[4] = 0x7fffffff;
+ /* Double precision constants (each constant is 16 byte long). */
+ sse2_buffer[8] = 0;
+ sse2_buffer[9] = 0x80000000;
+ sse2_buffer[12] = 0xffffffff;
+ sse2_buffer[13] = 0x7fffffff;
+}
+
+static sljit_s32 emit_groupf(struct sljit_compiler *compiler,
+ sljit_uw op,
+ sljit_s32 dst, sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8 *inst = emit_x86_instruction(compiler, 2 | (op & ~(sljit_uw)0xff), dst, 0, src, srcw);
+ FAIL_IF(!inst);
+ inst[0] = GROUP_0F;
+ inst[1] = op & 0xff;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_groupf_ext(struct sljit_compiler *compiler,
+ sljit_uw op,
+ sljit_s32 dst, sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8 *inst;
+
+ SLJIT_ASSERT((op & EX86_SSE2) && ((op & VEX_OP_0F38) || (op & VEX_OP_0F3A)));
+
+ inst = emit_x86_instruction(compiler, 3 | (op & ~((sljit_uw)0xff | VEX_OP_0F38 | VEX_OP_0F3A)), dst, 0, src, srcw);
+ FAIL_IF(!inst);
+ inst[0] = GROUP_0F;
+ inst[1] = U8((op & VEX_OP_0F38) ? 0x38 : 0x3A);
+ inst[2] = op & 0xff;
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler,
+ sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw)
+{
+ return emit_groupf(compiler, MOVSD_x_xm | (single ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, dst, src, srcw);
+}
+
+static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler,
+ sljit_s32 single, sljit_s32 dst, sljit_sw dstw, sljit_s32 src)
+{
+ return emit_groupf(compiler, MOVSD_xm_x | (single ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, src, dst, dstw);
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r;
+
+ CHECK_EXTRA_REGS(dst, dstw, (void)0);
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)
+ compiler->mode32 = 0;
+#endif
+
+ FAIL_IF(emit_groupf(compiler, CVTTSD2SI_r_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP2, dst_r, src, srcw));
+
+ if (dst & SLJIT_MEM)
+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG;
+
+ CHECK_EXTRA_REGS(src, srcw, (void)0);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)
+ compiler->mode32 = 0;
+#endif
+
+ if (src == SLJIT_IMM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
+ srcw = (sljit_s32)srcw;
+#endif
+ EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
+ src = TMP_REG1;
+ srcw = 0;
+ }
+
+ FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, src, srcw));
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 1;
+#endif
+ if (dst_r == TMP_FREG)
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ switch (GET_FLAG_TYPE(op)) {
+ case SLJIT_ORDERED_EQUAL:
+ /* Also: SLJIT_UNORDERED_OR_NOT_EQUAL */
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));
+ FAIL_IF(emit_groupf(compiler, CMPS_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, TMP_FREG, src2, src2w));
+
+ /* EQ */
+ FAIL_IF(emit_byte(compiler, 0));
+
+ src1 = TMP_FREG;
+ src2 = TMP_FREG;
+ src2w = 0;
+ break;
+
+ case SLJIT_ORDERED_LESS:
+ case SLJIT_UNORDERED_OR_GREATER:
+ /* Also: SLJIT_UNORDERED_OR_GREATER_EQUAL, SLJIT_ORDERED_LESS_EQUAL */
+ if (!FAST_IS_REG(src2)) {
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src2, src2w));
+ src2 = TMP_FREG;
+ }
+
+ return emit_groupf(compiler, UCOMISD_x_xm | EX86_SELECT_66(op) | EX86_SSE2, src2, src1, src1w);
+ }
+
+ if (!FAST_IS_REG(src1)) {
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));
+ src1 = TMP_FREG;
+ }
+
+ return emit_groupf(compiler, UCOMISD_x_xm | EX86_SELECT_66(op) | EX86_SSE2, src1, src2, src2w);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r;
+ sljit_u8 *inst;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 1;
+#endif
+
+ CHECK_ERROR();
+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
+
+ if (GET_OPCODE(op) == SLJIT_MOV_F64) {
+ if (FAST_IS_REG(dst))
+ return emit_sse2_load(compiler, op & SLJIT_32, dst, src, srcw);
+ if (FAST_IS_REG(src))
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, src);
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src, srcw));
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
+ }
+
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) {
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG;
+ if (FAST_IS_REG(src)) {
+ /* We overwrite the high bits of source. From SLJIT point of view,
+ this is not an issue.
+ Note: In SSE3, we could also use MOVDDUP and MOVSLDUP. */
+ FAIL_IF(emit_groupf(compiler, UNPCKLPD_x_xm | ((op & SLJIT_32) ? EX86_PREF_66 : 0) | EX86_SSE2, src, src, 0));
+ } else {
+ FAIL_IF(emit_sse2_load(compiler, !(op & SLJIT_32), TMP_FREG, src, srcw));
+ src = TMP_FREG;
+ }
+
+ FAIL_IF(emit_groupf(compiler, CVTPD2PS_x_xm | ((op & SLJIT_32) ? EX86_PREF_66 : 0) | EX86_SSE2, dst_r, src, 0));
+ if (dst_r == TMP_FREG)
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
+ return SLJIT_SUCCESS;
+ }
+
+ if (FAST_IS_REG(dst)) {
+ dst_r = (dst == src) ? TMP_FREG : dst;
+
+ if (src & SLJIT_MEM)
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src, srcw));
+
+ FAIL_IF(emit_groupf(compiler, PCMPEQD_x_xm | EX86_PREF_66 | EX86_SSE2, dst_r, dst_r, 0));
+
+ inst = emit_x86_instruction(compiler, 2 | EX86_PREF_66 | EX86_SSE2_OP2, 0, 0, dst_r, 0);
+ inst[0] = GROUP_0F;
+ /* Same as PSRLD_x / PSRLQ_x */
+ inst[1] = (op & SLJIT_32) ? PSLLD_x_i8 : PSLLQ_x_i8;
+
+ if (GET_OPCODE(op) == SLJIT_ABS_F64) {
+ inst[2] |= 2 << 3;
+ FAIL_IF(emit_byte(compiler, 1));
+ } else {
+ inst[2] |= 6 << 3;
+ FAIL_IF(emit_byte(compiler, ((op & SLJIT_32) ? 31 : 63)));
+ }
+
+ if (dst_r != TMP_FREG)
+ dst_r = (src & SLJIT_MEM) ? TMP_FREG : src;
+ return emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_NEG_F64 ? XORPD_x_xm : ANDPD_x_xm) | EX86_SSE2, dst, dst_r, 0);
+ }
+
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src, srcw));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_NEG_F64:
+ FAIL_IF(emit_groupf(compiler, XORPD_x_xm | EX86_SELECT_66(op) | EX86_SSE2, TMP_FREG, SLJIT_MEM0(), (sljit_sw)((op & SLJIT_32) ? sse2_buffer : sse2_buffer + 8)));
+ break;
+
+ case SLJIT_ABS_F64:
+ FAIL_IF(emit_groupf(compiler, ANDPD_x_xm | EX86_SELECT_66(op) | EX86_SSE2, TMP_FREG, SLJIT_MEM0(), (sljit_sw)((op & SLJIT_32) ? sse2_buffer + 4 : sse2_buffer + 12)));
+ break;
+ }
+
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 dst_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 1;
+#endif
+
+ if (FAST_IS_REG(dst)) {
+ dst_r = dst;
+ if (dst == src1)
+ ; /* Do nothing here. */
+ else if (dst == src2 && (GET_OPCODE(op) == SLJIT_ADD_F64 || GET_OPCODE(op) == SLJIT_MUL_F64)) {
+ /* Swap arguments. */
+ src2 = src1;
+ src2w = src1w;
+ } else if (dst != src2)
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, dst_r, src1, src1w));
+ else {
+ dst_r = TMP_FREG;
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));
+ }
+ } else {
+ dst_r = TMP_FREG;
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD_F64:
+ FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, src2, src2w));
+ break;
+
+ case SLJIT_SUB_F64:
+ FAIL_IF(emit_groupf(compiler, SUBSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, src2, src2w));
+ break;
+
+ case SLJIT_MUL_F64:
+ FAIL_IF(emit_groupf(compiler, MULSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, src2, src2w));
+ break;
+
+ case SLJIT_DIV_F64:
+ FAIL_IF(emit_groupf(compiler, DIVSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, src2, src2w));
+ break;
+ }
+
+ if (dst_r != dst)
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2r(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_uw pref;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fop2r(compiler, op, dst_freg, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 1;
+#endif
+
+ if (dst_freg == src1) {
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src2, src2w));
+ pref = EX86_SELECT_66(op) | EX86_SSE2;
+ FAIL_IF(emit_groupf(compiler, XORPD_x_xm | pref, TMP_FREG, src1, src1w));
+ FAIL_IF(emit_groupf(compiler, ANDPD_x_xm | pref, TMP_FREG, SLJIT_MEM0(), (sljit_sw)((op & SLJIT_32) ? sse2_buffer : sse2_buffer + 8)));
+ return emit_groupf(compiler, XORPD_x_xm | pref, dst_freg, TMP_FREG, 0);
+ }
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));
+ src1 = TMP_FREG;
+ src1w = 0;
+ }
+
+ if (dst_freg != src2)
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, dst_freg, src2, src2w));
+
+ pref = EX86_SELECT_66(op) | EX86_SSE2;
+ FAIL_IF(emit_groupf(compiler, XORPD_x_xm | pref, dst_freg, src1, src1w));
+ FAIL_IF(emit_groupf(compiler, ANDPD_x_xm | pref, dst_freg, SLJIT_MEM0(), (sljit_sw)((op & SLJIT_32) ? sse2_buffer : sse2_buffer + 8)));
+ return emit_groupf(compiler, XORPD_x_xm | pref, dst_freg, src1, src1w);
+}
+
+/* --------------------------------------------------------------------- */
+/* Conditional instructions */
+/* --------------------------------------------------------------------- */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler)
+{
+ sljit_u8 *inst;
+ struct sljit_label *label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_label(compiler));
+
+ if (compiler->last_label && compiler->last_label->size == compiler->size)
+ return compiler->last_label;
+
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+ PTR_FAIL_IF(!label);
+ set_label(label, compiler);
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1);
+ PTR_FAIL_IF(!inst);
+ inst[0] = SLJIT_INST_LABEL;
+
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, size;
+ sljit_u8 *inst;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (alignment <= SLJIT_LABEL_ALIGN_1) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - 1;
+ compiler->size += mask;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1);
+ PTR_FAIL_IF(!inst);
+ inst[0] = SLJIT_INST_LABEL;
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+ size = buffers->size;
+
+ while (size >= 4) {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
+ PTR_FAIL_IF(!inst);
+ INC_SIZE(4);
+ inst[0] = NOP;
+ inst[1] = NOP;
+ inst[2] = NOP;
+ inst[3] = NOP;
+ size -= 4;
+ }
+
+ if (size > 0) {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ PTR_FAIL_IF(!inst);
+ INC_SIZE(size);
+
+ do {
+ *inst++ = NOP;
+ } while (--size != 0);
+ }
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
+{
+ sljit_u8 *inst;
+ struct sljit_jump *jump;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_jump(compiler, type));
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF_NULL(jump);
+ set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | ((type & 0xff) << TYPE_SHIFT)));
+ type &= 0xff;
+
+ jump->addr = compiler->size;
+ /* Worst case size. */
+ compiler->size += (type >= SLJIT_JUMP) ? JUMP_MAX_SIZE : CJUMP_MAX_SIZE;
+ inst = (sljit_u8*)ensure_buf(compiler, 1);
+ PTR_FAIL_IF_NULL(inst);
+
+ inst[0] = SLJIT_INST_JUMP;
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
+{
+ sljit_u8 *inst;
+ struct sljit_jump *jump;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ CHECK_EXTRA_REGS(src, srcw, (void)0);
+
+ if (src == SLJIT_IMM) {
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF_NULL(jump);
+ set_jump(jump, compiler, (sljit_u32)(JUMP_ADDR | (type << TYPE_SHIFT)));
+ jump->u.target = (sljit_uw)srcw;
+
+ jump->addr = compiler->size;
+ /* Worst case size. */
+ compiler->size += JUMP_MAX_SIZE;
+ inst = (sljit_u8*)ensure_buf(compiler, 1);
+ FAIL_IF_NULL(inst);
+
+ inst[0] = SLJIT_INST_JUMP;
+ } else {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ /* REX_W is not necessary (src is not immediate). */
+ compiler->mode32 = 1;
+#endif
+ inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
+ FAIL_IF(!inst);
+ inst[0] = GROUP_FF;
+ inst[1] = U8(inst[1] | ((type >= SLJIT_FAST_CALL) ? CALL_rm : JMP_rm));
+ }
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 type)
+{
+ sljit_u8 *inst;
+ sljit_u8 cond_set;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ sljit_s32 reg;
+ sljit_uw size;
+#endif /* !SLJIT_CONFIG_X86_64 */
+ /* ADJUST_LOCAL_OFFSET and CHECK_EXTRA_REGS might overwrite these values. */
+ sljit_s32 dst_save = dst;
+ sljit_sw dstw_save = dstw;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
+
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ CHECK_EXTRA_REGS(dst, dstw, (void)0);
+
+ /* setcc = jcc + 0x10. */
+ cond_set = U8(get_jump_code((sljit_uw)type) + 0x10);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst)) {
+ size = 3 + 2;
+ if (reg_map[TMP_REG1] >= 4)
+ size += 1 + 1;
+ else if (reg_map[dst] >= 4)
+ size++;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+ INC_SIZE(size);
+ /* Set low register to conditional flag. */
+ if (reg_map[TMP_REG1] >= 4)
+ *inst++ = (reg_map[TMP_REG1] <= 7) ? REX : REX_B;
+
+ inst[0] = GROUP_0F;
+ inst[1] = cond_set;
+ inst[2] = MOD_REG | reg_lmap[TMP_REG1];
+ inst += 3;
+
+ if (reg_map[TMP_REG1] >= 4 || reg_map[dst] >= 4)
+ *inst++ = U8(REX | (reg_map[TMP_REG1] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B));
+
+ inst[0] = OR_rm8_r8;
+ inst[1] = U8(MOD_REG | (reg_lmap[TMP_REG1] << 3) | reg_lmap[dst]);
+ return SLJIT_SUCCESS;
+ }
+
+ reg = (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG1;
+
+ size = 3 + (reg_map[reg] >= 4) + 4;
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+ INC_SIZE(size);
+ /* Set low register to conditional flag. */
+
+ if (reg_map[reg] >= 4)
+ *inst++ = (reg_map[reg] <= 7) ? REX : REX_B;
+
+ inst[0] = GROUP_0F;
+ inst[1] = cond_set;
+ inst[2] = MOD_REG | reg_lmap[reg];
+
+ inst[3] = REX_W | (reg_map[reg] <= 7 ? 0 : (REX_B | REX_R));
+ /* The movzx instruction does not affect flags. */
+ inst[4] = GROUP_0F;
+ inst[5] = MOVZX_r_rm8;
+ inst[6] = U8(MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg]);
+
+ if (reg != TMP_REG1)
+ return SLJIT_SUCCESS;
+
+ if (GET_OPCODE(op) < SLJIT_ADD) {
+ compiler->mode32 = GET_OPCODE(op) != SLJIT_MOV;
+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
+ }
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);
+
+#else /* !SLJIT_CONFIG_X86_64 */
+ SLJIT_ASSERT(reg_map[TMP_REG1] < 4);
+
+ /* The SLJIT_CONFIG_X86_32 code path starts here. */
+ if (GET_OPCODE(op) < SLJIT_ADD && FAST_IS_REG(dst) && reg_map[dst] <= 4) {
+ /* Low byte is accessible. */
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3 + 3);
+ FAIL_IF(!inst);
+ INC_SIZE(3 + 3);
+ /* Set low byte to conditional flag. */
+ inst[0] = GROUP_0F;
+ inst[1] = cond_set;
+ inst[2] = U8(MOD_REG | reg_map[dst]);
+
+ inst[3] = GROUP_0F;
+ inst[4] = MOVZX_r_rm8;
+ inst[5] = U8(MOD_REG | (reg_map[dst] << 3) | reg_map[dst]);
+ return SLJIT_SUCCESS;
+ }
+
+ if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst) && reg_map[dst] <= 4) {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(3 + 2);
+
+ /* Set low byte to conditional flag. */
+ inst[0] = GROUP_0F;
+ inst[1] = cond_set;
+ inst[2] = U8(MOD_REG | reg_map[TMP_REG1]);
+
+ inst[3] = OR_rm8_r8;
+ inst[4] = U8(MOD_REG | (reg_map[TMP_REG1] << 3) | reg_map[dst]);
+ return SLJIT_SUCCESS;
+ }
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 3 + 3);
+ FAIL_IF(!inst);
+ INC_SIZE(3 + 3);
+ /* Set low byte to conditional flag. */
+ inst[0] = GROUP_0F;
+ inst[1] = cond_set;
+ inst[2] = U8(MOD_REG | reg_map[TMP_REG1]);
+
+ inst[3] = GROUP_0F;
+ inst[4] = MOVZX_r_rm8;
+ inst[5] = U8(MOD_REG | (reg_map[TMP_REG1] << 3) | reg_map[TMP_REG1]);
+
+ if (GET_OPCODE(op) < SLJIT_ADD)
+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, op, dst_save, dstw_save, dst_save, dstw_save, TMP_REG1, 0);
+#endif /* SLJIT_CONFIG_X86_64 */
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_freg,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2_freg)
+{
+ sljit_u8* inst;
+ sljit_uw size;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_fselect(compiler, type, dst_freg, src1, src1w, src2_freg));
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 1;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (dst_freg != src2_freg) {
+ if (dst_freg == src1) {
+ src1 = src2_freg;
+ src1w = 0;
+ type ^= 0x1;
+ } else
+ FAIL_IF(emit_sse2_load(compiler, type & SLJIT_32, dst_freg, src2_freg, 0));
+ }
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+ INC_SIZE(2);
+ inst[0] = U8(get_jump_code((sljit_uw)(type & ~SLJIT_32) ^ 0x1) - 0x10);
+
+ size = compiler->size;
+ FAIL_IF(emit_sse2_load(compiler, type & SLJIT_32, dst_freg, src1, src1w));
+
+ inst[1] = U8(compiler->size - size);
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 alignment = SLJIT_SIMD_GET_ELEM2_SIZE(type);
+ sljit_uw op;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_mov(compiler, type, vreg, srcdst, srcdstw));
+
+ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 1;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ switch (reg_size) {
+ case 4:
+ op = EX86_SSE2;
+ break;
+ case 5:
+ if (!(cpu_feature_list & CPU_FEATURE_AVX2))
+ return SLJIT_ERR_UNSUPPORTED;
+ op = EX86_SSE2 | VEX_256;
+ break;
+ default:
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+
+ if (!(srcdst & SLJIT_MEM))
+ alignment = reg_size;
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (elem_size == 2 || elem_size == 3) {
+ op |= alignment >= reg_size ? MOVAPS_x_xm : MOVUPS_x_xm;
+
+ if (elem_size == 3)
+ op |= EX86_PREF_66;
+
+ if (type & SLJIT_SIMD_STORE)
+ op += 1;
+ } else
+ return SLJIT_ERR_UNSUPPORTED;
+ } else {
+ op |= ((type & SLJIT_SIMD_STORE) ? MOVDQA_xm_x : MOVDQA_x_xm)
+ | (alignment >= reg_size ? EX86_PREF_66 : EX86_PREF_F3);
+ }
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if ((op & VEX_256) || ((cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX)))
+ return emit_vex_instruction(compiler, op, vreg, 0, srcdst, srcdstw);
+
+ return emit_groupf(compiler, op, vreg, srcdst, srcdstw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 use_vex = (cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX);
+ sljit_u8 *inst;
+ sljit_u8 opcode = 0;
+ sljit_uw op;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_replicate(compiler, type, vreg, src, srcw));
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (!(type & SLJIT_SIMD_FLOAT)) {
+ CHECK_EXTRA_REGS(src, srcw, (void)0);
+ }
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : (elem_size > 2))
+ return SLJIT_ERR_UNSUPPORTED;
+#else /* !SLJIT_CONFIG_X86_32 */
+ compiler->mode32 = 1;
+
+ if (elem_size > 3 || ((type & SLJIT_SIMD_FLOAT) && elem_size < 2))
+ return SLJIT_ERR_UNSUPPORTED;
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ if (reg_size != 4 && (reg_size != 5 || !(cpu_feature_list & CPU_FEATURE_AVX2)))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (reg_size == 5)
+ use_vex = 1;
+
+ if (use_vex && src != SLJIT_IMM) {
+ op = 0;
+
+ switch (elem_size) {
+ case 0:
+ if (cpu_feature_list & CPU_FEATURE_AVX2)
+ op = VPBROADCASTB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;
+ break;
+ case 1:
+ if (cpu_feature_list & CPU_FEATURE_AVX2)
+ op = VPBROADCASTW_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;
+ break;
+ case 2:
+ if (type & SLJIT_SIMD_FLOAT) {
+ if ((cpu_feature_list & CPU_FEATURE_AVX2) || ((cpu_feature_list & CPU_FEATURE_AVX) && (src & SLJIT_MEM)))
+ op = VBROADCASTSS_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;
+ } else if (cpu_feature_list & CPU_FEATURE_AVX2)
+ op = VPBROADCASTD_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;
+ break;
+ default:
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (!(type & SLJIT_SIMD_FLOAT)) {
+ if (cpu_feature_list & CPU_FEATURE_AVX2)
+ op = VPBROADCASTQ_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;
+ break;
+ }
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (reg_size == 5)
+ op = VBROADCASTSD_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;
+ break;
+ }
+
+ if (op != 0) {
+ if (!(src & SLJIT_MEM) && !(type & SLJIT_SIMD_FLOAT)) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (elem_size >= 3)
+ compiler->mode32 = 0;
+#endif /* SLJIT_CONFIG_X86_64 */
+ FAIL_IF(emit_vex_instruction(compiler, MOVD_x_rm | VEX_AUTO_W | EX86_PREF_66 | EX86_SSE2_OP1, vreg, 0, src, srcw));
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 1;
+#endif /* SLJIT_CONFIG_X86_64 */
+ src = vreg;
+ srcw = 0;
+ }
+
+ if (reg_size == 5)
+ op |= VEX_256;
+
+ return emit_vex_instruction(compiler, op, vreg, 0, src, srcw);
+ }
+ }
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (src == SLJIT_IMM) {
+ if (use_vex)
+ return emit_vex_instruction(compiler, XORPD_x_xm | (reg_size == 5 ? VEX_256 : 0) | (elem_size == 3 ? EX86_PREF_66 : 0) | EX86_SSE2 | VEX_SSE2_OPV, vreg, vreg, vreg, 0);
+
+ return emit_groupf(compiler, XORPD_x_xm | (elem_size == 3 ? EX86_PREF_66 : 0) | EX86_SSE2, vreg, vreg, 0);
+ }
+
+ SLJIT_ASSERT(reg_size == 4);
+
+ if (use_vex) {
+ if (elem_size == 3)
+ return emit_vex_instruction(compiler, MOVDDUP_x_xm | EX86_PREF_F2 | EX86_SSE2, vreg, 0, src, srcw);
+
+ SLJIT_ASSERT(!(src & SLJIT_MEM));
+ FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | EX86_SSE2 | VEX_SSE2_OPV, vreg, src, src, 0));
+ return emit_byte(compiler, 0);
+ }
+
+ if (elem_size == 2 && vreg != src) {
+ FAIL_IF(emit_sse2_load(compiler, 1, vreg, src, srcw));
+ src = vreg;
+ srcw = 0;
+ }
+
+ op = (elem_size == 2 ? SHUFPS_x_xm : MOVDDUP_x_xm) | (elem_size == 2 ? 0 : EX86_PREF_F2) | EX86_SSE2;
+ FAIL_IF(emit_groupf(compiler, op, vreg, src, srcw));
+
+ if (elem_size == 2)
+ return emit_byte(compiler, 0);
+ return SLJIT_SUCCESS;
+ }
+
+ if (src == SLJIT_IMM) {
+ if (elem_size == 0) {
+ srcw = (sljit_u8)srcw;
+ srcw |= srcw << 8;
+ srcw |= srcw << 16;
+ elem_size = 2;
+ } else if (elem_size == 1) {
+ srcw = (sljit_u16)srcw;
+ srcw |= srcw << 16;
+ elem_size = 2;
+ }
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (elem_size == 2 && (sljit_s32)srcw == -1)
+ srcw = -1;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (srcw == 0 || srcw == -1) {
+ if (use_vex)
+ return emit_vex_instruction(compiler, (srcw == 0 ? PXOR_x_xm : PCMPEQD_x_xm) | (reg_size == 5 ? VEX_256 : 0) | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, vreg, vreg, vreg, 0);
+
+ return emit_groupf(compiler, (srcw == 0 ? PXOR_x_xm : PCMPEQD_x_xm) | EX86_PREF_66 | EX86_SSE2, vreg, vreg, 0);
+ }
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (elem_size == 3)
+ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, srcw));
+ else
+#endif /* SLJIT_CONFIG_X86_64 */
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw);
+
+ src = TMP_REG1;
+ srcw = 0;
+
+ }
+
+ op = 2;
+ opcode = MOVD_x_rm;
+
+ switch (elem_size) {
+ case 0:
+ if (!FAST_IS_REG(src)) {
+ opcode = 0x3a /* Prefix of PINSRB_x_rm_i8. */;
+ op = 3;
+ }
+ break;
+ case 1:
+ if (!FAST_IS_REG(src))
+ opcode = PINSRW_x_rm_i8;
+ break;
+ case 2:
+ break;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ case 3:
+ /* MOVQ */
+ compiler->mode32 = 0;
+ break;
+#endif /* SLJIT_CONFIG_X86_64 */
+ }
+
+ if (use_vex) {
+ if (opcode != MOVD_x_rm) {
+ op = (opcode == 0x3a) ? (PINSRB_x_rm_i8 | VEX_OP_0F3A) : opcode;
+ FAIL_IF(emit_vex_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2_OP1 | VEX_SSE2_OPV, vreg, vreg, src, srcw));
+ } else
+ FAIL_IF(emit_vex_instruction(compiler, MOVD_x_rm | VEX_AUTO_W | EX86_PREF_66 | EX86_SSE2_OP1, vreg, 0, src, srcw));
+ } else {
+ inst = emit_x86_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2_OP1, vreg, 0, src, srcw);
+ FAIL_IF(!inst);
+ inst[0] = GROUP_0F;
+ inst[1] = opcode;
+
+ if (op == 3) {
+ SLJIT_ASSERT(opcode == 0x3a);
+ inst[2] = PINSRB_x_rm_i8;
+ }
+ }
+
+ if ((cpu_feature_list & CPU_FEATURE_AVX2) && use_vex && elem_size >= 2) {
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ op = VPBROADCASTD_x_xm;
+#else /* !SLJIT_CONFIG_X86_32 */
+ op = (elem_size == 3) ? VPBROADCASTQ_x_xm : VPBROADCASTD_x_xm;
+#endif /* SLJIT_CONFIG_X86_32 */
+ return emit_vex_instruction(compiler, op | ((reg_size == 5) ? VEX_256 : 0) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, vreg, 0);
+ }
+
+ SLJIT_ASSERT(reg_size == 4);
+
+ if (opcode != MOVD_x_rm)
+ FAIL_IF(emit_byte(compiler, 0));
+
+ switch (elem_size) {
+ case 0:
+ if (use_vex) {
+ FAIL_IF(emit_vex_instruction(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, TMP_FREG, TMP_FREG, 0));
+ return emit_vex_instruction(compiler, PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2 | VEX_SSE2_OPV, vreg, vreg, TMP_FREG, 0);
+ }
+ FAIL_IF(emit_groupf(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2, TMP_FREG, TMP_FREG, 0));
+ return emit_groupf_ext(compiler, PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, TMP_FREG, 0);
+ case 1:
+ if (use_vex)
+ FAIL_IF(emit_vex_instruction(compiler, PSHUFLW_x_xm | EX86_PREF_F2 | EX86_SSE2, vreg, 0, vreg, 0));
+ else
+ FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | EX86_PREF_F2 | EX86_SSE2, vreg, vreg, 0));
+ FAIL_IF(emit_byte(compiler, 0));
+ SLJIT_FALLTHROUGH
+ default:
+ if (use_vex)
+ FAIL_IF(emit_vex_instruction(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, 0, vreg, 0));
+ else
+ FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, vreg, 0));
+ return emit_byte(compiler, 0);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ case 3:
+ compiler->mode32 = 1;
+ if (use_vex)
+ FAIL_IF(emit_vex_instruction(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, 0, vreg, 0));
+ else
+ FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, vreg, 0));
+ return emit_byte(compiler, 0x44);
+#endif /* SLJIT_CONFIG_X86_64 */
+ }
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg, sljit_s32 lane_index,
+ sljit_s32 srcdst, sljit_sw srcdstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 use_vex = (cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX);
+ sljit_u8 *inst;
+ sljit_u8 opcode = 0;
+ sljit_uw op;
+ sljit_s32 vreg_orig = vreg;
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ sljit_s32 srcdst_is_ereg = 0;
+ sljit_s32 srcdst_orig = 0;
+ sljit_sw srcdstw_orig = 0;
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_mov(compiler, type, vreg, lane_index, srcdst, srcdstw));
+
+ ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
+
+ if (reg_size == 5) {
+ if (!(cpu_feature_list & CPU_FEATURE_AVX2))
+ return SLJIT_ERR_UNSUPPORTED;
+ use_vex = 1;
+ } else if (reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if ((type & SLJIT_SIMD_FLOAT) ? (elem_size < 2 || elem_size > 3) : elem_size > 2)
+ return SLJIT_ERR_UNSUPPORTED;
+#else /* SLJIT_CONFIG_X86_32 */
+ if (elem_size > 3 || ((type & SLJIT_SIMD_FLOAT) && elem_size < 2))
+ return SLJIT_ERR_UNSUPPORTED;
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 1;
+#else /* !SLJIT_CONFIG_X86_64 */
+ if (!(type & SLJIT_SIMD_FLOAT)) {
+ CHECK_EXTRA_REGS(srcdst, srcdstw, srcdst_is_ereg = 1);
+
+ if ((type & SLJIT_SIMD_STORE) && ((srcdst_is_ereg && elem_size < 2) || (elem_size == 0 && (type & SLJIT_SIMD_LANE_SIGNED) && FAST_IS_REG(srcdst) && reg_map[srcdst] >= 4))) {
+ srcdst_orig = srcdst;
+ srcdstw_orig = srcdstw;
+ srcdst = TMP_REG1;
+ srcdstw = 0;
+ }
+ }
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (type & SLJIT_SIMD_LANE_ZERO) {
+ if (lane_index == 0) {
+ if (!(type & SLJIT_SIMD_FLOAT)) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (elem_size == 3) {
+ compiler->mode32 = 0;
+ elem_size = 2;
+ }
+#endif /* SLJIT_CONFIG_X86_64 */
+ if (srcdst == SLJIT_IMM) {
+ if (elem_size == 0)
+ srcdstw = (sljit_u8)srcdstw;
+ else if (elem_size == 1)
+ srcdstw = (sljit_u16)srcdstw;
+
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcdstw);
+ srcdst = TMP_REG1;
+ srcdstw = 0;
+ elem_size = 2;
+ }
+
+ if (elem_size == 2) {
+ if (use_vex)
+ return emit_vex_instruction(compiler, MOVD_x_rm | VEX_AUTO_W | EX86_PREF_66 | EX86_SSE2_OP1, vreg, 0, srcdst, srcdstw);
+ return emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, vreg, srcdst, srcdstw);
+ }
+ } else if (srcdst & SLJIT_MEM) {
+ SLJIT_ASSERT(elem_size == 2 || elem_size == 3);
+
+ if (use_vex)
+ return emit_vex_instruction(compiler, MOVSD_x_xm | (elem_size == 2 ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, vreg, 0, srcdst, srcdstw);
+ return emit_groupf(compiler, MOVSD_x_xm | (elem_size == 2 ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2, vreg, srcdst, srcdstw);
+ } else if (elem_size == 3) {
+ if (use_vex)
+ return emit_vex_instruction(compiler, MOVQ_x_xm | EX86_PREF_F3 | EX86_SSE2, vreg, 0, srcdst, 0);
+ return emit_groupf(compiler, MOVQ_x_xm | EX86_PREF_F3 | EX86_SSE2, vreg, srcdst, 0);
+ } else if (use_vex) {
+ FAIL_IF(emit_vex_instruction(compiler, XORPD_x_xm | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, TMP_FREG, TMP_FREG, 0));
+ return emit_vex_instruction(compiler, MOVSD_x_xm | EX86_PREF_F3 | EX86_SSE2 | VEX_SSE2_OPV, vreg, TMP_FREG, srcdst, 0);
+ }
+ }
+
+ if (reg_size == 5 && lane_index >= (1 << (4 - elem_size))) {
+ vreg = TMP_FREG;
+ lane_index -= (1 << (4 - elem_size));
+ } else if ((type & SLJIT_SIMD_FLOAT) && vreg == srcdst) {
+ if (use_vex)
+ FAIL_IF(emit_vex_instruction(compiler, MOVSD_x_xm | (elem_size == 2 ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, TMP_FREG, srcdst, srcdstw));
+ else
+ FAIL_IF(emit_sse2_load(compiler, elem_size == 2, TMP_FREG, srcdst, srcdstw));
+ srcdst = TMP_FREG;
+ srcdstw = 0;
+ }
+
+ op = ((!(type & SLJIT_SIMD_FLOAT) || elem_size != 2) ? EX86_PREF_66 : 0)
+ | ((type & SLJIT_SIMD_FLOAT) ? XORPD_x_xm : PXOR_x_xm) | EX86_SSE2;
+
+ if (use_vex)
+ FAIL_IF(emit_vex_instruction(compiler, op | (reg_size == 5 ? VEX_256 : 0) | VEX_SSE2_OPV, vreg, vreg, vreg, 0));
+ else
+ FAIL_IF(emit_groupf(compiler, op, vreg, vreg, 0));
+ } else if (reg_size == 5 && lane_index >= (1 << (4 - elem_size))) {
+ FAIL_IF(emit_vex_instruction(compiler, ((type & SLJIT_SIMD_FLOAT) ? VEXTRACTF128_x_ym : VEXTRACTI128_x_ym) | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, vreg, 0, TMP_FREG, 0));
+ FAIL_IF(emit_byte(compiler, 1));
+
+ vreg = TMP_FREG;
+ lane_index -= (1 << (4 - elem_size));
+ }
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (elem_size == 3) {
+ if (srcdst & SLJIT_MEM) {
+ if (type & SLJIT_SIMD_STORE)
+ op = lane_index == 0 ? MOVLPD_m_x : MOVHPD_m_x;
+ else
+ op = lane_index == 0 ? MOVLPD_x_m : MOVHPD_x_m;
+
+ /* VEX prefix clears upper bits of the target register. */
+ if (use_vex && ((type & SLJIT_SIMD_STORE) || reg_size == 4 || vreg == TMP_FREG))
+ FAIL_IF(emit_vex_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2
+ | ((type & SLJIT_SIMD_STORE) ? 0 : VEX_SSE2_OPV), vreg, (type & SLJIT_SIMD_STORE) ? 0 : vreg, srcdst, srcdstw));
+ else
+ FAIL_IF(emit_groupf(compiler, op | EX86_PREF_66 | EX86_SSE2, vreg, srcdst, srcdstw));
+
+ /* In case of store, vreg is not TMP_FREG. */
+ } else if (type & SLJIT_SIMD_STORE) {
+ if (lane_index == 1) {
+ if (use_vex)
+ return emit_vex_instruction(compiler, MOVHLPS_x_x | EX86_SSE2 | VEX_SSE2_OPV, srcdst, srcdst, vreg, 0);
+ return emit_groupf(compiler, MOVHLPS_x_x | EX86_SSE2, srcdst, vreg, 0);
+ }
+ if (use_vex)
+ return emit_vex_instruction(compiler, MOVSD_x_xm | EX86_PREF_F2 | EX86_SSE2 | VEX_SSE2_OPV, srcdst, srcdst, vreg, 0);
+ return emit_sse2_load(compiler, 0, srcdst, vreg, 0);
+ } else if (use_vex && (reg_size == 4 || vreg == TMP_FREG)) {
+ if (lane_index == 1)
+ FAIL_IF(emit_vex_instruction(compiler, MOVLHPS_x_x | EX86_SSE2 | VEX_SSE2_OPV, vreg, vreg, srcdst, 0));
+ else
+ FAIL_IF(emit_vex_instruction(compiler, MOVSD_x_xm | EX86_PREF_F2 | EX86_SSE2 | VEX_SSE2_OPV, vreg, vreg, srcdst, 0));
+ } else {
+ if (lane_index == 1)
+ FAIL_IF(emit_groupf(compiler, MOVLHPS_x_x | EX86_SSE2, vreg, srcdst, 0));
+ else
+ FAIL_IF(emit_sse2_load(compiler, 0, vreg, srcdst, 0));
+ }
+ } else if (type & SLJIT_SIMD_STORE) {
+ if (lane_index == 0) {
+ if (use_vex)
+ return emit_vex_instruction(compiler, MOVSD_xm_x | EX86_PREF_F3 | EX86_SSE2 | ((srcdst & SLJIT_MEM) ? 0 : VEX_SSE2_OPV),
+ vreg, ((srcdst & SLJIT_MEM) ? 0 : srcdst), srcdst, srcdstw);
+ return emit_sse2_store(compiler, 1, srcdst, srcdstw, vreg);
+ }
+
+ if (srcdst & SLJIT_MEM) {
+ if (use_vex)
+ FAIL_IF(emit_vex_instruction(compiler, EXTRACTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, vreg, 0, srcdst, srcdstw));
+ else
+ FAIL_IF(emit_groupf_ext(compiler, EXTRACTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, vreg, srcdst, srcdstw));
+ return emit_byte(compiler, U8(lane_index));
+ }
+
+ if (use_vex) {
+ FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | EX86_SSE2 | VEX_SSE2_OPV, srcdst, vreg, vreg, 0));
+ return emit_byte(compiler, U8(lane_index));
+ }
+
+ if (srcdst == vreg)
+ op = SHUFPS_x_xm | EX86_SSE2;
+ else {
+ switch (lane_index) {
+ case 1:
+ op = MOVSHDUP_x_xm | EX86_PREF_F3 | EX86_SSE2;
+ break;
+ case 2:
+ op = MOVHLPS_x_x | EX86_SSE2;
+ break;
+ default:
+ SLJIT_ASSERT(lane_index == 3);
+ op = PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2;
+ break;
+ }
+ }
+
+ FAIL_IF(emit_groupf(compiler, op, srcdst, vreg, 0));
+
+ op &= 0xff;
+ if (op == SHUFPS_x_xm || op == PSHUFD_x_xm)
+ return emit_byte(compiler, U8(lane_index));
+
+ return SLJIT_SUCCESS;
+ } else {
+ if (lane_index != 0 || (srcdst & SLJIT_MEM)) {
+ FAIL_IF(emit_groupf_ext(compiler, INSERTPS_x_xm | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, vreg, srcdst, srcdstw));
+ FAIL_IF(emit_byte(compiler, U8(lane_index << 4)));
+ } else
+ FAIL_IF(emit_sse2_store(compiler, 1, vreg, 0, srcdst));
+ }
+
+ if (vreg != TMP_FREG || (type & SLJIT_SIMD_STORE))
+ return SLJIT_SUCCESS;
+
+ SLJIT_ASSERT(reg_size == 5);
+
+ if (type & SLJIT_SIMD_LANE_ZERO) {
+ FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg_orig, 0, TMP_FREG, 0));
+ return emit_byte(compiler, 0x4e);
+ }
+
+ FAIL_IF(emit_vex_instruction(compiler, VINSERTF128_y_y_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2 | VEX_SSE2_OPV, vreg_orig, vreg_orig, TMP_FREG, 0));
+ return emit_byte(compiler, 1);
+ }
+
+ if (srcdst == SLJIT_IMM) {
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcdstw);
+ srcdst = TMP_REG1;
+ srcdstw = 0;
+ }
+
+ op = 3;
+
+ switch (elem_size) {
+ case 0:
+ opcode = (type & SLJIT_SIMD_STORE) ? PEXTRB_rm_x_i8 : PINSRB_x_rm_i8;
+ break;
+ case 1:
+ if (!(type & SLJIT_SIMD_STORE)) {
+ op = 2;
+ opcode = PINSRW_x_rm_i8;
+ } else
+ opcode = PEXTRW_rm_x_i8;
+ break;
+ case 2:
+ opcode = (type & SLJIT_SIMD_STORE) ? PEXTRD_rm_x_i8 : PINSRD_x_rm_i8;
+ break;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ case 3:
+ /* PINSRQ / PEXTRQ */
+ opcode = (type & SLJIT_SIMD_STORE) ? PEXTRD_rm_x_i8 : PINSRD_x_rm_i8;
+ compiler->mode32 = 0;
+ break;
+#endif /* SLJIT_CONFIG_X86_64 */
+ }
+
+ if (use_vex && (type & SLJIT_SIMD_STORE)) {
+ op = opcode | ((op == 3) ? VEX_OP_0F3A : 0);
+ FAIL_IF(emit_vex_instruction(compiler, op | EX86_PREF_66 | VEX_AUTO_W | EX86_SSE2_OP1 | VEX_SSE2_OPV, vreg, 0, srcdst, srcdstw));
+ } else {
+ inst = emit_x86_instruction(compiler, op | EX86_PREF_66 | EX86_SSE2_OP1, vreg, 0, srcdst, srcdstw);
+ FAIL_IF(!inst);
+ inst[0] = GROUP_0F;
+
+ if (op == 3) {
+ inst[1] = 0x3a;
+ inst[2] = opcode;
+ } else
+ inst[1] = opcode;
+ }
+
+ FAIL_IF(emit_byte(compiler, U8(lane_index)));
+
+ if (!(type & SLJIT_SIMD_LANE_SIGNED) || (srcdst & SLJIT_MEM)) {
+ if (vreg == TMP_FREG && !(type & SLJIT_SIMD_STORE)) {
+ SLJIT_ASSERT(reg_size == 5);
+
+ if (type & SLJIT_SIMD_LANE_ZERO) {
+ FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg_orig, 0, TMP_FREG, 0));
+ return emit_byte(compiler, 0x4e);
+ }
+
+ FAIL_IF(emit_vex_instruction(compiler, VINSERTI128_y_y_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2 | VEX_SSE2_OPV, vreg_orig, vreg_orig, TMP_FREG, 0));
+ return emit_byte(compiler, 1);
+ }
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if (srcdst_orig & SLJIT_MEM)
+ return emit_mov(compiler, srcdst_orig, srcdstw_orig, TMP_REG1, 0);
+#endif /* SLJIT_CONFIG_X86_32 */
+ return SLJIT_SUCCESS;
+ }
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (elem_size >= 3)
+ return SLJIT_SUCCESS;
+
+ compiler->mode32 = (type & SLJIT_32);
+
+ op = 2;
+
+ if (elem_size == 0)
+ op |= EX86_REX;
+
+ if (elem_size == 2) {
+ if (type & SLJIT_32)
+ return SLJIT_SUCCESS;
+
+ SLJIT_ASSERT(!(compiler->mode32));
+ op = 1;
+ }
+
+ inst = emit_x86_instruction(compiler, op, srcdst, 0, srcdst, 0);
+ FAIL_IF(!inst);
+
+ if (op != 1) {
+ inst[0] = GROUP_0F;
+ inst[1] = U8((elem_size == 0) ? MOVSX_r_rm8 : MOVSX_r_rm16);
+ } else
+ inst[0] = MOVSXD_r_rm;
+#else /* !SLJIT_CONFIG_X86_64 */
+ if (elem_size >= 2)
+ return SLJIT_SUCCESS;
+
+ FAIL_IF(emit_groupf(compiler, (elem_size == 0) ? MOVSX_r_rm8 : MOVSX_r_rm16,
+ (srcdst_orig != 0 && FAST_IS_REG(srcdst_orig)) ? srcdst_orig : srcdst, srcdst, 0));
+
+ if (srcdst_orig & SLJIT_MEM)
+ return emit_mov(compiler, srcdst_orig, srcdstw_orig, TMP_REG1, 0);
+#endif /* SLJIT_CONFIG_X86_64 */
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_s32 src_lane_index)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 use_vex = (cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX);
+ sljit_uw pref;
+ sljit_u8 byte;
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ sljit_s32 opcode3 = TMP_REG1;
+#else /* !SLJIT_CONFIG_X86_32 */
+ sljit_s32 opcode3 = SLJIT_S0;
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index));
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 1;
+#endif /* SLJIT_CONFIG_X86_64 */
+ SLJIT_ASSERT(reg_map[opcode3] == 3);
+
+ if (reg_size == 5) {
+ if (!(cpu_feature_list & CPU_FEATURE_AVX2))
+ return SLJIT_ERR_UNSUPPORTED;
+ use_vex = 1;
+ } else if (reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ pref = 0;
+ byte = U8(src_lane_index);
+
+ if (elem_size == 3) {
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (reg_size == 5) {
+ if (src_lane_index == 0)
+ return emit_vex_instruction(compiler, VBROADCASTSD_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, src, 0);
+
+ FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg, 0, src, 0));
+
+ byte = U8(byte | (byte << 2));
+ return emit_byte(compiler, U8(byte | (byte << 4)));
+ }
+
+ if (src_lane_index == 0) {
+ if (use_vex)
+ return emit_vex_instruction(compiler, MOVDDUP_x_xm | EX86_PREF_F2 | EX86_SSE2, vreg, 0, src, 0);
+ return emit_groupf(compiler, MOVDDUP_x_xm | EX86_PREF_F2 | EX86_SSE2, vreg, src, 0);
+ }
+
+ /* Changes it to SHUFPD_x_xm. */
+ pref = EX86_PREF_66;
+ } else if (elem_size != 2)
+ return SLJIT_ERR_UNSUPPORTED;
+ else if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (reg_size == 5) {
+ SLJIT_ASSERT(elem_size == 2);
+
+ if (src_lane_index == 0)
+ return emit_vex_instruction(compiler, VBROADCASTSS_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, src, 0);
+
+ FAIL_IF(emit_vex_instruction(compiler, VPERMPD_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg, 0, src, 0));
+
+ byte = 0x44;
+ if (src_lane_index >= 4) {
+ byte = 0xee;
+ src_lane_index -= 4;
+ }
+
+ FAIL_IF(emit_byte(compiler, byte));
+ FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | VEX_256 | pref | EX86_SSE2 | VEX_SSE2_OPV, vreg, vreg, vreg, 0));
+ byte = U8(src_lane_index);
+ } else if (use_vex) {
+ FAIL_IF(emit_vex_instruction(compiler, SHUFPS_x_xm | pref | EX86_SSE2 | VEX_SSE2_OPV, vreg, src, src, 0));
+ } else {
+ if (vreg != src)
+ FAIL_IF(emit_groupf(compiler, MOVAPS_x_xm | pref | EX86_SSE2, vreg, src, 0));
+
+ FAIL_IF(emit_groupf(compiler, SHUFPS_x_xm | pref | EX86_SSE2, vreg, vreg, 0));
+ }
+
+ if (elem_size == 2) {
+ byte = U8(byte | (byte << 2));
+ byte = U8(byte | (byte << 4));
+ } else
+ byte = U8(byte | (byte << 1));
+
+ return emit_byte(compiler, U8(byte));
+ }
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (elem_size == 0) {
+ if (reg_size == 5 && src_lane_index >= 16) {
+ FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg, 0, src, 0));
+ FAIL_IF(emit_byte(compiler, src_lane_index >= 24 ? 0xff : 0xaa));
+ src_lane_index &= 0x7;
+ src = vreg;
+ }
+
+ if (src_lane_index != 0 || (vreg != src && (!(cpu_feature_list & CPU_FEATURE_AVX2) || !use_vex))) {
+ pref = 0;
+
+ if ((src_lane_index & 0x3) == 0) {
+ pref = EX86_PREF_66;
+ byte = U8(src_lane_index >> 2);
+ } else if (src_lane_index < 8 && (src_lane_index & 0x1) == 0) {
+ pref = EX86_PREF_F2;
+ byte = U8(src_lane_index >> 1);
+ } else {
+ if (!use_vex) {
+ if (vreg != src)
+ FAIL_IF(emit_groupf(compiler, MOVDQA_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, src, 0));
+
+ FAIL_IF(emit_groupf(compiler, PSRLDQ_x | EX86_PREF_66 | EX86_SSE2_OP2, opcode3, vreg, 0));
+ } else
+ FAIL_IF(emit_vex_instruction(compiler, PSRLDQ_x | EX86_PREF_66 | EX86_SSE2_OP2 | VEX_SSE2_OPV, opcode3, vreg, src, 0));
+
+ FAIL_IF(emit_byte(compiler, U8(src_lane_index)));
+ }
+
+ if (pref != 0) {
+ if (use_vex)
+ FAIL_IF(emit_vex_instruction(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, vreg, 0, src, 0));
+ else
+ FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, vreg, src, 0));
+ FAIL_IF(emit_byte(compiler, byte));
+ }
+
+ src = vreg;
+ }
+
+ if (use_vex && (cpu_feature_list & CPU_FEATURE_AVX2))
+ return emit_vex_instruction(compiler, VPBROADCASTB_x_xm | (reg_size == 5 ? VEX_256 : 0) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, src, 0);
+
+ SLJIT_ASSERT(reg_size == 4);
+ FAIL_IF(emit_groupf(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2, TMP_FREG, TMP_FREG, 0));
+ return emit_groupf_ext(compiler, PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, TMP_FREG, 0);
+ }
+
+ if ((cpu_feature_list & CPU_FEATURE_AVX2) && use_vex && src_lane_index == 0 && elem_size <= 3) {
+ switch (elem_size) {
+ case 1:
+ pref = VPBROADCASTW_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;
+ break;
+ case 2:
+ pref = VPBROADCASTD_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;
+ break;
+ default:
+ pref = VPBROADCASTQ_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2;
+ break;
+ }
+
+ if (reg_size == 5)
+ pref |= VEX_256;
+
+ return emit_vex_instruction(compiler, pref, vreg, 0, src, 0);
+ }
+
+ if (reg_size == 5) {
+ switch (elem_size) {
+ case 1:
+ byte = U8(src_lane_index & 0x3);
+ src_lane_index >>= 2;
+ pref = PSHUFLW_x_xm | VEX_256 | ((src_lane_index & 1) == 0 ? EX86_PREF_F2 : EX86_PREF_F3) | EX86_SSE2;
+ break;
+ case 2:
+ byte = U8(src_lane_index & 0x3);
+ src_lane_index >>= 1;
+ pref = PSHUFD_x_xm | VEX_256 | EX86_PREF_66 | EX86_SSE2;
+ break;
+ case 3:
+ pref = 0;
+ break;
+ default:
+ FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg, 0, src, 0));
+ return emit_byte(compiler, U8(src_lane_index == 0 ? 0x44 : 0xee));
+ }
+
+ if (pref != 0) {
+ FAIL_IF(emit_vex_instruction(compiler, pref, vreg, 0, src, 0));
+ byte = U8(byte | (byte << 2));
+ FAIL_IF(emit_byte(compiler, U8(byte | (byte << 4))));
+
+ if (src_lane_index == 0)
+ return emit_vex_instruction(compiler, VPBROADCASTQ_x_xm | VEX_256 | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, vreg, 0);
+
+ src = vreg;
+ }
+
+ FAIL_IF(emit_vex_instruction(compiler, VPERMQ_y_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | VEX_W | EX86_SSE2, vreg, 0, src, 0));
+ byte = U8(src_lane_index);
+ byte = U8(byte | (byte << 2));
+ return emit_byte(compiler, U8(byte | (byte << 4)));
+ }
+
+ switch (elem_size) {
+ case 1:
+ byte = U8(src_lane_index & 0x3);
+ src_lane_index >>= 1;
+ pref = (src_lane_index & 2) == 0 ? EX86_PREF_F2 : EX86_PREF_F3;
+
+ if (use_vex)
+ FAIL_IF(emit_vex_instruction(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, vreg, 0, src, 0));
+ else
+ FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | pref | EX86_SSE2, vreg, src, 0));
+ byte = U8(byte | (byte << 2));
+ FAIL_IF(emit_byte(compiler, U8(byte | (byte << 4))));
+
+ if ((cpu_feature_list & CPU_FEATURE_AVX2) && use_vex && pref == EX86_PREF_F2)
+ return emit_vex_instruction(compiler, VPBROADCASTD_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, vreg, 0);
+
+ src = vreg;
+ SLJIT_FALLTHROUGH
+ case 2:
+ byte = U8(src_lane_index);
+ byte = U8(byte | (byte << 2));
+ break;
+ default:
+ byte = U8(src_lane_index << 1);
+ byte = U8(byte | (byte << 2) | 0x4);
+ break;
+ }
+
+ if (use_vex)
+ FAIL_IF(emit_vex_instruction(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, 0, src, 0));
+ else
+ FAIL_IF(emit_groupf(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, src, 0));
+ return emit_byte(compiler, U8(byte | (byte << 4)));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 elem2_size = SLJIT_SIMD_GET_ELEM2_SIZE(type);
+ sljit_s32 use_vex = (cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX);
+ sljit_u8 opcode;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_extend(compiler, type, vreg, src, srcw));
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 1;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (reg_size == 5) {
+ if (!(cpu_feature_list & CPU_FEATURE_AVX2))
+ return SLJIT_ERR_UNSUPPORTED;
+ use_vex = 1;
+ } else if (reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_FLOAT) {
+ if (elem_size != 2 || elem2_size != 3)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (use_vex)
+ return emit_vex_instruction(compiler, CVTPS2PD_x_xm | ((reg_size == 5) ? VEX_256 : 0) | EX86_SSE2, vreg, 0, src, srcw);
+ return emit_groupf(compiler, CVTPS2PD_x_xm | EX86_SSE2, vreg, src, srcw);
+ }
+
+ switch (elem_size) {
+ case 0:
+ if (elem2_size == 1)
+ opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXBW_x_xm : PMOVZXBW_x_xm;
+ else if (elem2_size == 2)
+ opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXBD_x_xm : PMOVZXBD_x_xm;
+ else if (elem2_size == 3)
+ opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXBQ_x_xm : PMOVZXBQ_x_xm;
+ else
+ return SLJIT_ERR_UNSUPPORTED;
+ break;
+ case 1:
+ if (elem2_size == 2)
+ opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXWD_x_xm : PMOVZXWD_x_xm;
+ else if (elem2_size == 3)
+ opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXWQ_x_xm : PMOVZXWQ_x_xm;
+ else
+ return SLJIT_ERR_UNSUPPORTED;
+ break;
+ case 2:
+ if (elem2_size == 3)
+ opcode = (type & SLJIT_SIMD_EXTEND_SIGNED) ? PMOVSXDQ_x_xm : PMOVZXDQ_x_xm;
+ else
+ return SLJIT_ERR_UNSUPPORTED;
+ break;
+ default:
+ return SLJIT_ERR_UNSUPPORTED;
+ }
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if (use_vex)
+ return emit_vex_instruction(compiler, opcode | ((reg_size == 5) ? VEX_256 : 0) | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, src, srcw);
+ return emit_groupf_ext(compiler, opcode | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, src, srcw);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 vreg,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 use_vex = (cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX);
+ sljit_s32 dst_r;
+ sljit_uw op;
+ sljit_u8 *inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_sign(compiler, type, vreg, dst, dstw));
+
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ CHECK_EXTRA_REGS(dst, dstw, (void)0);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 1;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (elem_size > 3 || ((type & SLJIT_SIMD_FLOAT) && elem_size < 2))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (reg_size == 4) {
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ op = EX86_PREF_66 | EX86_SSE2_OP2;
+
+ switch (elem_size) {
+ case 1:
+ if (use_vex)
+ FAIL_IF(emit_vex_instruction(compiler, PACKSSWB_x_xm | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, vreg, vreg, 0));
+ else
+ FAIL_IF(emit_groupf(compiler, PACKSSWB_x_xm | EX86_PREF_66 | EX86_SSE2, TMP_FREG, vreg, 0));
+ vreg = TMP_FREG;
+ break;
+ case 2:
+ op = EX86_SSE2_OP2;
+ break;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ op |= (elem_size < 2) ? PMOVMSKB_r_x : MOVMSKPS_r_x;
+
+ if (use_vex)
+ FAIL_IF(emit_vex_instruction(compiler, op, dst_r, 0, vreg, 0));
+ else
+ FAIL_IF(emit_groupf(compiler, op, dst_r, vreg, 0));
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = type & SLJIT_32;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (elem_size == 1) {
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 8, dst_r, 0);
+ FAIL_IF(!inst);
+ inst[1] |= SHR;
+ }
+
+ if (dst_r == TMP_REG1)
+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
+
+ return SLJIT_SUCCESS;
+ }
+
+ if (reg_size != 5 || !(cpu_feature_list & CPU_FEATURE_AVX2))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (elem_size == 1) {
+ FAIL_IF(emit_vex_instruction(compiler, VEXTRACTI128_x_ym | VEX_256 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2, vreg, 0, TMP_FREG, 0));
+ FAIL_IF(emit_byte(compiler, 1));
+ FAIL_IF(emit_vex_instruction(compiler, PACKSSWB_x_xm | VEX_256 | EX86_PREF_66 | EX86_SSE2 | VEX_SSE2_OPV, TMP_FREG, vreg, TMP_FREG, 0));
+ FAIL_IF(emit_groupf(compiler, PMOVMSKB_r_x | EX86_PREF_66 | EX86_SSE2_OP2, dst_r, TMP_FREG, 0));
+ } else {
+ op = MOVMSKPS_r_x | VEX_256 | EX86_SSE2_OP2;
+
+ if (elem_size == 0)
+ op = PMOVMSKB_r_x | VEX_256 | EX86_PREF_66 | EX86_SSE2_OP2;
+ else if (elem_size == 3)
+ op |= EX86_PREF_66;
+
+ FAIL_IF(emit_vex_instruction(compiler, op, dst_r, 0, vreg, 0));
+ }
+
+ if (dst_r == TMP_REG1) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = type & SLJIT_32;
+#endif /* SLJIT_CONFIG_X86_64 */
+ return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_simd_mov(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_vreg, sljit_s32 src_vreg)
+{
+ sljit_uw op = ((type & SLJIT_SIMD_FLOAT) ? MOVAPS_x_xm : MOVDQA_x_xm) | EX86_SSE2;
+
+ SLJIT_ASSERT(SLJIT_SIMD_GET_REG_SIZE(type) == 4);
+
+ if (!(type & SLJIT_SIMD_FLOAT) || SLJIT_SIMD_GET_ELEM_SIZE(type) == 3)
+ op |= EX86_PREF_66;
+
+ return emit_groupf(compiler, op, dst_vreg, src_vreg, 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *compiler, sljit_s32 type,
+ sljit_s32 dst_vreg, sljit_s32 src1_vreg, sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 reg_size = SLJIT_SIMD_GET_REG_SIZE(type);
+ sljit_s32 elem_size = SLJIT_SIMD_GET_ELEM_SIZE(type);
+ sljit_s32 use_vex = (cpu_feature_list & CPU_FEATURE_AVX) && (compiler->options & SLJIT_ENTER_USE_VEX);
+ sljit_uw op = 0;
+ sljit_uw mov_op = 0;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_simd_op2(compiler, type, dst_vreg, src1_vreg, src2, src2w));
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 1;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (reg_size == 5) {
+ if (!(cpu_feature_list & CPU_FEATURE_AVX2))
+ return SLJIT_ERR_UNSUPPORTED;
+ } else if (reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
+ return SLJIT_ERR_UNSUPPORTED;
+
+ switch (SLJIT_SIMD_GET_OPCODE(type)) {
+ case SLJIT_SIMD_OP2_AND:
+ op = (type & SLJIT_SIMD_FLOAT) ? ANDPD_x_xm : PAND_x_xm;
+
+ if (!(type & SLJIT_SIMD_FLOAT) || elem_size == 3)
+ op |= EX86_PREF_66;
+ break;
+ case SLJIT_SIMD_OP2_OR:
+ op = (type & SLJIT_SIMD_FLOAT) ? ORPD_x_xm : POR_x_xm;
+
+ if (!(type & SLJIT_SIMD_FLOAT) || elem_size == 3)
+ op |= EX86_PREF_66;
+ break;
+ case SLJIT_SIMD_OP2_XOR:
+ op = (type & SLJIT_SIMD_FLOAT) ? XORPD_x_xm : PXOR_x_xm;
+
+ if (!(type & SLJIT_SIMD_FLOAT) || elem_size == 3)
+ op |= EX86_PREF_66;
+ break;
+
+ case SLJIT_SIMD_OP2_SHUFFLE:
+ if (reg_size != 4)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ op = PSHUFB_x_xm | EX86_PREF_66 | VEX_OP_0F38;
+ break;
+ }
+
+ if (type & SLJIT_SIMD_TEST)
+ return SLJIT_SUCCESS;
+
+ if ((src2 & SLJIT_MEM) && SLJIT_SIMD_GET_ELEM2_SIZE(type) < reg_size) {
+ mov_op = ((type & SLJIT_SIMD_FLOAT) ? (MOVUPS_x_xm | (elem_size == 3 ? EX86_PREF_66 : 0)) : (MOVDQU_x_xm | EX86_PREF_F3)) | EX86_SSE2;
+ if (use_vex)
+ FAIL_IF(emit_vex_instruction(compiler, mov_op, TMP_FREG, 0, src2, src2w));
+ else
+ FAIL_IF(emit_groupf(compiler, mov_op, TMP_FREG, src2, src2w));
+
+ src2 = TMP_FREG;
+ src2w = 0;
+ }
+
+ if (reg_size == 5 || use_vex) {
+ if (reg_size == 5)
+ op |= VEX_256;
+
+ return emit_vex_instruction(compiler, op | EX86_SSE2 | VEX_SSE2_OPV, dst_vreg, src1_vreg, src2, src2w);
+ }
+
+ if (dst_vreg != src1_vreg) {
+ if (dst_vreg == src2) {
+ if (SLJIT_SIMD_GET_OPCODE(type) == SLJIT_SIMD_OP2_SHUFFLE) {
+ FAIL_IF(emit_simd_mov(compiler, type, TMP_FREG, src2));
+ FAIL_IF(emit_simd_mov(compiler, type, dst_vreg, src1_vreg));
+ src2 = TMP_FREG;
+ src2w = 0;
+ } else
+ src2 = src1_vreg;
+ } else
+ FAIL_IF(emit_simd_mov(compiler, type, dst_vreg, src1_vreg));
+ }
+
+ if (op & (VEX_OP_0F38 | VEX_OP_0F3A))
+ return emit_groupf_ext(compiler, op | EX86_SSE2, dst_vreg, src2, src2w);
+ return emit_groupf(compiler, op | EX86_SSE2, dst_vreg, src2, src2w);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst_reg,
+ sljit_s32 mem_reg)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));
+
+ if ((op & SLJIT_ATOMIC_USE_LS) || GET_OPCODE(op) == SLJIT_MOV_S8 || GET_OPCODE(op) == SLJIT_MOV_S16 || GET_OPCODE(op) == SLJIT_MOV_S32)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op1(compiler, op & ~SLJIT_ATOMIC_USE_CAS, dst_reg, 0, SLJIT_MEM1(mem_reg), 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src_reg,
+ sljit_s32 mem_reg,
+ sljit_s32 temp_reg)
+{
+ sljit_uw pref;
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ sljit_s32 saved_reg = TMP_REG1;
+ sljit_s32 swap_tmp = 0;
+ sljit_sw srcw = 0;
+ sljit_sw tempw = 0;
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));
+ CHECK_EXTRA_REGS(src_reg, srcw, (void)0);
+ CHECK_EXTRA_REGS(temp_reg, tempw, (void)0);
+
+ SLJIT_ASSERT(FAST_IS_REG(src_reg) || src_reg == SLJIT_MEM1(SLJIT_SP));
+ SLJIT_ASSERT(FAST_IS_REG(temp_reg) || temp_reg == SLJIT_MEM1(SLJIT_SP));
+
+ if ((op & SLJIT_ATOMIC_USE_LS) || GET_OPCODE(op) == SLJIT_MOV_S8 || GET_OPCODE(op) == SLJIT_MOV_S16 || GET_OPCODE(op) == SLJIT_MOV_S32)
+ return SLJIT_ERR_UNSUPPORTED;
+
+ if (op & SLJIT_ATOMIC_TEST)
+ return SLJIT_SUCCESS;
+
+ op = GET_OPCODE(op);
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if (temp_reg == SLJIT_TMP_DEST_REG) {
+ FAIL_IF(emit_byte(compiler, XCHG_EAX_r | reg_map[TMP_REG1]));
+
+ if (src_reg == SLJIT_R0)
+ src_reg = TMP_REG1;
+ if (mem_reg == SLJIT_R0)
+ mem_reg = TMP_REG1;
+
+ temp_reg = SLJIT_R0;
+ swap_tmp = 1;
+ }
+
+ /* Src is virtual register or its low byte is not accessible. */
+ if ((src_reg & SLJIT_MEM) || (op == SLJIT_MOV_U8 && reg_map[src_reg] >= 4)) {
+ SLJIT_ASSERT(src_reg != SLJIT_R1 && temp_reg != SLJIT_TMP_DEST_REG);
+
+ if (swap_tmp) {
+ saved_reg = (mem_reg != SLJIT_R1) ? SLJIT_R1 : SLJIT_R2;
+
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, saved_reg, 0);
+ EMIT_MOV(compiler, saved_reg, 0, src_reg, srcw);
+ } else
+ EMIT_MOV(compiler, TMP_REG1, 0, src_reg, srcw);
+
+ src_reg = saved_reg;
+
+ if (mem_reg == src_reg)
+ mem_reg = saved_reg;
+ }
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ if (temp_reg != SLJIT_R0) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+
+ EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_R0, 0);
+ EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, 0);
+
+ if (src_reg == SLJIT_R0)
+ src_reg = TMP_REG2;
+ if (mem_reg == SLJIT_R0)
+ mem_reg = TMP_REG2;
+#else /* !SLJIT_CONFIG_X86_64 */
+ SLJIT_ASSERT(!swap_tmp);
+
+ if (src_reg == TMP_REG1) {
+ if (mem_reg == SLJIT_R0) {
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R1, 0);
+ EMIT_MOV(compiler, SLJIT_R1, 0, SLJIT_R0, 0);
+ EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, tempw);
+
+ mem_reg = SLJIT_R1;
+ saved_reg = SLJIT_R1;
+ } else {
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0);
+ EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, tempw);
+ saved_reg = SLJIT_R0;
+ }
+ } else {
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R0, 0);
+ EMIT_MOV(compiler, SLJIT_R0, 0, temp_reg, tempw);
+
+ if (src_reg == SLJIT_R0)
+ src_reg = TMP_REG1;
+ if (mem_reg == SLJIT_R0)
+ mem_reg = TMP_REG1;
+ }
+#endif /* SLJIT_CONFIG_X86_64 */
+ }
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = op != SLJIT_MOV && op != SLJIT_MOV_P;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ /* Lock prefix. */
+ FAIL_IF(emit_byte(compiler, GROUP_LOCK));
+
+ pref = 0;
+ if (op == SLJIT_MOV_U16)
+ pref = EX86_HALF_ARG | EX86_PREF_66;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (op == SLJIT_MOV_U8)
+ pref = EX86_REX;
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ FAIL_IF(emit_groupf(compiler, (op == SLJIT_MOV_U8 ? CMPXCHG_rm8_r : CMPXCHG_rm_r) | pref, src_reg, SLJIT_MEM1(mem_reg), 0));
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if (swap_tmp) {
+ SLJIT_ASSERT(temp_reg == SLJIT_R0);
+ FAIL_IF(emit_byte(compiler, XCHG_EAX_r | reg_map[TMP_REG1]));
+
+ if (saved_reg != TMP_REG1)
+ return emit_mov(compiler, saved_reg, 0, SLJIT_MEM1(SLJIT_SP), 0);
+ return SLJIT_SUCCESS;
+ }
+#endif /* SLJIT_CONFIG_X86_32 */
+
+ if (temp_reg != SLJIT_R0) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+ return emit_mov(compiler, SLJIT_R0, 0, TMP_REG2, 0);
+#else /* !SLJIT_CONFIG_X86_64 */
+ EMIT_MOV(compiler, SLJIT_R0, 0, (saved_reg == SLJIT_R0) ? SLJIT_MEM1(SLJIT_SP) : saved_reg, 0);
+ if (saved_reg == SLJIT_R1)
+ return emit_mov(compiler, SLJIT_R1, 0, SLJIT_MEM1(SLJIT_SP), 0);
+#endif /* SLJIT_CONFIG_X86_64 */
+ }
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);
+
+ CHECK_EXTRA_REGS(dst, dstw, (void)0);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+#endif
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (NOT_HALFWORD(offset)) {
+ FAIL_IF(emit_load_imm64(compiler, TMP_REG1, offset));
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ SLJIT_ASSERT(emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0) != SLJIT_ERR_UNSUPPORTED);
+ return compiler->error;
+#else
+ return emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, TMP_REG1, 0);
+#endif
+ }
+#endif
+
+ if (offset != 0)
+ return emit_lea_binary(compiler, dst, dstw, SLJIT_SP, 0, SLJIT_IMM, offset);
+ return emit_mov(compiler, dst, dstw, SLJIT_SP, 0);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
+{
+ sljit_u8 *inst;
+ struct sljit_const *const_;
+ sljit_s32 reg;
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ sljit_s32 dst_is_ereg = 0;
+#endif /* !SLJIT_CONFIG_X86_32 */
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1);
+
+ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+ PTR_FAIL_IF(!const_);
+ set_const(const_, compiler);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = (op & SLJIT_32);
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if ((init_value & 0x100) != 0)
+ init_value = init_value | -(sljit_sw)0x100;
+ else
+ init_value = (sljit_u8)init_value;
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if (dst_is_ereg) {
+ if (emit_mov(compiler, dst, dstw, SLJIT_IMM, (sljit_s32)init_value))
+ return NULL;
+ dst = 0;
+ break;
+ }
+#endif /* !SLJIT_CONFIG_X86_32 */
+
+ reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (emit_mov(compiler, reg, 0, SLJIT_IMM, init_value))
+ return NULL;
+ break;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ case SLJIT_MOV:
+ compiler->mode32 = 0;
+ reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (emit_load_imm64(compiler, reg, init_value))
+ return NULL;
+ break;
+#endif /* SLJIT_CONFIG_X86_64 */
+ default:
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = (op == SLJIT_MOV32);
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (emit_mov(compiler, dst, dstw, SLJIT_IMM, (sljit_s32)init_value))
+ return NULL;
+ dst = 0;
+ break;
+ }
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1);
+ PTR_FAIL_IF(!inst);
+
+ inst[0] = SLJIT_INST_CONST;
+
+ if (dst & SLJIT_MEM) {
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (op == SLJIT_MOV) {
+ if (emit_mov(compiler, dst, dstw, TMP_REG1, 0))
+ return NULL;
+ return const_;
+ }
+#endif
+
+ if (emit_mov_byte(compiler, 0, dst, dstw, TMP_REG1, 0))
+ return NULL;
+ }
+
+ return const_;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ struct sljit_jump *jump;
+ sljit_u8 *inst;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ sljit_s32 reg;
+#endif /* SLJIT_CONFIG_X86_64 */
+ SLJIT_UNUSED_ARG(op);
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+
+ CHECK_EXTRA_REGS(dst, dstw, (void)0);
+
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ PTR_FAIL_IF(!jump);
+ set_mov_addr(jump, compiler, 0);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+ if (dst & SLJIT_MEM)
+ reg = TMP_REG1;
+ else
+ reg = (op != SLJIT_ADD_ABS_ADDR) ? dst : TMP_REG2;
+
+ PTR_FAIL_IF(emit_load_imm64(compiler, reg, 0));
+ jump->addr = compiler->size;
+
+ if (reg_map[reg] >= 8)
+ jump->flags |= MOV_ADDR_HI;
+#else /* !SLJIT_CONFIG_X86_64 */
+ if (op == SLJIT_ADD_ABS_ADDR) {
+ if (dst != SLJIT_R0) {
+ /* Must not be a signed byte argument. */
+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 0x100, dst, dstw);
+ PTR_FAIL_IF(!inst);
+ *(inst + 1) |= ADD;
+ } else
+ PTR_FAIL_IF(emit_do_imm(compiler, ADD_EAX_i32, 0));
+ } else {
+ PTR_FAIL_IF(emit_mov(compiler, dst, dstw, SLJIT_IMM, 0));
+ }
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1);
+ PTR_FAIL_IF(!inst);
+
+ inst[0] = SLJIT_INST_MOV_ADDR;
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (op == SLJIT_ADD_ABS_ADDR) {
+ inst = emit_x86_instruction(compiler, 1, reg, 0, dst, dstw);
+ PTR_FAIL_IF(!inst);
+ *inst = ADD_rm_r;
+ } else if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_mov(compiler, dst, dstw, TMP_REG1, 0));
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ return jump;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
+{
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_uw)), 0);
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ sljit_unaligned_store_sw((void*)addr, (sljit_sw)(new_target - (addr + 4) - (sljit_uw)executable_offset));
+#else
+ sljit_unaligned_store_sw((void*)addr, (sljit_sw)new_target);
+#endif
+ SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_uw)), 1);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
+{
+ void *start_addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (op == SLJIT_MOV) {
+ start_addr = (void*)(addr - sizeof(sljit_sw));
+ SLJIT_UPDATE_WX_FLAGS(start_addr, (void*)addr, 0);
+ sljit_unaligned_store_sw(start_addr, new_constant);
+ SLJIT_UPDATE_WX_FLAGS(start_addr, (void*)addr, 1);
+ return;
+ }
+#endif
+
+ start_addr = (void*)(addr - sizeof(sljit_s32));
+
+ if ((op | SLJIT_32) == SLJIT_MOV32_U8) {
+ if ((new_constant & 0x100) != 0)
+ new_constant = new_constant | -(sljit_sw)0x100;
+ else
+ new_constant = (sljit_u8)new_constant;
+ }
+
+ SLJIT_UPDATE_WX_FLAGS(start_addr, (void*)addr, 0);
+ sljit_unaligned_store_s32(start_addr, (sljit_s32)new_constant);
+ SLJIT_UPDATE_WX_FLAGS(start_addr, (void*)addr, 1);
+}
diff --git a/deps/sljit/sljit_src/sljitSerialize.c b/deps/sljit/sljit_src/sljitSerialize.c
new file mode 100644
index 0000000..042cc18
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitSerialize.c
@@ -0,0 +1,585 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define SLJIT_GET_LABEL_INDEX(label) \
+ ((label)->u.index < SLJIT_LABEL_ALIGNED ? (label)->u.index : ((struct sljit_extended_label*)(label))->index)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_uw sljit_get_label_index(struct sljit_label *label)
+{
+ return SLJIT_GET_LABEL_INDEX(label);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_label(struct sljit_jump *jump)
+{
+ return !(jump->flags & JUMP_ADDR) && (jump->u.label != NULL);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_target(struct sljit_jump *jump)
+{
+ return (jump->flags & JUMP_ADDR) != 0;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_is_mov_addr(struct sljit_jump *jump)
+{
+ return (jump->flags & JUMP_MOV_ADDR) != 0;
+}
+
+#define SLJIT_SERIALIZE_DEBUG ((sljit_u16)0x1)
+
+struct sljit_serialized_compiler {
+ sljit_u32 signature;
+ sljit_u16 version;
+ sljit_u16 cpu_type;
+
+ sljit_uw buf_segment_count;
+ sljit_uw label_count;
+ sljit_uw aligned_label_count;
+ sljit_uw jump_count;
+ sljit_uw const_count;
+
+ sljit_s32 options;
+ sljit_s32 scratches;
+ sljit_s32 saveds;
+ sljit_s32 fscratches;
+ sljit_s32 fsaveds;
+ sljit_s32 local_size;
+ sljit_uw size;
+
+#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)
+ sljit_s32 status_flags_state;
+#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ sljit_s32 args_size;
+#endif /* SLJIT_CONFIG_X86_32 */
+
+#if ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \
+ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ sljit_uw args_size;
+#endif /* (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ sljit_uw cpool_diff;
+ sljit_uw cpool_fill;
+ sljit_uw patches;
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
+ sljit_s32 delay_slot;
+#endif /* SLJIT_CONFIG_MIPS */
+
+};
+
+struct sljit_serialized_debug_info {
+ sljit_sw last_flags;
+ sljit_s32 last_return;
+ sljit_s32 logical_local_size;
+};
+
+struct sljit_serialized_label {
+ sljit_uw size;
+};
+
+struct sljit_serialized_aligned_label {
+ sljit_uw size;
+ sljit_uw data;
+};
+
+struct sljit_serialized_jump {
+ sljit_uw addr;
+ sljit_uw flags;
+ sljit_uw value;
+};
+
+struct sljit_serialized_const {
+ sljit_uw addr;
+};
+
+#define SLJIT_SERIALIZE_ALIGN(v) (((v) + sizeof(sljit_uw) - 1) & ~(sljit_uw)(sizeof(sljit_uw) - 1))
+#if (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
+#define SLJIT_SERIALIZE_SIGNATURE 0x534c4a54
+#else /* !SLJIT_LITTLE_ENDIAN */
+#define SLJIT_SERIALIZE_SIGNATURE 0x544a4c53
+#endif /* SLJIT_LITTLE_ENDIAN */
+#define SLJIT_SERIALIZE_VERSION 1
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_uw* sljit_serialize_compiler(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_uw *size)
+{
+ sljit_uw serialized_size = sizeof(struct sljit_serialized_compiler);
+ struct sljit_memory_fragment *buf;
+ struct sljit_label *label;
+ struct sljit_jump *jump;
+ struct sljit_const *const_;
+ struct sljit_serialized_compiler *serialized_compiler;
+ struct sljit_serialized_label *serialized_label;
+ struct sljit_serialized_aligned_label *serialized_aligned_label;
+ struct sljit_serialized_jump *serialized_jump;
+ struct sljit_serialized_const *serialized_const;
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ struct sljit_serialized_debug_info *serialized_debug_info;
+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
+ sljit_uw counter, used_size;
+ sljit_u8 *result;
+ sljit_u8 *ptr;
+ SLJIT_UNUSED_ARG(options);
+
+ if (size != NULL)
+ *size = 0;
+
+ PTR_FAIL_IF(compiler->error);
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ if (!(options & SLJIT_SERIALIZE_IGNORE_DEBUG))
+ serialized_size += sizeof(struct sljit_serialized_debug_info);
+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ serialized_size += SLJIT_SERIALIZE_ALIGN(compiler->cpool_fill * (sizeof(sljit_uw) + 1));
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+ /* Compute the size of the data. */
+ buf = compiler->buf;
+ while (buf != NULL) {
+ serialized_size += sizeof(sljit_uw) + SLJIT_SERIALIZE_ALIGN(buf->used_size);
+ buf = buf->next;
+ }
+
+ label = compiler->labels;
+ while (label != NULL) {
+ used_size = sizeof(struct sljit_serialized_label);
+
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ used_size += sizeof(struct sljit_serialized_aligned_label);
+
+ serialized_size += used_size;
+ label = label->next;
+ }
+
+ jump = compiler->jumps;
+ while (jump != NULL) {
+ serialized_size += sizeof(struct sljit_serialized_jump);
+ jump = jump->next;
+ }
+
+ const_ = compiler->consts;
+ while (const_ != NULL) {
+ serialized_size += sizeof(struct sljit_serialized_const);
+ const_ = const_->next;
+ }
+
+ result = (sljit_u8*)SLJIT_MALLOC(serialized_size, compiler->allocator_data);
+ PTR_FAIL_IF_NULL(result);
+
+ if (size != NULL)
+ *size = serialized_size;
+
+ ptr = result;
+ serialized_compiler = (struct sljit_serialized_compiler*)ptr;
+ ptr += sizeof(struct sljit_serialized_compiler);
+
+ serialized_compiler->signature = SLJIT_SERIALIZE_SIGNATURE;
+ serialized_compiler->version = SLJIT_SERIALIZE_VERSION;
+ serialized_compiler->cpu_type = 0;
+ serialized_compiler->label_count = compiler->label_count;
+ serialized_compiler->options = compiler->options;
+ serialized_compiler->scratches = compiler->scratches;
+ serialized_compiler->saveds = compiler->saveds;
+ serialized_compiler->fscratches = compiler->fscratches;
+ serialized_compiler->fsaveds = compiler->fsaveds;
+ serialized_compiler->local_size = compiler->local_size;
+ serialized_compiler->size = compiler->size;
+
+#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)
+ serialized_compiler->status_flags_state = compiler->status_flags_state;
+#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
+ || ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \
+ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ serialized_compiler->args_size = compiler->args_size;
+#endif /* SLJIT_CONFIG_X86_32 || (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ serialized_compiler->cpool_diff = compiler->cpool_diff;
+ serialized_compiler->cpool_fill = compiler->cpool_fill;
+ serialized_compiler->patches = compiler->patches;
+
+ SLJIT_MEMCPY(ptr, compiler->cpool, compiler->cpool_fill * sizeof(sljit_uw));
+ SLJIT_MEMCPY(ptr + compiler->cpool_fill * sizeof(sljit_uw), compiler->cpool_unique, compiler->cpool_fill);
+ ptr += SLJIT_SERIALIZE_ALIGN(compiler->cpool_fill * (sizeof(sljit_uw) + 1));
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
+ serialized_compiler->delay_slot = compiler->delay_slot;
+#endif /* SLJIT_CONFIG_MIPS */
+
+ buf = compiler->buf;
+ counter = 0;
+ while (buf != NULL) {
+ used_size = buf->used_size;
+ *(sljit_uw*)ptr = used_size;
+ ptr += sizeof(sljit_uw);
+ SLJIT_MEMCPY(ptr, buf->memory, used_size);
+ ptr += SLJIT_SERIALIZE_ALIGN(used_size);
+ buf = buf->next;
+ counter++;
+ }
+ serialized_compiler->buf_segment_count = counter;
+
+ label = compiler->labels;
+ counter = 0;
+ while (label != NULL) {
+ serialized_label = (struct sljit_serialized_label*)ptr;
+ serialized_label->size = (label->u.index < SLJIT_LABEL_ALIGNED) ? label->size : label->u.index;
+ ptr += sizeof(struct sljit_serialized_label);
+
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ serialized_aligned_label = (struct sljit_serialized_aligned_label*)ptr;
+ serialized_aligned_label->size = label->size;
+ serialized_aligned_label->data = ((struct sljit_extended_label*)label)->data;
+ ptr += sizeof(struct sljit_serialized_aligned_label);
+ counter++;
+ }
+
+ label = label->next;
+ }
+ serialized_compiler->aligned_label_count = counter;
+
+ jump = compiler->jumps;
+ counter = 0;
+ while (jump != NULL) {
+ serialized_jump = (struct sljit_serialized_jump*)ptr;
+ serialized_jump->addr = jump->addr;
+ serialized_jump->flags = jump->flags;
+
+ if (jump->flags & JUMP_ADDR)
+ serialized_jump->value = jump->u.target;
+ else if (jump->u.label != NULL)
+ serialized_jump->value = SLJIT_GET_LABEL_INDEX(jump->u.label);
+ else
+ serialized_jump->value = SLJIT_MAX_ADDRESS;
+
+ ptr += sizeof(struct sljit_serialized_jump);
+ jump = jump->next;
+ counter++;
+ }
+ serialized_compiler->jump_count = counter;
+
+ const_ = compiler->consts;
+ counter = 0;
+ while (const_ != NULL) {
+ serialized_const = (struct sljit_serialized_const*)ptr;
+ serialized_const->addr = const_->addr;
+ ptr += sizeof(struct sljit_serialized_const);
+ const_ = const_->next;
+ counter++;
+ }
+ serialized_compiler->const_count = counter;
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ if (!(options & SLJIT_SERIALIZE_IGNORE_DEBUG)) {
+ serialized_debug_info = (struct sljit_serialized_debug_info*)ptr;
+ serialized_debug_info->last_flags = compiler->last_flags;
+ serialized_debug_info->last_return = compiler->last_return;
+ serialized_debug_info->logical_local_size = compiler->logical_local_size;
+ serialized_compiler->cpu_type |= SLJIT_SERIALIZE_DEBUG;
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ ptr += sizeof(struct sljit_serialized_debug_info);
+#endif /* SLJIT_DEBUG */
+ }
+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
+
+ SLJIT_ASSERT((sljit_uw)(ptr - result) == serialized_size);
+ return (sljit_uw*)result;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler *sljit_deserialize_compiler(sljit_uw* buffer, sljit_uw size,
+ sljit_s32 options, void *allocator_data)
+{
+ struct sljit_compiler *compiler;
+ struct sljit_serialized_compiler *serialized_compiler;
+ struct sljit_serialized_label *serialized_label;
+ struct sljit_serialized_aligned_label *serialized_aligned_label;
+ struct sljit_serialized_jump *serialized_jump;
+ struct sljit_serialized_const *serialized_const;
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ struct sljit_serialized_debug_info *serialized_debug_info;
+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
+ struct sljit_memory_fragment *buf;
+ struct sljit_memory_fragment *last_buf;
+ struct sljit_label *label;
+ struct sljit_label *last_label;
+ struct sljit_label **label_list = NULL;
+ struct sljit_label **label_list_ptr = NULL;
+ struct sljit_jump *jump;
+ struct sljit_jump *last_jump;
+ struct sljit_const *const_;
+ struct sljit_const *last_const;
+ sljit_u8 *ptr = (sljit_u8*)buffer;
+ sljit_u8 *end = ptr + size;
+ sljit_uw i, type, used_size, aligned_size;
+ sljit_uw label_count, aligned_label_count;
+ SLJIT_UNUSED_ARG(options);
+
+ if (size < sizeof(struct sljit_serialized_compiler) || (size & (sizeof(sljit_uw) - 1)) != 0)
+ return NULL;
+
+ serialized_compiler = (struct sljit_serialized_compiler*)ptr;
+
+ if (serialized_compiler->signature != SLJIT_SERIALIZE_SIGNATURE || serialized_compiler->version != SLJIT_SERIALIZE_VERSION)
+ return NULL;
+
+ compiler = sljit_create_compiler(allocator_data);
+ PTR_FAIL_IF(compiler == NULL);
+
+ compiler->label_count = serialized_compiler->label_count;
+ compiler->options = serialized_compiler->options;
+ compiler->scratches = serialized_compiler->scratches;
+ compiler->saveds = serialized_compiler->saveds;
+ compiler->fscratches = serialized_compiler->fscratches;
+ compiler->fsaveds = serialized_compiler->fsaveds;
+ compiler->local_size = serialized_compiler->local_size;
+ compiler->size = serialized_compiler->size;
+
+#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)
+ compiler->status_flags_state = serialized_compiler->status_flags_state;
+#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
+ || ((defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)) \
+ || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ compiler->args_size = serialized_compiler->args_size;
+#endif /* SLJIT_CONFIG_X86_32 || (SLJIT_CONFIG_ARM_32 && __SOFTFP__) || SLJIT_CONFIG_MIPS_32 */
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ used_size = serialized_compiler->cpool_fill;
+ aligned_size = SLJIT_SERIALIZE_ALIGN(used_size * (sizeof(sljit_uw) + 1));
+ compiler->cpool_diff = serialized_compiler->cpool_diff;
+ compiler->cpool_fill = used_size;
+ compiler->patches = serialized_compiler->patches;
+
+ if ((sljit_uw)(end - ptr) < aligned_size)
+ goto error;
+
+ SLJIT_MEMCPY(compiler->cpool, ptr, used_size * sizeof(sljit_uw));
+ SLJIT_MEMCPY(compiler->cpool_unique, ptr + used_size * sizeof(sljit_uw), used_size);
+ ptr += aligned_size;
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
+ compiler->delay_slot = serialized_compiler->delay_slot;
+#endif /* SLJIT_CONFIG_MIPS */
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ if (!(serialized_compiler->cpu_type & SLJIT_SERIALIZE_DEBUG))
+ goto error;
+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
+
+ ptr += sizeof(struct sljit_serialized_compiler);
+ i = serialized_compiler->buf_segment_count;
+ last_buf = NULL;
+ while (i > 0) {
+ if ((sljit_uw)(end - ptr) < sizeof(sljit_uw))
+ goto error;
+
+ used_size = *(sljit_uw*)ptr;
+ aligned_size = SLJIT_SERIALIZE_ALIGN(used_size);
+ ptr += sizeof(sljit_uw);
+
+ if ((sljit_uw)(end - ptr) < aligned_size)
+ goto error;
+
+ if (last_buf == NULL) {
+ SLJIT_ASSERT(compiler->buf != NULL && compiler->buf->next == NULL);
+ buf = compiler->buf;
+ } else {
+ buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, allocator_data);
+ if (!buf)
+ goto error;
+ buf->next = NULL;
+ }
+
+ buf->used_size = used_size;
+ SLJIT_MEMCPY(buf->memory, ptr, used_size);
+
+ if (last_buf != NULL)
+ last_buf->next = buf;
+ last_buf = buf;
+
+ ptr += aligned_size;
+ i--;
+ }
+
+ last_label = NULL;
+ label_count = serialized_compiler->label_count;
+ aligned_label_count = serialized_compiler->aligned_label_count;
+ i = (label_count * sizeof(struct sljit_serialized_label)) + (aligned_label_count * sizeof(struct sljit_serialized_aligned_label));
+
+ if ((sljit_uw)(end - ptr) < i)
+ goto error;
+
+ label_list = (struct sljit_label **)SLJIT_MALLOC(label_count * sizeof(struct sljit_label*), allocator_data);
+ if (label_list == NULL)
+ goto error;
+
+ label_list_ptr = label_list;
+ for (i = 0; i < label_count; i++) {
+ serialized_label = (struct sljit_serialized_label*)ptr;
+ type = serialized_label->size;
+
+ if (type < SLJIT_LABEL_ALIGNED) {
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+ } else {
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ }
+
+ if (label == NULL)
+ goto error;
+
+ label->next = NULL;
+
+ if (last_label != NULL)
+ last_label->next = label;
+ else
+ compiler->labels = label;
+ last_label = label;
+
+ *label_list_ptr++ = label;
+
+ ptr += sizeof(struct sljit_serialized_label);
+
+ if (type < SLJIT_LABEL_ALIGNED) {
+ label->u.index = i;
+ label->size = type;
+ } else {
+ if (aligned_label_count == 0)
+ goto error;
+
+ aligned_label_count--;
+
+ serialized_aligned_label = (struct sljit_serialized_aligned_label*)ptr;
+ label->u.index = type;
+ label->size = serialized_aligned_label->size;
+
+ ((struct sljit_extended_label*)label)->index = i;
+ ((struct sljit_extended_label*)label)->data = serialized_aligned_label->data;
+ ptr += sizeof(struct sljit_serialized_aligned_label);
+ }
+ }
+ compiler->last_label = last_label;
+
+ if (aligned_label_count != 0)
+ goto error;
+
+ last_jump = NULL;
+ i = serialized_compiler->jump_count;
+ if ((sljit_uw)(end - ptr) < i * sizeof(struct sljit_serialized_jump))
+ goto error;
+
+ while (i > 0) {
+ jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ if (jump == NULL)
+ goto error;
+
+ serialized_jump = (struct sljit_serialized_jump*)ptr;
+ jump->next = NULL;
+ jump->addr = serialized_jump->addr;
+ jump->flags = serialized_jump->flags;
+
+ if (!(serialized_jump->flags & JUMP_ADDR)) {
+ if (serialized_jump->value != SLJIT_MAX_ADDRESS) {
+ if (serialized_jump->value >= label_count)
+ goto error;
+ jump->u.label = label_list[serialized_jump->value];
+ } else
+ jump->u.label = NULL;
+ } else
+ jump->u.target = serialized_jump->value;
+
+ if (last_jump != NULL)
+ last_jump->next = jump;
+ else
+ compiler->jumps = jump;
+ last_jump = jump;
+
+ ptr += sizeof(struct sljit_serialized_jump);
+ i--;
+ }
+ compiler->last_jump = last_jump;
+
+ SLJIT_FREE(label_list, allocator_data);
+ label_list = NULL;
+
+ last_const = NULL;
+ i = serialized_compiler->const_count;
+ if ((sljit_uw)(end - ptr) < i * sizeof(struct sljit_serialized_const))
+ goto error;
+
+ while (i > 0) {
+ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
+ if (const_ == NULL)
+ goto error;
+
+ serialized_const = (struct sljit_serialized_const*)ptr;
+ const_->next = NULL;
+ const_->addr = serialized_const->addr;
+
+ if (last_const != NULL)
+ last_const->next = const_;
+ else
+ compiler->consts = const_;
+ last_const = const_;
+
+ ptr += sizeof(struct sljit_serialized_const);
+ i--;
+ }
+ compiler->last_const = last_const;
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ if ((sljit_uw)(end - ptr) < sizeof(struct sljit_serialized_debug_info))
+ goto error;
+
+ serialized_debug_info = (struct sljit_serialized_debug_info*)ptr;
+ compiler->last_flags = (sljit_s32)serialized_debug_info->last_flags;
+ compiler->last_return = serialized_debug_info->last_return;
+ compiler->logical_local_size = serialized_debug_info->logical_local_size;
+#endif /* SLJIT_ARGUMENT_CHECKS || SLJIT_DEBUG */
+
+ return compiler;
+
+error:
+ sljit_free_compiler(compiler);
+ if (label_list != NULL)
+ SLJIT_FREE(label_list, allocator_data);
+ return NULL;
+}
diff --git a/deps/sljit/sljit_src/sljitUtils.c b/deps/sljit/sljit_src/sljitUtils.c
new file mode 100644
index 0000000..967593b
--- /dev/null
+++ b/deps/sljit/sljit_src/sljitUtils.c
@@ -0,0 +1,344 @@
+/*
+ * Stack-less Just-In-Time compiler
+ *
+ * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* ------------------------------------------------------------------------ */
+/* Locks */
+/* ------------------------------------------------------------------------ */
+
+/* Executable Allocator */
+
+#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \
+ && !(defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)
+#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
+#define SLJIT_ALLOCATOR_LOCK()
+#define SLJIT_ALLOCATOR_UNLOCK()
+#elif !(defined _WIN32)
+#include
+
+static pthread_mutex_t allocator_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#define SLJIT_ALLOCATOR_LOCK() pthread_mutex_lock(&allocator_lock)
+#define SLJIT_ALLOCATOR_UNLOCK() pthread_mutex_unlock(&allocator_lock)
+#else /* windows */
+static HANDLE allocator_lock;
+
+static SLJIT_INLINE void allocator_grab_lock(void)
+{
+ HANDLE lock;
+ if (SLJIT_UNLIKELY(!InterlockedCompareExchangePointer(&allocator_lock, NULL, NULL))) {
+ lock = CreateMutex(NULL, FALSE, NULL);
+ if (InterlockedCompareExchangePointer(&allocator_lock, lock, NULL))
+ CloseHandle(lock);
+ }
+ WaitForSingleObject(allocator_lock, INFINITE);
+}
+
+#define SLJIT_ALLOCATOR_LOCK() allocator_grab_lock()
+#define SLJIT_ALLOCATOR_UNLOCK() ReleaseMutex(allocator_lock)
+#endif /* thread implementation */
+#endif /* SLJIT_EXECUTABLE_ALLOCATOR && !SLJIT_WX_EXECUTABLE_ALLOCATOR */
+
+/* ------------------------------------------------------------------------ */
+/* Stack */
+/* ------------------------------------------------------------------------ */
+
+#if ((defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \
+ && !(defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)) \
+ || ((defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \
+ && !((defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) \
+ || (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)))
+
+#ifndef _WIN32
+/* Provides mmap function. */
+#include
+#include
+
+#ifndef MAP_ANON
+#ifdef MAP_ANONYMOUS
+#define MAP_ANON MAP_ANONYMOUS
+#endif /* MAP_ANONYMOUS */
+#endif /* !MAP_ANON */
+
+#ifndef MAP_ANON
+
+#include
+
+#ifdef O_CLOEXEC
+#define SLJIT_CLOEXEC O_CLOEXEC
+#else /* !O_CLOEXEC */
+#define SLJIT_CLOEXEC 0
+#endif /* O_CLOEXEC */
+
+/* Some old systems do not have MAP_ANON. */
+static int dev_zero = -1;
+
+#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
+
+static SLJIT_INLINE int open_dev_zero(void)
+{
+ dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC);
+
+ return dev_zero < 0;
+}
+
+#else /* !SLJIT_SINGLE_THREADED */
+
+#include
+
+static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static SLJIT_INLINE int open_dev_zero(void)
+{
+ pthread_mutex_lock(&dev_zero_mutex);
+ if (SLJIT_UNLIKELY(dev_zero < 0))
+ dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC);
+
+ pthread_mutex_unlock(&dev_zero_mutex);
+ return dev_zero < 0;
+}
+
+#endif /* SLJIT_SINGLE_THREADED */
+#undef SLJIT_CLOEXEC
+#endif /* !MAP_ANON */
+#endif /* !_WIN32 */
+#endif /* open_dev_zero */
+
+#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \
+ || (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
+
+#ifdef _WIN32
+
+static SLJIT_INLINE sljit_uw get_page_alignment(void) {
+ SYSTEM_INFO si;
+ static sljit_uw sljit_page_align = 0;
+ if (!sljit_page_align) {
+ GetSystemInfo(&si);
+ sljit_page_align = (sljit_uw)si.dwPageSize - 1;
+ }
+ return sljit_page_align;
+}
+
+#else
+
+#include
+
+static SLJIT_INLINE sljit_uw get_page_alignment(void) {
+ static sljit_uw sljit_page_align = 0;
+
+ sljit_sw align;
+
+ if (!sljit_page_align) {
+#ifdef _SC_PAGESIZE
+ align = sysconf(_SC_PAGESIZE);
+#else
+ align = getpagesize();
+#endif
+ /* Should never happen. */
+ if (align < 0)
+ align = 4096;
+ sljit_page_align = (sljit_uw)align - 1;
+ }
+ return sljit_page_align;
+}
+
+#endif /* _WIN32 */
+
+#endif /* get_page_alignment() */
+
+#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
+
+#if (defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)
+{
+ struct sljit_stack *stack;
+ void *ptr;
+
+ SLJIT_UNUSED_ARG(allocator_data);
+
+ if (start_size > max_size || start_size < 1)
+ return NULL;
+
+ stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);
+ if (stack == NULL)
+ return NULL;
+
+ ptr = SLJIT_MALLOC(max_size, allocator_data);
+ if (ptr == NULL) {
+ SLJIT_FREE(stack, allocator_data);
+ return NULL;
+ }
+
+ stack->min_start = (sljit_u8 *)ptr;
+ stack->end = stack->min_start + max_size;
+ stack->start = stack->end - start_size;
+ stack->top = stack->end;
+ return stack;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
+{
+ SLJIT_UNUSED_ARG(allocator_data);
+ SLJIT_FREE((void*)stack->min_start, allocator_data);
+ SLJIT_FREE(stack, allocator_data);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)
+{
+ if ((new_start < stack->min_start) || (new_start >= stack->end))
+ return NULL;
+ stack->start = new_start;
+ return new_start;
+}
+
+#else /* !SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */
+
+#ifdef _WIN32
+
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
+{
+ SLJIT_UNUSED_ARG(allocator_data);
+ VirtualFree((void*)stack->min_start, 0, MEM_RELEASE);
+ SLJIT_FREE(stack, allocator_data);
+}
+
+#else /* !_WIN32 */
+
+SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
+{
+ SLJIT_UNUSED_ARG(allocator_data);
+ munmap((void*)stack->min_start, (size_t)(stack->end - stack->min_start));
+ SLJIT_FREE(stack, allocator_data);
+}
+
+#endif /* _WIN32 */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)
+{
+ struct sljit_stack *stack;
+ void *ptr;
+ sljit_uw page_align;
+
+ SLJIT_UNUSED_ARG(allocator_data);
+
+ if (start_size > max_size || start_size < 1)
+ return NULL;
+
+ stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);
+ if (stack == NULL)
+ return NULL;
+
+ /* Align max_size. */
+ page_align = get_page_alignment();
+ max_size = (max_size + page_align) & ~page_align;
+
+#ifdef _WIN32
+ ptr = VirtualAlloc(NULL, max_size, MEM_RESERVE, PAGE_READWRITE);
+ if (!ptr) {
+ SLJIT_FREE(stack, allocator_data);
+ return NULL;
+ }
+
+ stack->min_start = (sljit_u8 *)ptr;
+ stack->end = stack->min_start + max_size;
+ stack->start = stack->end;
+
+ if (sljit_stack_resize(stack, stack->end - start_size) == NULL) {
+ sljit_free_stack(stack, allocator_data);
+ return NULL;
+ }
+#else /* !_WIN32 */
+#ifdef MAP_ANON
+ ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+#else /* !MAP_ANON */
+ if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero())) {
+ SLJIT_FREE(stack, allocator_data);
+ return NULL;
+ }
+ ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
+#endif /* MAP_ANON */
+ if (ptr == MAP_FAILED) {
+ SLJIT_FREE(stack, allocator_data);
+ return NULL;
+ }
+ stack->min_start = (sljit_u8 *)ptr;
+ stack->end = stack->min_start + max_size;
+ stack->start = stack->end - start_size;
+#endif /* _WIN32 */
+
+ stack->top = stack->end;
+ return stack;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)
+{
+#if defined _WIN32 || defined(POSIX_MADV_DONTNEED)
+ sljit_uw aligned_old_start;
+ sljit_uw aligned_new_start;
+ sljit_uw page_align;
+#endif
+
+ if ((new_start < stack->min_start) || (new_start >= stack->end))
+ return NULL;
+
+#ifdef _WIN32
+ page_align = get_page_alignment();
+
+ aligned_new_start = (sljit_uw)new_start & ~page_align;
+ aligned_old_start = ((sljit_uw)stack->start) & ~page_align;
+ if (aligned_new_start != aligned_old_start) {
+ if (aligned_new_start < aligned_old_start) {
+ if (!VirtualAlloc((void*)aligned_new_start, aligned_old_start - aligned_new_start, MEM_COMMIT, PAGE_READWRITE))
+ return NULL;
+ }
+ else {
+ if (!VirtualFree((void*)aligned_old_start, aligned_new_start - aligned_old_start, MEM_DECOMMIT))
+ return NULL;
+ }
+ }
+#elif defined(POSIX_MADV_DONTNEED)
+ if (stack->start < new_start) {
+ page_align = get_page_alignment();
+
+ aligned_new_start = (sljit_uw)new_start & ~page_align;
+ aligned_old_start = ((sljit_uw)stack->start) & ~page_align;
+
+ if (aligned_new_start > aligned_old_start) {
+ posix_madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, POSIX_MADV_DONTNEED);
+#ifdef MADV_FREE
+ madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_FREE);
+#endif /* MADV_FREE */
+ }
+ }
+#endif /* _WIN32 */
+
+ stack->start = new_start;
+ return new_start;
+}
+
+#endif /* SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */
+
+#endif /* SLJIT_UTIL_STACK */
diff --git a/doc/html/NON-AUTOTOOLS-BUILD.txt b/doc/html/NON-AUTOTOOLS-BUILD.txt
new file mode 100644
index 0000000..45c8bad
--- /dev/null
+++ b/doc/html/NON-AUTOTOOLS-BUILD.txt
@@ -0,0 +1,487 @@
+Building PCRE2 without using autotools
+======================================
+
+This document contains the following sections:
+
+ General
+ Generic instructions for the PCRE2 C libraries
+ Stack size in Windows environments
+ Linking programs in Windows environments
+ Calling conventions in Windows environments
+ Comments about Win32 builds
+ Building PCRE2 on Windows with CMake
+ Building PCRE2 on Windows with Visual Studio
+ Testing with RunTest.bat
+ Building PCRE2 on z/OS and z/VM
+ Building PCRE2 under VMS
+
+
+General
+-------
+
+The source of the PCRE2 libraries consists entirely of code written in Standard
+C, and so should compile successfully on any system that has a Standard C
+compiler and library.
+
+The PCRE2 distribution includes a "configure" file for use by the
+configure/make (autotools) build system, as found in many Unix-like
+environments. The README file contains information about the options for
+"configure".
+
+There is also support for CMake, which some users prefer, especially in Windows
+environments, though it can also be run in Unix-like environments. See the
+section entitled "Building PCRE2 on Windows with CMake" below.
+
+Versions of src/config.h and src/pcre2.h are distributed in the PCRE2 tarballs
+under the names src/config.h.generic and src/pcre2.h.generic. These are
+provided for those who build PCRE2 without using "configure" or CMake. If you
+use "configure" or CMake, the .generic versions are not used.
+
+
+Generic instructions for the PCRE2 C libraries
+----------------------------------------------
+
+There are three possible PCRE2 libraries, each handling data with a specific
+code unit width: 8, 16, or 32 bits. You can build any combination of them. The
+following are generic instructions for building a PCRE2 C library "by hand". If
+you are going to use CMake, this section does not apply to you; you can skip
+ahead to the CMake section. Note that the settings concerned with 8-bit,
+16-bit, and 32-bit code units relate to the type of data string that PCRE2
+processes. They are NOT referring to the underlying operating system bit width.
+You do not have to do anything special to compile in a 64-bit environment, for
+example.
+
+ (1) Copy or rename the file src/config.h.generic as src/config.h, and edit the
+ macro settings that it contains to whatever is appropriate for your
+ environment. In particular, you can alter the definition of the NEWLINE
+ macro to specify what character(s) you want to be interpreted as line
+ terminators by default. You need to #define at least one of
+ SUPPORT_PCRE2_8, SUPPORT_PCRE2_16, or SUPPORT_PCRE2_32, depending on which
+ libraries you are going to build. You must set all that apply.
+
+ When you subsequently compile any of the PCRE2 modules, you must specify
+ -DHAVE_CONFIG_H to your compiler so that src/config.h is included in the
+ sources.
+
+ An alternative approach is not to edit src/config.h, but to use -D on the
+ compiler command line to make any changes that you need to the
+ configuration options. In this case -DHAVE_CONFIG_H must not be set.
+
+ NOTE: There have been occasions when the way in which certain parameters
+ in src/config.h are used has changed between releases. (In the
+ configure/make world, this is handled automatically.) When upgrading to a
+ new release, you are strongly advised to review src/config.h.generic
+ before re-using what you had previously.
+
+ Note also that the src/config.h.generic file is created from a config.h
+ that was generated by Autotools, which automatically includes settings of
+ a number of macros that are not actually used by PCRE2 (for example,
+ HAVE_DLFCN_H).
+
+ (2) Copy or rename the file src/pcre2.h.generic as src/pcre2.h.
+
+ (3) EITHER:
+ Copy or rename file src/pcre2_chartables.c.dist as
+ src/pcre2_chartables.c.
+
+ OR:
+ Compile src/pcre2_dftables.c as a stand-alone program (using
+ -DHAVE_CONFIG_H if you have set up src/config.h), and then run it with
+ the single argument "src/pcre2_chartables.c". This generates a set of
+ standard character tables and writes them to that file. The tables are
+ generated using the default C locale for your system. If you want to use
+ a locale that is specified by LC_xxx environment variables, add the -L
+ option to the pcre2_dftables command. You must use this method if you
+ are building on a system that uses EBCDIC code.
+
+ The tables in src/pcre2_chartables.c are defaults. The caller of PCRE2 can
+ specify alternative tables at run time.
+
+ (4) For a library that supports 8-bit code units in the character strings that
+ it processes, compile the following source files from the src directory,
+ setting -DPCRE2_CODE_UNIT_WIDTH=8 as a compiler option. Also set
+ -DHAVE_CONFIG_H if you have set up src/config.h with your configuration,
+ or else use other -D settings to change the configuration as required.
+
+ pcre2_auto_possess.c
+ pcre2_chkdint.c
+ pcre2_chartables.c
+ pcre2_compile.c
+ pcre2_compile_cgroup.c
+ pcre2_compile_class.c
+ pcre2_config.c
+ pcre2_context.c
+ pcre2_convert.c
+ pcre2_dfa_match.c
+ pcre2_error.c
+ pcre2_extuni.c
+ pcre2_find_bracket.c
+ pcre2_jit_compile.c
+ pcre2_maketables.c
+ pcre2_match.c
+ pcre2_match_data.c
+ pcre2_match_next.c
+ pcre2_newline.c
+ pcre2_ord2utf.c
+ pcre2_pattern_info.c
+ pcre2_script_run.c
+ pcre2_serialize.c
+ pcre2_string_utils.c
+ pcre2_study.c
+ pcre2_substitute.c
+ pcre2_substring.c
+ pcre2_tables.c
+ pcre2_ucd.c
+ pcre2_valid_utf.c
+ pcre2_xclass.c
+
+ Make sure that you include -I. in the compiler command (or equivalent for
+ an unusual compiler) so that all included PCRE2 header files are first
+ sought in the src directory under the current directory. Otherwise you run
+ the risk of picking up a previously-installed file from somewhere else.
+
+ Note that you must compile pcre2_jit_compile.c, even if you have not
+ defined SUPPORT_JIT in src/config.h, because when JIT support is not
+ configured, dummy functions are compiled. When JIT support IS configured,
+ pcre2_jit_compile.c #includes other files from the sljit dependency,
+ all of whose names begin with "sljit".
+
+ Note also that the pcre2_fuzzsupport.c file contains special code that is
+ useful to those who want to run fuzzing tests on the PCRE2 library. Unless
+ you are doing that, you can ignore it.
+
+ (5) Now link all the compiled code into an object library in whichever form
+ your system keeps such libraries. This is the PCRE2 C 8-bit library,
+ typically called something like libpcre2-8. If your system has static and
+ shared libraries, you may have to do this once for each type.
+
+ (6) If you want to build a library that supports 16-bit or 32-bit code units,
+ set 16 or 32 as the value of -DPCRE2_CODE_UNIT_WIDTH when obeying step 4
+ above. If you want to build more than one PCRE2 library, repeat steps 4
+ and 5 as necessary.
+
+ (7) If you want to build the POSIX wrapper functions (which apply only to the
+ 8-bit library), ensure that you have the src/pcre2posix.h file and then
+ compile src/pcre2posix.c. Link the result (on its own) as the pcre2posix
+ library. If targeting a DLL in Windows, make sure to include
+ -DPCRE2POSIX_SHARED with your compiler flags.
+
+ (8) The pcre2test program can be linked with any combination of the 8-bit,
+ 16-bit and 32-bit libraries (depending on what you specfied in
+ src/config.h) . Compile src/pcre2test.c; don't forget -DHAVE_CONFIG_H if
+ necessary, but do NOT define PCRE2_CODE_UNIT_WIDTH. Then link with the
+ appropriate library/ies. If you compiled an 8-bit library, pcre2test also
+ needs the pcre2posix wrapper library when linking.
+
+ (9) Run pcre2test on the testinput files in the testdata directory, and check
+ that the output matches the corresponding testoutput files. There are
+ comments about what each test does in the section entitled "Testing PCRE2"
+ in the README file. If you compiled more than one of the 8-bit, 16-bit and
+ 32-bit libraries, you need to run pcre2test with the -16 option to do
+ 16-bit tests and with the -32 option to do 32-bit tests.
+
+ Some tests are relevant only when certain build-time options are selected.
+ For example, test 4 is for Unicode support, and will not run if you have
+ built PCRE2 without it. See the comments at the start of each testinput
+ file. If you have a suitable Unix-like shell, the RunTest script will run
+ the appropriate tests for you. The command "RunTest list" will output a
+ list of all the tests.
+
+ Note that the supplied files are in Unix format, with just LF characters
+ as line terminators. You may need to edit them to change this if your
+ system uses a different convention.
+
+(10) If you have built PCRE2 with SUPPORT_JIT, the JIT features can be tested
+ by running pcre2test with the -jit option. This is done automatically by
+ the RunTest script. You might also like to build and run the freestanding
+ JIT test program, src/pcre2_jit_test.c.
+
+(11) The pcre2test program tests the POSIX wrapper library, but there is also a
+ freestanding test program in src/pcre2posix_test.c. It must be linked with
+ both the pcre2posix library and the 8-bit PCRE2 library.
+
+(12) If you want to use the pcre2grep command, compile and link
+ src/pcre2grep.c; it uses only the 8-bit PCRE2 library (it does not need
+ the pcre2posix library). If you have built the PCRE2 library with JIT
+ support by defining SUPPORT_JIT in src/config.h, you can also define
+ SUPPORT_PCRE2GREP_JIT, which causes pcre2grep to make use of JIT (unless
+ it is run with --no-jit). If you define SUPPORT_PCRE2GREP_JIT without
+ defining SUPPORT_JIT, pcre2grep does not try to make use of JIT.
+
+
+Stack size in Windows environments
+----------------------------------
+
+Prior to release 10.30 the default system stack size of 1MiB in some Windows
+environments caused issues with some tests. This should no longer be the case
+for 10.30 and later releases.
+
+
+Linking programs in Windows environments
+----------------------------------------
+
+If you want to statically link a program against a PCRE2 library in the form of
+a non-dll .a file, you must define PCRE2_STATIC before including src/pcre2.h.
+
+
+Calling conventions in Windows environments
+-------------------------------------------
+
+It is possible to compile programs to use different calling conventions using
+MSVC. Search the web for "calling conventions" for more information. To make it
+easier to change the calling convention for the exported functions in a
+PCRE2 library, the macro PCRE2_CALL_CONVENTION is present in all the external
+definitions. It can be set externally when compiling (e.g. in CFLAGS). If it is
+not set, it defaults to empty; the default calling convention is then used
+(which is what is wanted most of the time).
+
+
+Comments about Win32 builds (see also "Building PCRE2 on Windows with CMake")
+---------------------------
+
+There are two ways of building PCRE2 using the "configure, make, make install"
+paradigm on Windows systems: using MinGW or using Cygwin. These are not at all
+the same thing; they are completely different from each other. There is also
+support for building using CMake, which some users find a more straightforward
+way of building PCRE2 under Windows.
+
+The MinGW home page (http://www.mingw.org/) says this:
+
+ MinGW: A collection of freely available and freely distributable Windows
+ specific header files and import libraries combined with GNU toolsets that
+ allow one to produce native Windows programs that do not rely on any
+ 3rd-party C runtime DLLs.
+
+The Cygwin home page (http://www.cygwin.com/) says this:
+
+ Cygwin is a Linux-like environment for Windows. It consists of two parts:
+
+ . A DLL (cygwin1.dll) which acts as a Linux API emulation layer providing
+ substantial Linux API functionality
+
+ . A collection of tools which provide Linux look and feel.
+
+On both MinGW and Cygwin, PCRE2 should build correctly using:
+
+ ./configure && make && make install
+
+This should create two libraries called libpcre2-8 and libpcre2-posix. These
+are independent libraries: when you link with libpcre2-posix you must also link
+with libpcre2-8, which contains the basic functions.
+
+Using Cygwin's compiler generates libraries and executables that depend on
+cygwin1.dll. If a library that is generated this way is distributed,
+cygwin1.dll has to be distributed as well. Since cygwin1.dll is under the GPL
+licence, this forces not only PCRE2 to be under the GPL, but also the entire
+application. A distributor who wants to keep their own code proprietary must
+purchase an appropriate Cygwin licence.
+
+MinGW has no such restrictions. The MinGW compiler generates a library or
+executable that can run standalone on Windows without any third party dll or
+licensing issues.
+
+But there is more complication:
+
+If a Cygwin user uses the -mno-cygwin Cygwin gcc flag, what that really does is
+to tell Cygwin's gcc to use the MinGW gcc. Cygwin's gcc is only acting as a
+front end to MinGW's gcc (if you install Cygwin's gcc, you get both Cygwin's
+gcc and MinGW's gcc). So, a user can:
+
+. Build native binaries by using MinGW or by getting Cygwin and using
+ -mno-cygwin.
+
+. Build binaries that depend on cygwin1.dll by using Cygwin with the normal
+ compiler flags.
+
+The test files that are supplied with PCRE2 are in UNIX format, with LF
+characters as line terminators. Unless your PCRE2 library uses a default
+newline option that includes LF as a valid newline, it may be necessary to
+change the line terminators in the test files to get some of the tests to work.
+
+
+Building PCRE2 on Windows with CMake
+------------------------------------
+
+CMake is an alternative configuration facility that can be used instead of
+"configure". CMake creates project files (make files, solution files, etc.)
+tailored to numerous development environments, including Visual Studio,
+Borland, Msys, MinGW, NMake, and Unix. If possible, use short paths with no
+spaces in the names for your CMake installation and your PCRE2 source and build
+directories.
+
+If you are using CMake and encounter errors, deleting the CMake cache and
+restarting from a fresh build may fix the error. In the CMake GUI, the cache can
+be deleted by selecting "File > Delete Cache"; or the folder "CMakeCache" can
+be deleted.
+
+1. Install the latest CMake version available from http://www.cmake.org/, and
+ ensure that cmake\bin is on your path.
+
+2. Unzip (retaining folder structure) the PCRE2 source tree into a source
+ directory such as C:\pcre2. You should ensure your local date and time
+ is not earlier than the file dates in your source dir if the release is
+ very new.
+
+3. Create a new, empty build directory, preferably a subdirectory of the
+ source dir. For example, C:\pcre2\pcre2-xx\build.
+
+4. Run CMake.
+
+ - Using the CLI, simply run `cmake ..` inside the `build/` directory. You can
+ use the `ccmake` ncurses GUI to select and configure PCRE2 features.
+
+ - Using the CMake GUI:
+
+ a) Run cmake-gui from the Shell environment of your build tool, for
+ example, Msys for Msys/MinGW or Visual Studio Command Prompt for
+ VC/VC++.
+
+ b) Enter C:\pcre2\pcre2-xx and C:\pcre2\pcre2-xx\build for the source and
+ build directories, respectively.
+
+ c) Press the "Configure" button.
+
+ d) Select the particular IDE / build tool that you are using (Visual
+ Studio, MSYS makefiles, MinGW makefiles, etc.)
+
+ e) The GUI will then list several configuration options. This is where
+ you can disable Unicode support or select other PCRE2 optional features.
+
+ f) Press "Configure" again. The adjacent "Generate" button should now be
+ active.
+
+ g) Press "Generate".
+
+5. The build directory should now contain a usable build system, be it a
+ solution file for Visual Studio, makefiles for MinGW, etc. Exit from
+ cmake-gui and use the generated build system with your compiler or IDE.
+ E.g., for MinGW you can run "make", or for Visual Studio, open the PCRE2
+ solution, select the desired configuration (Debug, or Release, etc.) and
+ build the ALL_BUILD project.
+
+ Regardless of build system used, `cmake --build .` will build it.
+
+6. If during configuration with cmake-gui you've elected to build the test
+ programs, you can execute them by building the test project. E.g., for
+ MinGW: "make test"; for Visual Studio build the RUN_TESTS project. The
+ most recent build configuration is targeted by the tests. A summary of
+ test results is presented. Complete test output is subsequently
+ available for review in Testing\Temporary under your build dir.
+
+ Regardless of build system used, `ctest` will run the tests.
+
+
+Building PCRE2 on Windows with Visual Studio
+--------------------------------------------
+
+The code currently cannot be compiled without an inttypes.h header, which is
+available only with Visual Studio 2013 or newer. However, this portable and
+permissively-licensed implementation of the stdint.h header could be used as an
+alternative:
+
+ http://www.azillionmonkeys.com/qed/pstdint.h
+
+Just rename it and drop it into the top level of the build tree.
+
+
+Testing with RunTest.bat
+------------------------
+
+If configured with CMake, building the test project ("make test" or building
+ALL_TESTS in Visual Studio) creates (and runs) pcre2_test.bat (and depending
+on your configuration options, possibly other test programs) in the build
+directory. The pcre2_test.bat script runs RunTest.bat with correct source and
+exe paths.
+
+For manual testing with RunTest.bat, provided the build dir is a subdirectory
+of the source directory: Open command shell window. Chdir to the location
+of your pcre2test.exe and pcre2grep.exe programs. Call RunTest.bat with
+"..\RunTest.Bat" or "..\..\RunTest.bat" as appropriate.
+
+To run only a particular test with RunTest.Bat provide a test number argument.
+
+Otherwise:
+
+1. Copy RunTest.bat into the directory where pcre2test.exe and pcre2grep.exe
+ have been created.
+
+2. Edit RunTest.bat to identify the full or relative location of
+ the pcre2 source (wherein which the testdata folder resides), e.g.:
+
+ set srcdir=C:\pcre2\pcre2-10.00
+
+3. In a Windows command environment, chdir to the location of your bat and
+ exe programs.
+
+4. Run RunTest.bat. Test outputs will automatically be compared to expected
+ results, and discrepancies will be identified in the console output.
+
+To independently test the just-in-time compiler, run pcre2_jit_test.exe.
+
+
+Building PCRE2 on z/OS and z/VM
+-------------------------------
+
+z/OS and z/VM are operating systems for mainframe computers, produced by IBM.
+The character code used is EBCDIC, not ASCII or Unicode. In z/OS, UNIX APIs and
+applications can be supported through UNIX System Services.
+
+The PCRE2 codebase compiles and runs with native EBCDIC support on modern z/OS
+systems, using the pre-installed tools (/bin/sh, ./configure, and the XLC or
+IBM-Clang compilers). PCRE2 supports z/OS using both Autoconf (./configure) and
+CMake (which IBM distributes via "zopen install cmake").
+
+Note that as of the time of writing, IBM's port of CMake to z/OS has only
+partial support for EBCDIC. It is recommended to build PCRE2 using the
+./configure script, if you require an EBCDIC build.
+
+Any EBCDIC codepage should work (PCRE2 does not assume or require IBM-1047), or
+PCRE2 can compiled for ASCII/Latin-1/Unicode.
+
+After unpacking the PCRE2 tarball, you must subsequently tag the files as ASCII
+in order for the z/OS shell and compiler to interpret them correctly:
+ chtag -R -tc ISO8859-1
+
+Some unusual features on the IBM platform are:
+ - The _ALL_SOURCE macro must be provided. Unlike on Linux or macOS, even quite
+ standard POSIX APIs are not made visible by default. PCRE2's Autoconf and
+ CMake system both provide this for you.
+ - The `cc`, `c89`, and even `c99` compilers provided by IBM do not default to
+ the same argument ordering as other Unix platforms.
+ - The XLC compiler requires `-qhaltonmsg=CCN3296`, otherwise it will treat any
+ preprocessor #include errors as a warning rather than an error. Needless to
+ say this default wrecks Autoconf and CMake's feature-detection tests.
+ PCRE2's build system is aware of this.
+ - The test suite (in the testdata/ directory) is entirely in ASCII/UTF-8.
+ When running the tests, you must ensure that the EBCDIC-native build of
+ pcre2test receives an EBCDIC version of these files. The easiest way to
+ achieve this is via filesystem tagging (chtag). Alternatively, you could
+ manually re-encode the testdata files as EBCDIC, and tag them as EBCDIC.
+ (Latin-1 and EBCDIC are one-to-one convertible encodings, a simple
+ byte-by-byte permutation of the 256 values.)
+
+In native z/OS (without UNIX System Services) and in z/VM, a user has provided a
+special port of PCRE2. For details, please see file 939 on this web site:
+
+ http://www.cbttape.org
+
+The user-provided port also provides an API for LE languages such as COBOL and
+for the z/OS and z/VM versions of the Rexx languages.
+
+
+Building PCRE2 under VMS
+------------------------
+
+Alexey Chuphin has contributed some auxiliary files for building PCRE2 under
+OpenVMS. They are in the "vms" directory in the distribution tarball. Please
+read the file called vms/openvms_readme.txt. The pcre2test and pcre2grep
+programs contain some VMS-specific code.
+
+This has not been tested for some time. The PCRE2 maintainers would be grateful
+to learn whether it still works (or if anyone still uses it).
+
+
+=============================
+Last updated: 17 October 2025
+=============================
+
diff --git a/doc/html/README.txt b/doc/html/README.txt
new file mode 100644
index 0000000..3adf495
--- /dev/null
+++ b/doc/html/README.txt
@@ -0,0 +1,1008 @@
+README file for PCRE2 (Perl-compatible regular expression library)
+==================================================================
+
+PCRE2 is a re-working of the original PCRE1 library to provide an entirely new
+API. Since its initial release in 2015, there has been further development of
+the code and it now differs from PCRE1 in more than just the API. There are new
+features, and the internals have been improved. The original PCRE1 library is
+now obsolete and no longer maintained. The latest release of PCRE2 is available
+in .tar.gz, tar.bz2, or .zip form from this GitHub repository:
+
+https://github.com/PCRE2Project/pcre2/releases
+
+There is a mailing list for discussion about the development of PCRE2 at
+pcre2-dev@googlegroups.com. You can subscribe by sending an email to
+pcre2-dev+subscribe@googlegroups.com.
+
+You can access the archives and also subscribe or manage your subscription
+here:
+
+https://groups.google.com/g/pcre2-dev
+
+Please read the NEWS file if you are upgrading from a previous release. The
+contents of this README file are:
+
+ The PCRE2 APIs
+ Documentation for PCRE2
+ Building PCRE2 on non-Unix-like systems
+ Building PCRE2 without using autotools
+ Building PCRE2 using autotools
+ Retrieving configuration information
+ Shared libraries
+ Cross-compiling using autotools
+ Making new tarballs
+ Testing PCRE2
+ Character tables
+ File manifest
+
+
+The PCRE2 APIs
+--------------
+
+PCRE2 is written in C, and it has its own API. There are three sets of
+functions, one for the 8-bit library, which processes strings of bytes, one for
+the 16-bit library, which processes strings of 16-bit values, and one for the
+32-bit library, which processes strings of 32-bit values. Unlike PCRE1, there
+are no C++ wrappers.
+
+The distribution does contain a set of C wrapper functions for the 8-bit
+library that are based on the POSIX regular expression API (see the pcre2posix
+man page). These are built into a library called libpcre2-posix. Note that this
+just provides a POSIX calling interface to PCRE2; the regular expressions
+themselves still follow Perl syntax and semantics. The POSIX API is restricted,
+and does not give full access to all of PCRE2's facilities.
+
+The header file for the POSIX-style functions is called pcre2posix.h. The
+official POSIX name is regex.h, but I did not want to risk possible problems
+with existing files of that name by distributing it that way. To use PCRE2 with
+an existing program that uses the POSIX API, pcre2posix.h will have to be
+renamed or pointed at by a link (or the program modified, of course). See the
+pcre2posix documentation for more details.
+
+
+Documentation for PCRE2
+-----------------------
+
+If you install PCRE2 in the normal way on a Unix-like system, you will end up
+with a set of man pages whose names all start with "pcre2". The one that is
+just called "pcre2" lists all the others. In addition to these man pages, the
+PCRE2 documentation is supplied in two other forms:
+
+ 1. There are files called doc/pcre2.txt, doc/pcre2grep.txt, and
+ doc/pcre2test.txt in the source distribution. The first of these is a
+ concatenation of the text forms of all the section 3 man pages except the
+ listing of pcre2demo.c and those that summarize individual functions. The
+ other two are the text forms of the section 1 man pages for the pcre2grep
+ and pcre2test commands. These text forms are provided for ease of scanning
+ with text editors or similar tools. They are installed in
+ /share/doc/pcre2, where is the installation prefix
+ (defaulting to /usr/local).
+
+ 2. A set of files containing all the documentation in HTML form, hyperlinked
+ in various ways, and rooted in a file called index.html, is distributed in
+ doc/html and installed in /share/doc/pcre2/html.
+
+
+Building PCRE2 on non-Unix-like systems
+---------------------------------------
+
+For a non-Unix-like system, please read the file NON-AUTOTOOLS-BUILD, though if
+your system supports the use of "configure" and "make" you may be able to build
+PCRE2 using autotools in the same way as for many Unix-like systems. This file
+also contains useful information on building for some unusual Unix environments
+(such as EBCDIC mainframes).
+
+PCRE2 can also be configured using CMake, which can be run in various ways
+(command line, GUI, etc). This creates Makefiles, solution files, etc. The file
+NON-AUTOTOOLS-BUILD has information about CMake.
+
+PCRE2 has been compiled on many different operating systems. It should be
+straightforward to build PCRE2 on any system that has a C99 or later compiler
+and library.
+
+
+Building PCRE2 without using autotools
+--------------------------------------
+
+The use of autotools (in particular, libtool) is problematic in some
+environments, even some that are Unix or Unix-like. See the NON-AUTOTOOLS-BUILD
+file for ways of building PCRE2 without using autotools.
+
+
+Building PCRE2 using autotools
+------------------------------
+
+The following instructions assume the use of the widely used "configure; make;
+make install" (autotools) process.
+
+If you have downloaded and unpacked a PCRE2 release tarball, run the
+"configure" command from the PCRE2 directory, with your current directory set
+to the directory where you want the files to be created. This command is a
+standard GNU "autoconf" configuration script, for which generic instructions
+are supplied in the file INSTALL.
+
+The files in the GitHub repository do not contain "configure". If you have
+downloaded the PCRE2 source files from GitHub, before you can run "configure"
+you must run the shell script called autogen.sh. This runs a number of
+autotools to create a "configure" script (you must of course have the autotools
+commands installed in order to do this).
+
+Most commonly, people build PCRE2 within its own distribution directory, and in
+this case, on many systems, just running "./configure" is sufficient. However,
+the usual methods of changing standard defaults are available. For example:
+
+CFLAGS='-O2 -Wall' ./configure --prefix=/opt/local
+
+This command specifies that the C compiler should be run with the flags '-O2
+-Wall' instead of the default, and that "make install" should install PCRE2
+under /opt/local instead of the default /usr/local.
+
+If you want to build in a different directory, just run "configure" with that
+directory as current. For example, suppose you have unpacked the PCRE2 source
+into /source/pcre2/pcre2-xxx, but you want to build it in
+/build/pcre2/pcre2-xxx:
+
+cd /build/pcre2/pcre2-xxx
+/source/pcre2/pcre2-xxx/configure
+
+PCRE2 is written in C and is normally compiled as a C library. However, it is
+possible to build it as a C++ library, though the provided building apparatus
+does not have any features to support this.
+
+There are some optional features that can be included or omitted from the PCRE2
+library. They are also documented in the pcre2build man page.
+
+. By default, both shared and static libraries are built. You can change this
+ by adding one of these options to the "configure" command:
+
+ --disable-shared
+ --disable-static
+
+ Setting --disable-shared ensures that PCRE2 libraries are built as static
+ libraries. The binaries that are then created as part of the build process
+ (for example, pcre2test and pcre2grep) are linked statically with one or more
+ PCRE2 libraries, but may also be dynamically linked with other libraries such
+ as libc. If you want these binaries to be fully statically linked, you can
+ set LDFLAGS like this:
+
+ LDFLAGS=--static ./configure --disable-shared
+
+ Note the two hyphens in --static. Of course, this works only if static
+ versions of all the relevant libraries are available for linking. See also
+ "Shared libraries" below.
+
+ Shared libraries are compiled with symbol versioning enabled on platforms that
+ support this, but this can be disabled by adding --disable-symvers.
+
+. By default, only the 8-bit library is built. If you add --enable-pcre2-16 to
+ the "configure" command, the 16-bit library is also built. If you add
+ --enable-pcre2-32 to the "configure" command, the 32-bit library is also
+ built. If you want only the 16-bit or 32-bit library, use --disable-pcre2-8
+ to disable building the 8-bit library.
+
+. If you want to include support for just-in-time (JIT) compiling, which can
+ give large performance improvements on certain platforms, add --enable-jit to
+ the "configure" command. This support is available only for certain hardware
+ architectures. If you try to enable it on an unsupported architecture, there
+ will be a compile time error. If in doubt, use --enable-jit=auto, which
+ enables JIT only if the current hardware is supported.
+
+. If you are enabling JIT under SELinux environment you may also want to add
+ --enable-jit-sealloc, which enables the use of an executable memory allocator
+ that is compatible with SELinux. Warning: this allocator is experimental!
+ It does not support fork() operation and may crash when no disk space is
+ available. This option has no effect if JIT is disabled.
+
+. If you do not want to make use of the default support for UTF-8 Unicode
+ character strings in the 8-bit library, UTF-16 Unicode character strings in
+ the 16-bit library, or UTF-32 Unicode character strings in the 32-bit
+ library, you can add --disable-unicode to the "configure" command. This
+ reduces the size of the libraries. It is not possible to configure one
+ library with Unicode support, and another without, in the same configuration.
+ It is also not possible to use --enable-ebcdic (see below) with Unicode
+ support, so if this option is set, you must also use --disable-unicode.
+
+ When Unicode support is available, the use of a UTF encoding still has to be
+ enabled by setting the PCRE2_UTF option at run time or starting a pattern
+ with (*UTF). When PCRE2 is compiled with Unicode support, its input can only
+ either be ASCII or UTF-8/16/32, even when running on EBCDIC platforms.
+
+ As well as supporting UTF strings, Unicode support includes support for the
+ \P, \p, and \X sequences that recognize Unicode character properties.
+ However, only a subset of Unicode properties are supported; see the
+ pcre2pattern man page for details. Escape sequences such as \d and \w in
+ patterns do not by default make use of Unicode properties, but can be made to
+ do so by setting the PCRE2_UCP option or starting a pattern with (*UCP).
+
+. You can build PCRE2 to recognize either CR or LF or the sequence CRLF, or any
+ of the preceding, or any of the Unicode newline sequences, or the NUL (zero)
+ character as indicating the end of a line. Whatever you specify at build time
+ is the default; the caller of PCRE2 can change the selection at run time. The
+ default newline indicator is a single LF character (the Unix standard). You
+ can specify the default newline indicator by adding --enable-newline-is-cr,
+ --enable-newline-is-lf, --enable-newline-is-crlf,
+ --enable-newline-is-anycrlf, --enable-newline-is-any, or
+ --enable-newline-is-nul to the "configure" command, respectively.
+
+. By default, the sequence \R in a pattern matches any Unicode line ending
+ sequence. This is independent of the option specifying what PCRE2 considers
+ to be the end of a line (see above). However, the caller of PCRE2 can
+ restrict \R to match only CR, LF, or CRLF. You can make this the default by
+ adding --enable-bsr-anycrlf to the "configure" command (bsr = "backslash R").
+
+. In a pattern, the escape sequence \C matches a single code unit, even in a
+ UTF mode. This can be dangerous because it breaks up multi-code-unit
+ characters. You can build PCRE2 with the use of \C permanently locked out by
+ adding --enable-never-backslash-C (note the upper case C) to the "configure"
+ command. When \C is allowed by the library, individual applications can lock
+ it out by calling pcre2_compile() with the PCRE2_NEVER_BACKSLASH_C option.
+
+. PCRE2 has a counter that limits the depth of nesting of parentheses in a
+ pattern. This limits the amount of system stack that a pattern uses when it
+ is compiled. The default is 250, but you can change it by setting, for
+ example,
+
+ --with-parens-nest-limit=500
+
+. PCRE2 has a counter that can be set to limit the amount of computing resource
+ it uses when matching a pattern. If the limit is exceeded during a match, the
+ match fails. The default is ten million. You can change the default by
+ setting, for example,
+
+ --with-match-limit=500000
+
+ on the "configure" command. This is just the default; individual calls to
+ pcre2_match() or pcre2_dfa_match() can supply their own value. There is more
+ discussion in the pcre2api man page (search for pcre2_set_match_limit).
+
+. There is a separate counter that limits the depth of nested backtracking
+ (pcre2_match()) or nested function calls (pcre2_dfa_match()) during a
+ matching process, which indirectly limits the amount of heap memory that is
+ used, and in the case of pcre2_dfa_match() the amount of stack as well. This
+ counter also has a default of ten million, which is essentially "unlimited".
+ You can change the default by setting, for example,
+
+ --with-match-limit-depth=5000
+
+ There is more discussion in the pcre2api man page (search for
+ pcre2_set_depth_limit).
+
+. You can also set an explicit limit on the amount of heap memory used by
+ the pcre2_match() and pcre2_dfa_match() interpreters:
+
+ --with-heap-limit=500
+
+ The units are kibibytes (units of 1024 bytes). This limit does not apply when
+ the JIT optimization (which has its own memory control features) is used.
+ There is more discussion on the pcre2api man page (search for
+ pcre2_set_heap_limit).
+
+. In the 8-bit library, the default maximum compiled pattern size is around
+ 64 kibibytes. You can increase this by adding --with-link-size=3 to the
+ "configure" command. PCRE2 then uses three bytes instead of two for offsets
+ to different parts of the compiled pattern. In the 16-bit library,
+ --with-link-size=3 is the same as --with-link-size=4, which (in both
+ libraries) uses four-byte offsets. Increasing the internal link size reduces
+ performance in the 8-bit and 16-bit libraries. In the 32-bit library, the
+ link size setting is ignored, as 4-byte offsets are always used.
+
+. Lookbehind assertions in which one or more branches can match a variable
+ number of characters are supported only if there is a maximum matching length
+ for each top-level branch. There is a limit to this maximum that defaults to
+ 255 characters. You can alter this default by a setting such as
+
+ --with-max-varlookbehind=100
+
+ The limit can be changed at runtime by calling pcre2_set_max_varlookbehind().
+ Lookbehind assertions in which every branch matches a fixed number of
+ characters (not necessarily all the same) are not constrained by this limit.
+
+. For speed, PCRE2 uses four tables for manipulating and identifying characters
+ whose code point values are less than 256. By default, it uses a set of
+ tables for ASCII encoding that is part of the distribution. If you specify
+
+ --enable-rebuild-chartables
+
+ a program called pcre2_dftables is compiled and run in the default C locale
+ when you obey "make". It builds a source file called pcre2_chartables.c. If
+ you do not specify this option, pcre2_chartables.c is created as a copy of
+ pcre2_chartables.c.dist. See "Character tables" below for further
+ information.
+
+. It is possible to compile PCRE2 for use on systems that use EBCDIC as their
+ character code (as opposed to ASCII/Unicode) by specifying
+
+ --enable-ebcdic --disable-unicode
+
+ This automatically implies --enable-rebuild-chartables (see above), in order
+ to ensure that you have the correct default character tables for your system's
+ codepage. There is an exception when you set --enable-ebcdic-ignoring-compiler
+ (see below), which allows using a default set of EBCDIC 1047 character tables
+ rather than forcing use of --enable-rebuild-chartables.
+
+ When PCRE2 is built with EBCDIC support, it always operates in EBCDIC. It
+ cannot support both EBCDIC and ASCII or UTF-8/16/32.
+
+ There is a second option, --enable-ebcdic-nl25, which specifies that the code
+ value for the EBCDIC NL character is 0x25 instead of the default 0x15.
+
+ There is a third option, --enable-ebcdic-ignoring-compiler, which disregards
+ the compiler's codepage for determining the numeric value of C character
+ constants such as 'z', and instead forces PCRE2 to use numeric constants for
+ the EBCDIC 1047 codepage instead.
+
+. If you specify --enable-debug, additional debugging code is included in the
+ build. This option is intended for use by the PCRE2 maintainers.
+
+. In environments where valgrind is installed, if you specify
+
+ --enable-valgrind
+
+ PCRE2 will use valgrind annotations to mark certain memory regions as
+ unaddressable. This allows it to detect invalid memory accesses, and is
+ mostly useful for debugging PCRE2 itself.
+
+. In environments where the gcc compiler is used and lcov is installed, if you
+ specify
+
+ --enable-coverage
+
+ the build process implements a code coverage report for the test suite. The
+ report is generated by running "make coverage". If ccache is installed on
+ your system, it must be disabled when building PCRE2 for coverage reporting.
+ You can do this by setting the environment variable CCACHE_DISABLE=1 before
+ running "make" to build PCRE2. There is more information about coverage
+ reporting in the "pcre2build" documentation.
+
+. When JIT support is enabled, pcre2grep automatically makes use of it, unless
+ you add --disable-pcre2grep-jit to the "configure" command.
+
+. There is support for calling external programs during matching in the
+ pcre2grep command, using PCRE2's callout facility with string arguments. This
+ support can be disabled by adding --disable-pcre2grep-callout to the
+ "configure" command. There are two kinds of callout: one that generates
+ output from inbuilt code, and another that calls an external program. The
+ latter has special support for Windows and VMS; otherwise it assumes the
+ existence of the fork() function. This facility can be disabled by adding
+ --disable-pcre2grep-callout-fork to the "configure" command.
+
+. The pcre2grep program currently supports only 8-bit data files, and so
+ requires the 8-bit PCRE2 library. It is possible to compile pcre2grep to use
+ libz and/or libbz2, in order to read .gz and .bz2 files (respectively), by
+ specifying one or both of
+
+ --enable-pcre2grep-libz
+ --enable-pcre2grep-libbz2
+
+ Of course, the relevant libraries must be installed on your system.
+
+. The default starting size (in bytes) of the internal buffer used by pcre2grep
+ can be set by, for example:
+
+ --with-pcre2grep-bufsize=51200
+
+ The value must be a plain integer. The default is 20480. The amount of memory
+ used by pcre2grep is actually three times this number, to allow for "before"
+ and "after" lines. If very long lines are encountered, the buffer is
+ automatically enlarged, up to a fixed maximum size.
+
+. The default maximum size of pcre2grep's internal buffer can be set by, for
+ example:
+
+ --with-pcre2grep-max-bufsize=2097152
+
+ The default is either 1048576 or the value of --with-pcre2grep-bufsize,
+ whichever is the larger.
+
+. It is possible to compile pcre2test so that it links with the libreadline
+ or libedit libraries, by specifying, respectively,
+
+ --enable-pcre2test-libreadline or --enable-pcre2test-libedit
+
+ If this is done, when pcre2test's input is from a terminal, it reads it using
+ the readline() function. This provides line-editing and history facilities.
+ Note that libreadline is GPL-licensed, so if you distribute a binary of
+ pcre2test linked in this way, there may be licensing issues. These can be
+ avoided by linking with libedit (which has a BSD licence) instead.
+
+ Enabling libreadline causes the -lreadline option to be added to the
+ pcre2test build. In many operating environments with a system-installed
+ readline library this is sufficient. However, in some environments (e.g. if
+ an unmodified distribution version of readline is in use), it may be
+ necessary to specify something like LIBS="-lncurses" as well. This is
+ because, to quote the readline INSTALL, "Readline uses the termcap functions,
+ but does not link with the termcap or curses library itself, allowing
+ applications which link with readline the option to choose an appropriate
+ library." If you get error messages about missing functions tgetstr, tgetent,
+ tputs, tgetflag, or tgoto, this is the problem, and linking with the ncurses
+ library should fix it.
+
+. The C99 standard defines formatting modifiers z and t for size_t and
+ ptrdiff_t values, respectively. By default, PCRE2 uses these modifiers in
+ environments other than Microsoft Visual Studio versions earlier than 2013
+ when __STDC_VERSION__ is defined and has a value greater than or equal to
+ 199901L (indicating C99). However, there is at least one environment that
+ claims to be C99 but does not support these modifiers. If
+ --disable-percent-zt is specified, no use is made of the z or t modifiers.
+ Instead of %td or %zu, %lu is used, with a cast for size_t values.
+
+. There is a special option called --enable-fuzz-support for use by people who
+ want to run fuzzing tests on PCRE2. If set, it causes an extra library
+ called libpcre2-fuzzsupport.a to be built, but not installed. This contains
+ a single function called LLVMFuzzerTestOneInput() whose arguments are a
+ pointer to a string and the length of the string. When called, this function
+ tries to compile the string as a pattern, and if that succeeds, to match
+ it. This is done both with no options and with some random options bits that
+ are generated from the string. Setting --enable-fuzz-support also causes an
+ executable called pcre2fuzzcheck-{8,16,32} to be created. This is normally
+ run under valgrind or used when PCRE2 is compiled with address sanitizing
+ enabled. It calls the fuzzing function and outputs information about what it
+ is doing. The input strings are specified by arguments: if an argument
+ starts with "=" the rest of it is a literal input string. Otherwise, it is
+ assumed to be a file name, and the contents of the file are the test string.
+
+. Releases before 10.30 could be compiled with --disable-stack-for-recursion,
+ which caused pcre2_match() to use individual blocks on the heap for
+ backtracking instead of recursive function calls (which use the stack). This
+ is now obsolete because pcre2_match() was refactored always to use the heap
+ (in a much more efficient way than before). This option is retained for
+ backwards compatibility, but has no effect other than to output a warning.
+
+The "configure" script builds the following files for the basic C library:
+
+. Makefile the makefile that builds the library
+. src/config.h build-time configuration options for the library
+. src/pcre2.h the public PCRE2 header file
+. pcre2-config script that shows the building settings such as CFLAGS
+ that were set for "configure"
+. libpcre2-8.pc )
+. libpcre2-16.pc ) data for the pkg-config command
+. libpcre2-32.pc )
+. libpcre2-posix.pc )
+. libtool script that builds shared and/or static libraries
+
+Versions of config.h and pcre2.h are distributed in the src directory of PCRE2
+tarballs under the names config.h.generic and pcre2.h.generic. These are
+provided for those who have to build PCRE2 without using "configure" or CMake.
+If you use "configure" or CMake, the .generic versions are not used.
+
+The "configure" script also creates config.status, which is an executable
+script that can be run to recreate the configuration, and config.log, which
+contains compiler output from tests that "configure" runs.
+
+Once "configure" has run, you can run "make". This builds whichever of the
+libraries libpcre2-8, libpcre2-16 and libpcre2-32 are configured, and a test
+program called pcre2test. If you enabled JIT support with --enable-jit, another
+test program called pcre2_jit_test is built as well. If the 8-bit library is
+built, libpcre2-posix, pcre2posix_test, and the pcre2grep command are also
+built. Running "make" with the -j option may speed up compilation on
+multiprocessor systems.
+
+The command "make check" runs all the appropriate tests. Details of the PCRE2
+tests are given below in a separate section of this document. The -j option of
+"make" can also be used when running the tests.
+
+You can use "make install" to install PCRE2 into live directories on your
+system. The following are installed (file names are all relative to the
+ that is set when "configure" is run):
+
+ Commands (bin):
+ pcre2test
+ pcre2grep (if 8-bit support is enabled)
+ pcre2-config
+
+ Libraries (lib):
+ libpcre2-8 (if 8-bit support is enabled)
+ libpcre2-16 (if 16-bit support is enabled)
+ libpcre2-32 (if 32-bit support is enabled)
+ libpcre2-posix (if 8-bit support is enabled)
+
+ Configuration information (lib/pkgconfig):
+ libpcre2-8.pc
+ libpcre2-16.pc
+ libpcre2-32.pc
+ libpcre2-posix.pc
+
+ Header files (include):
+ pcre2.h
+ pcre2posix.h
+
+ Man pages (share/man/man{1,3}):
+ pcre2grep.1
+ pcre2test.1
+ pcre2-config.1
+ pcre2.3
+ pcre2*.3 (lots more pages, all starting "pcre2")
+
+ HTML documentation (share/doc/pcre2/html):
+ index.html
+ *.html (lots more pages, hyperlinked from index.html)
+
+ Text file documentation (share/doc/pcre2):
+ AUTHORS.md
+ COPYING
+ ChangeLog
+ LICENCE.md
+ NEWS
+ README
+ SECURITY.md
+ SUPPORT-LIFECYCLE.md
+ pcre2.txt (a concatenation of the man(3) pages)
+ pcre2test.txt the pcre2test man page
+ pcre2grep.txt the pcre2grep man page
+ pcre2-config.txt the pcre2-config man page
+
+If you want to remove PCRE2 from your system, you can run "make uninstall".
+This removes all the files that "make install" installed. However, it does not
+remove any directories, because these are often shared with other programs.
+
+
+Retrieving configuration information
+------------------------------------
+
+Running "make install" installs the command pcre2-config, which can be used to
+recall information about the PCRE2 configuration and installation. For example:
+
+ pcre2-config --version
+
+prints the version number, and
+
+ pcre2-config --libs8
+
+outputs information about where the 8-bit library is installed. This command
+can be included in makefiles for programs that use PCRE2, saving the programmer
+from having to remember too many details. Run pcre2-config with no arguments to
+obtain a list of possible arguments.
+
+The pkg-config command is another system for saving and retrieving information
+about installed libraries. Instead of separate commands for each library, a
+single command is used. For example:
+
+ pkg-config --libs libpcre2-16
+
+The data is held in *.pc files that are installed in a directory called
+/lib/pkgconfig.
+
+
+Shared libraries
+----------------
+
+The default distribution builds PCRE2 as shared libraries and static libraries,
+as long as the operating system supports shared libraries. Shared library
+support relies on the "libtool" script which is built as part of the
+"configure" process.
+
+The libtool script is used to compile and link both shared and static
+libraries. They are placed in a subdirectory called .libs when they are newly
+built. The programs pcre2test and pcre2grep are built to use these uninstalled
+libraries (by means of wrapper scripts in the case of shared libraries). When
+you use "make install" to install shared libraries, pcre2grep and pcre2test are
+automatically re-built to use the newly installed shared libraries before being
+installed themselves. However, the versions left in the build directory still
+use the uninstalled libraries.
+
+To build PCRE2 using static libraries only you must use --disable-shared when
+configuring it. For example:
+
+./configure --prefix=/usr/gnu --disable-shared
+
+Then run "make" in the usual way. Similarly, you can use --disable-static to
+build only shared libraries. Note, however, that when you build only static
+libraries, binary programs such as pcre2test and pcre2grep may still be
+dynamically linked with other libraries (for example, libc) unless you set
+LDFLAGS to --static when running "configure".
+
+
+Cross-compiling using autotools
+-------------------------------
+
+You can specify CC and CFLAGS in the normal way to the "configure" command, in
+order to cross-compile PCRE2 for some other host. However, you should NOT
+specify --enable-rebuild-chartables, because if you do, the pcre2_dftables.c
+source file is compiled and run on the local host, in order to generate the
+inbuilt character tables (the pcre2_chartables.c file). This will probably not
+work, because pcre2_dftables.c needs to be compiled with the local compiler,
+not the cross compiler.
+
+When --enable-rebuild-chartables is not specified, pcre2_chartables.c is
+created by making a copy of pcre2_chartables.c.dist, which is a default set of
+tables that assumes ASCII code. Cross-compiling with the default tables should
+not be a problem.
+
+If you need to modify the character tables when cross-compiling, you should
+move pcre2_chartables.c.dist out of the way, then compile pcre2_dftables.c by
+hand and run it on the local host to make a new version of
+pcre2_chartables.c.dist. See the pcre2build section "Creating character tables
+at build time" for more details.
+
+
+Making new tarballs
+-------------------
+
+The command "make dist" creates three PCRE2 tarballs, in tar.gz, tar.bz2, and
+zip formats. The command "make distcheck" does the same, but then does a trial
+build of the new distribution to ensure that it works.
+
+If you have modified any of the man page sources in the doc directory, you
+should first run the maint/UpdateAlways script before making a distribution.
+This script creates the .txt and HTML forms of the documentation from the man
+pages.
+
+
+Testing PCRE2
+-------------
+
+To test the basic PCRE2 library on a Unix-like system, run the RunTest script.
+There is another script called RunGrepTest that tests the pcre2grep command.
+When the 8-bit library is built, a test program for the POSIX wrapper, called
+pcre2posix_test, is compiled, and when JIT support is enabled, a test program
+called pcre2_jit_test is built. The scripts and the program tests are all run
+when you obey "make check". For other environments, see the instructions in
+NON-AUTOTOOLS-BUILD.
+
+The RunTest script runs the pcre2test test program (which is documented in its
+own man page) on each of the relevant testinput files in the testdata
+directory, and compares the output with the contents of the corresponding
+testoutput files. RunTest places its output in directories
+testoutput{8,16,32}{,-jit,-dfa}. Other files whose names begin with "test" are
+used as working files in some tests.
+
+Some tests are relevant only when certain build-time options were selected. For
+example, the tests for UTF-8/16/32 features are run only when Unicode support
+is available. RunTest outputs a comment when it skips a test.
+
+Many (but not all) of the tests that are not skipped are run twice if JIT
+support is available. On the second run, JIT compilation is forced. This
+testing can be suppressed by putting "-nojit" on the RunTest command line.
+
+The entire set of tests is run once for each of the 8-bit, 16-bit and 32-bit
+libraries that are enabled. If you want to run just one set of tests, call
+RunTest with either the -8, -16 or -32 option.
+
+If valgrind is installed, you can run the tests under it by putting "-valgrind"
+on the RunTest command line. To run pcre2test on just one or more specific test
+files, give their numbers as arguments to RunTest, for example:
+
+ RunTest 2 7 11
+
+You can also specify ranges of tests such as 3-6 or 3- (meaning 3 to the
+end), or a number preceded by ~ to exclude a test. For example:
+
+ Runtest 3-15 ~10
+
+This runs tests 3 to 15, excluding test 10, and just ~13 runs all the tests
+except test 13. Whatever order the arguments are in, the tests are always run
+in numerical order.
+
+You can also call RunTest with the single argument "list" to cause it to output
+a list of tests.
+
+The test sequence starts with "test 0", which is a special test that has no
+input file, and whose output is not checked. This is because it will be
+different on different hardware and with different configurations. The test
+exists in order to exercise some of pcre2test's code that would not otherwise
+be run.
+
+Tests 1 and 2 can always be run, as they expect only plain text strings (not
+UTF) and make no use of Unicode properties. The first test file can be fed
+directly into the perltest.sh script to check that Perl gives the same results.
+The only difference you should see is in the first few lines, where the Perl
+version is given instead of the PCRE2 version. The second set of tests check
+auxiliary functions, error detection, and run-time flags that are specific to
+PCRE2. It also uses the debugging flags to check some of the internals of
+pcre2_compile().
+
+If you build PCRE2 with a locale setting that is not the standard C locale, the
+character tables may be different (see next paragraph). In some cases, this may
+cause failures in the second set of tests. For example, in a locale where the
+isprint() function yields TRUE for characters in the range 128-255, the use of
+[:isascii:] inside a character class defines a different set of characters, and
+this shows up in this test as a difference in the compiled code, which is being
+listed for checking. For example, where the comparison test output contains
+[\x00-\x7f] the test might contain [\x00-\xff], and similarly in some other
+cases. This is not a bug in PCRE2.
+
+Test 3 checks pcre2_maketables(), the facility for building a set of character
+tables for a specific locale and using them instead of the default tables. The
+script uses the "locale" command to check for the availability of the "fr_FR",
+"french", or "fr" locale, and uses the first one that it finds. If the "locale"
+command fails, or if its output doesn't include "fr_FR", "french", or "fr" in
+the list of available locales, the third test cannot be run, and a comment is
+output to say why. If running this test produces an error like this:
+
+ ** Failed to set locale "fr_FR"
+
+it means that the given locale is not available on your system, despite being
+listed by "locale". This does not mean that PCRE2 is broken. There are three
+alternative output files for the third test, because three different versions
+of the French locale have been encountered. The test passes if its output
+matches any one of them.
+
+Tests 4 and 5 check UTF and Unicode property support, test 4 being compatible
+with the perltest.sh script, and test 5 checking PCRE2-specific things.
+
+Tests 6 and 7 check the pcre2_dfa_match() alternative matching function, in
+non-UTF mode and UTF-mode with Unicode property support, respectively.
+
+Test 8 checks some internal offsets and code size features, but it is run only
+when Unicode support is enabled. The output is different in 8-bit, 16-bit, and
+32-bit modes and for different link sizes, so there are different output files
+for each mode and link size.
+
+Tests 9 and 10 are run only in 8-bit mode, and tests 11 and 12 are run only in
+16-bit and 32-bit modes. These are tests that generate different output in
+8-bit mode. Each pair are for general cases and Unicode support, respectively.
+
+Test 13 checks the handling of non-UTF characters greater than 255 by
+pcre2_dfa_match() in 16-bit and 32-bit modes.
+
+Test 14 contains some special UTF and UCP tests that give different output for
+different code unit widths.
+
+Test 15 contains a number of tests that must not be run with JIT. They check,
+among other non-JIT things, the match-limiting features of the interpretive
+matcher.
+
+Test 16 is run only when JIT support is not available. It checks that an
+attempt to use JIT has the expected behaviour.
+
+Test 17 is run only when JIT support is available. It checks JIT complete and
+partial modes, match-limiting under JIT, and other JIT-specific features.
+
+Tests 18 and 19 are run only in 8-bit mode. They check the POSIX interface to
+the 8-bit library, without and with Unicode support, respectively.
+
+Test 20 checks the serialization functions by writing a set of compiled
+patterns to a file, and then reloading and checking them.
+
+Tests 21 and 22 test \C support when the use of \C is not locked out, without
+and with UTF support, respectively. Test 23 tests \C when it is locked out.
+
+Tests 24 and 25 test the experimental pattern conversion functions, without and
+with UTF support, respectively.
+
+Test 26 checks Unicode property support using tests that were generated
+automatically from the Unicode data tables. These are the archived version of
+the tests from Unicode 15.
+
+Test 27 checks Unicode property support using tests that are generated
+automatically from the currently-used Unicode data tables.
+
+Test 28 tests EBCDIC support, and is only run when PCRE2 is specifically
+compiled for EBCDIC. Test 29 tests EBCDIC when NL has been configured to be
+0x25.
+
+
+Character tables
+----------------
+
+For speed, PCRE2 uses four tables for manipulating and identifying characters
+whose code point values are less than 256. By default, a set of tables that is
+built into the library is used. The pcre2_maketables() function can be called
+by an application to create a new set of tables in the current locale. This are
+passed to PCRE2 by calling pcre2_set_character_tables() to put a pointer into a
+compile context.
+
+The source file called pcre2_chartables.c contains the default set of tables.
+By default, this is created as a copy of pcre2_chartables.c.dist, which
+contains tables for ASCII coding. However, if --enable-rebuild-chartables is
+specified for ./configure, a new version of pcre2_chartables.c is built by the
+program pcre2_dftables (compiled from pcre2_dftables.c), which uses the ANSI C
+character handling functions such as isalnum(), isalpha(), isupper(),
+islower(), etc. to build the table sources. This means that the default C
+locale that is set for your system will control the contents of these default
+tables. You can change the default tables by editing pcre2_chartables.c and
+then re-building PCRE2. If you do this, you should take care to ensure that the
+file does not get automatically re-generated. The best way to do this is to
+move pcre2_chartables.c.dist out of the way and replace it with your customized
+tables.
+
+When the pcre2_dftables program is run as a result of specifying
+--enable-rebuild-chartables, it uses the default C locale that is set on your
+system. It does not pay attention to the LC_xxx environment variables. In other
+words, it uses the system's default locale rather than whatever the compiling
+user happens to have set. If you really do want to build a source set of
+character tables in a locale that is specified by the LC_xxx variables, you can
+run the pcre2_dftables program by hand with the -L option. For example:
+
+ ./pcre2_dftables -L pcre2_chartables.c.special
+
+The second argument names the file where the source code for the tables is
+written. The first two 256-byte tables provide lower casing and case flipping
+functions, respectively. The next table consists of a number of 32-byte bit
+maps which identify certain character classes such as digits, "word"
+characters, white space, etc. These are used when building 32-byte bit maps
+that represent character classes for code points less than 256. The final
+256-byte table has bits indicating various character types, as follows:
+
+ 1 white space character
+ 2 letter
+ 4 lower case letter
+ 8 decimal digit
+ 16 alphanumeric or '_'
+
+You can also specify -b (with or without -L) when running pcre2_dftables. This
+causes the tables to be written in binary instead of as source code. A set of
+binary tables can be loaded into memory by an application and passed to
+pcre2_compile() in the same way as tables created dynamically by calling
+pcre2_maketables(). The tables are just a string of bytes, independent of
+hardware characteristics such as endianness. This means they can be bundled
+with an application that runs in different environments, to ensure consistent
+behaviour.
+
+See also the pcre2build section "Creating character tables at build time".
+
+
+File manifest
+-------------
+
+The distribution should contain the files listed below.
+
+(A) Source files for the PCRE2 library functions and their headers are found in
+ the src directory:
+
+ src/pcre2_dftables.c auxiliary program for building pcre2_chartables.c
+ when --enable-rebuild-chartables is specified
+
+ src/pcre2_chartables.c.dist a default set of character tables that assume
+ ASCII coding; unless --enable-rebuild-chartables is
+ specified, used by copying to pcre2_chartables.c
+ src/pcre2_chartables.c.ebcdic-1047-{nl15,nl25} a default set of character
+ tables for EBCDIC 1047; used if
+ --enable-ebcdic-ignoring-compiler is specified
+ without --enable-rebuild-chartables
+
+ src/pcre2posix.c )
+ src/pcre2_auto_possess.c )
+ src/pcre2_chkdint.c )
+ src/pcre2_compile.c )
+ src/pcre2_compile_cgroup.c )
+ src/pcre2_compile_class.c )
+ src/pcre2_config.c )
+ src/pcre2_context.c )
+ src/pcre2_convert.c )
+ src/pcre2_dfa_match.c )
+ src/pcre2_error.c )
+ src/pcre2_extuni.c )
+ src/pcre2_find_bracket.c )
+ src/pcre2_jit_compile.c )
+ src/pcre2_maketables.c ) sources for the functions in the library,
+ src/pcre2_match.c ) and some internal functions that they use
+ src/pcre2_match_data.c )
+ src/pcre2_match_next.c )
+ src/pcre2_newline.c )
+ src/pcre2_ord2utf.c )
+ src/pcre2_pattern_info.c )
+ src/pcre2_script_run.c )
+ src/pcre2_serialize.c )
+ src/pcre2_string_utils.c )
+ src/pcre2_study.c )
+ src/pcre2_substitute.c )
+ src/pcre2_substring.c )
+ src/pcre2_tables.c )
+ src/pcre2_ucd.c )
+ src/pcre2_valid_utf.c )
+ src/pcre2_xclass.c )
+
+ src/pcre2_fuzzsupport.c function for (optional) fuzzing support
+
+ src/config.h.in template for config.h, when built by "configure"
+ src/pcre2.h.in template for pcre2.h when built by "configure"
+ src/pcre2posix.h header for the external POSIX wrapper API
+ src/pcre2_compile.h header for internal use
+ src/pcre2_internal.h header for internal use
+ src/pcre2_intmodedep.h a mode-specific internal header
+ src/pcre2_jit_char_inc.h header used by JIT
+ src/pcre2_jit_match_inc.h header used by JIT
+ src/pcre2_jit_misc_inc.h header used by JIT
+ src/pcre2_jit_simd_inc.h header used by JIT
+ src/pcre2_printint_inc.h debugging function that is used by pcre2test
+ src/pcre2_ucp.h header for Unicode property handling
+ src/pcre2_ucptables_inc.h header with Unicode data tables
+ src/pcre2_util.h header for internal utils
+
+ deps/sljit/sljit_src/* source files for the JIT compiler
+
+(B) Source files for programs that use PCRE2:
+
+ src/pcre2demo.c simple demonstration of coding calls to PCRE2
+ src/pcre2grep.c source of a grep utility that uses PCRE2
+ src/pcre2test.c comprehensive test program
+ src/pcre2test_inc.h header used by pcre2test
+ src/pcre2_jit_test.c JIT test program
+ src/pcre2posix_test.c POSIX wrapper API test program
+
+(C) Auxiliary files:
+
+ AUTHORS.md information about the authors of PCRE2
+ ChangeLog log of changes to the code
+ HACKING some notes about the internals of PCRE2
+ INSTALL generic installation instructions
+ LICENCE.md conditions for the use of PCRE2
+ COPYING the same, using GNU's standard name
+ SECURITY.md information on reporting vulnerabilities
+ SUPPORT-LIFECYCLE.md information on the support policy
+ Makefile.in ) template for Unix Makefile, which is built by
+ ) "configure"
+ Makefile.am ) the automake input that was used to create
+ ) Makefile.in
+ NEWS important changes in this release
+ NON-AUTOTOOLS-BUILD notes on building PCRE2 without using autotools
+ README this file
+ RunTest a Unix shell script for running tests
+ RunGrepTest a Unix shell script for pcre2grep tests
+ RunTest.bat a Windows batch file for running tests
+ RunGrepTest.bat a Windows batch file for pcre2grep tests
+ aclocal.m4 m4 macros (generated by "aclocal")
+ m4/* m4 macros (used by autoconf)
+ configure a configuring shell script (built by autoconf)
+ configure.ac ) the autoconf input that was used to build
+ ) "configure" and config.h
+ doc/*.3 man page sources for PCRE2
+ doc/*.1 man page sources for pcre2grep and pcre2test
+ doc/html/* HTML documentation
+ doc/pcre2.txt plain text version of the man pages
+ doc/pcre2-config.txt plain text documentation of pcre2-config script
+ doc/pcre2grep.txt plain text documentation of grep utility program
+ doc/pcre2test.txt plain text documentation of test program
+ libpcre2-8.pc.in template for libpcre2-8.pc for pkg-config
+ libpcre2-16.pc.in template for libpcre2-16.pc for pkg-config
+ libpcre2-32.pc.in template for libpcre2-32.pc for pkg-config
+ libpcre2-posix.pc.in template for libpcre2-posix.pc for pkg-config
+ ar-lib )
+ config.guess )
+ config.sub )
+ depcomp ) helper tools generated by libtool and
+ compile ) automake, used internally by ./configure
+ install-sh )
+ ltmain.sh )
+ missing )
+ test-driver )
+ perltest.sh Script for running a Perl test program
+ pcre2-config.in source of script which retains PCRE2 information
+ testdata/testinput* test data for main library tests
+ testdata/testoutput* expected test results
+ testdata/grep* input and output for pcre2grep tests
+ testdata/* other supporting test files
+ src/libpcre2-8.sym.in )
+ src/libpcre2-16.sym.in ) symbol version script templates for the
+ src/libpcre2-32.sym.in ) GNU, BSD and Sun linkers
+ src/libpcre2-posix.sym.in )
+
+(D) Auxiliary files for CMake support
+
+ cmake/COPYING-CMAKE-SCRIPTS
+ cmake/FindEditline.cmake
+ cmake/FindReadline.cmake
+ cmake/pcre2-config.cmake.in
+ cmake/PCRE2CheckVscript.cmake
+ cmake/PCRE2UseSystemExtensions.cmake
+ cmake/PCRE2WarningAsError.cmake
+ src/config-cmake.h.in
+ CMakeLists.txt
+
+(E) Auxiliary files for building PCRE2 "by hand"
+
+ src/pcre2.h.generic ) a version of the public PCRE2 header file
+ ) for use in non-"configure" environments
+ src/config.h.generic ) a version of config.h for use in non-"configure"
+ ) environments
+
+(F) Auxiliary files for building PCRE2 using other build systems
+
+ BUILD.bazel ) files used by the Bazel
+ MODULE.bazel ) build system
+ build.zig file used by zig's build system
+ build.zig.zon file used by zig's package manager
+
+(G) Auxiliary files for building PCRE2 under OpenVMS
+
+ vms/configure.com )
+ vms/openvms_readme.txt ) These files were contributed by a PCRE2 user.
+ vms/pcre2.h_patch )
+ vms/stdint.h )
+
+============================
+Last updated: 08 August 2026
+============================
+
diff --git a/doc/html/index.html b/doc/html/index.html
new file mode 100644
index 0000000..f33d615
--- /dev/null
+++ b/doc/html/index.html
@@ -0,0 +1,346 @@
+
+
+
+PCRE2 specification
+
+
+
+Perl-compatible Regular Expressions (revised API: PCRE2)
+
+The HTML documentation for PCRE2 consists of a number of pages that are listed
+below in alphabetical order. If you are new to PCRE2, please read the first one
+first.
+
+
+
+| pcre2 |
+ Introductory page |
+
+| pcre2-config |
+ Information about the installation configuration |
+
+| pcre2api |
+ PCRE2's native API |
+
+| pcre2build |
+ Building PCRE2 |
+
+| pcre2callout |
+ The callout facility |
+
+| pcre2compat |
+ Compability with Perl |
+
+| pcre2convert |
+ Experimental foreign pattern conversion functions |
+
+| pcre2demo |
+ A demonstration C program that uses the PCRE2 library |
+
+| pcre2grep |
+ The pcre2grep command |
+
+| pcre2jit |
+ Discussion of the just-in-time optimization support |
+
+| pcre2limits |
+ Details of size and other limits |
+
+| pcre2matching |
+ Discussion of the two matching algorithms |
+
+| pcre2partial |
+ Using PCRE2 for partial matching |
+
+| pcre2pattern |
+ Specification of the regular expressions supported by PCRE2 |
+
+| pcre2perform |
+ Some comments on performance |
+
+| pcre2posix |
+ The POSIX API to the PCRE2 8-bit library |
+
+| pcre2sample |
+ Discussion of the pcre2demo program |
+
+| pcre2serialize |
+ Serializing functions for saving precompiled patterns |
+
+| pcre2syntax |
+ Syntax quick-reference summary |
+
+| pcre2test |
+ The pcre2test command for testing PCRE2 |
+
+| pcre2unicode |
+ Discussion of Unicode and UTF-8/UTF-16/UTF-32 support |
+
+
+
+There are also individual pages that summarize the interface for each function
+in the library.
+
+
+
+
+
+
diff --git a/doc/html/pcre2-config.html b/doc/html/pcre2-config.html
new file mode 100644
index 0000000..371ec8f
--- /dev/null
+++ b/doc/html/pcre2-config.html
@@ -0,0 +1,103 @@
+
+
+pcre2-config specification
+
+
+pcre2-config man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+pcre2-config [--prefix] [--exec-prefix] [--version]
+ [--libs8] [--libs16] [--libs32] [--libs-posix]
+ [--cflags] [--cflags-posix]
+
+
+
+pcre2-config returns the configuration of the installed PCRE2 libraries
+and the options required to compile a program to use them. Some of the options
+apply only to the 8-bit, 16-bit, or 32-bit libraries, respectively, and are not
+available for libraries that have not been built. If an unavailable option is
+encountered, the "usage" information is output.
+
+
+
+--prefix
+Writes the directory prefix used in the PCRE2 installation for
+architecture-independent files (/usr on many systems, /usr/local on
+some systems) to the standard output.
+
+
+--exec-prefix
+Writes the directory prefix used in the PCRE2 installation for
+architecture-dependent files (normally the same as --prefix) to the
+standard output.
+
+
+--version
+Writes the version number of the installed PCRE2 libraries to the standard
+output.
+
+
+--libs8
+Writes to the standard output the command line options required to link
+with the 8-bit PCRE2 library (-lpcre2-8 on many systems).
+
+
+--libs16
+Writes to the standard output the command line options required to link
+with the 16-bit PCRE2 library (-lpcre2-16 on many systems).
+
+
+--libs32
+Writes to the standard output the command line options required to link
+with the 32-bit PCRE2 library (-lpcre2-32 on many systems).
+
+
+--libs-posix
+Writes to the standard output the command line options required to link with
+PCRE2's POSIX API wrapper library (-lpcre2-posix -lpcre2-8 on many
+systems).
+
+
+--cflags
+Writes to the standard output the command line options required to compile
+files that use PCRE2 (this may include some -I options, but is blank on
+many systems).
+
+
+--cflags-posix
+Writes to the standard output the command line options required to compile
+files that use PCRE2's POSIX API wrapper library (this may include some
+-I options, but is blank on many systems).
+
+
+
+pcre2(3)
+
+
+
+This manual page was originally written by Mark Baker for the Debian GNU/Linux
+system. It has been subsequently revised as a generic PCRE2 man page.
+
+
+
+Last updated: 22 February 2025
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2.html b/doc/html/pcre2.html
new file mode 100644
index 0000000..69b25db
--- /dev/null
+++ b/doc/html/pcre2.html
@@ -0,0 +1,214 @@
+
+
+pcre2 specification
+
+
+pcre2 man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+PCRE2 is the name used for a revised API for the PCRE library, which is a set
+of functions, written in C, that implement regular expression pattern matching
+using the same syntax and semantics as Perl, with just a few differences. After
+nearly two decades, the limitations of the original API were making development
+increasingly difficult. The new API is more extensible, and it was simplified
+by abolishing the separate "study" optimizing function; in PCRE2, patterns are
+automatically optimized where possible. Since forking from PCRE1, the code has
+been extensively refactored and new features introduced. The old library is now
+obsolete and is no longer maintained.
+
+
+As well as Perl-style regular expression patterns, some features that appeared
+in Python and the original PCRE before they appeared in Perl are available
+using the Python syntax. There is also support for some .NET and Oniguruma
+syntax items, and there are options for requesting minor changes that give
+better ECMAScript (JavaScript) compatibility.
+
+
+The source code for PCRE2 can be compiled to support strings of 8-bit, 16-bit,
+or 32-bit code units, which means that up to three separate libraries may be
+installed, one for each code unit size. The size of a code unit is not related
+to the bit size of the underlying hardware. In a 64-bit environment that also
+supports 32-bit applications, versions of PCRE2 that are compiled in both
+64-bit and 32-bit modes may be needed.
+
+
+The original work to extend PCRE to 16-bit and 32-bit code units was done by
+Zoltan Herczeg and Christian Persch, respectively. In all three cases, strings
+can be interpreted either as one character per code unit, or as UTF-encoded
+Unicode, with support for Unicode general category properties. Unicode support
+is optional at build time (but is the default). However, processing strings as
+UTF code units must be enabled explicitly at run time. The version of Unicode
+in use can be discovered by running
+
+ pcre2test -C
+
+
+
+The three libraries contain identical sets of functions, with names ending in
+_8, _16, or _32, respectively (for example, pcre2_compile_8()). However,
+by defining PCRE2_CODE_UNIT_WIDTH to be 8, 16, or 32, a program that uses just
+one code unit width can be written using generic names such as
+pcre2_compile(), and the documentation is written assuming that this is
+the case.
+
+
+In addition to the Perl-compatible matching function, PCRE2 contains an
+alternative function that matches the same compiled patterns in a different
+way. In certain circumstances, the alternative function has some advantages.
+For a discussion of the two matching algorithms, see the
+pcre2matching
+page.
+
+
+Details of exactly which Perl regular expression features are and are not
+supported by PCRE2 are given in separate documents. See the
+pcre2pattern
+and
+pcre2compat
+pages. There is a syntax summary in the
+pcre2syntax
+page.
+
+
+Some features of PCRE2 can be included, excluded, or changed when the library
+is built. The
+pcre2_config()
+function makes it possible for a client to discover which features are
+available. The features themselves are described in the
+pcre2build
+page. Documentation about building PCRE2 for various operating systems can be
+found in the
+README
+and
+NON-AUTOTOOLS-BUILD
+files in the source distribution.
+
+
+The libraries contains a number of undocumented internal functions and data
+tables that are used by more than one of the exported external functions, but
+which are not intended for use by external callers. Their names all begin with
+"_pcre2", which hopefully will not provoke any name clashes. In some
+environments, it is possible to control which external symbols are exported
+when a shared library is built, and in these cases the undocumented symbols are
+not exported.
+
+
+
+If you are using PCRE2 in a non-UTF application that permits users to supply
+arbitrary patterns for compilation, you should be aware of a feature that
+allows users to turn on UTF support from within a pattern. For example, an
+8-bit pattern that begins with "(*UTF)" turns on UTF-8 mode, which interprets
+patterns and subjects as strings of UTF-8 code units instead of individual
+8-bit characters. This causes both the pattern and any data against which it is
+matched to be checked for UTF-8 validity. If the data string is very long, such
+a check might use sufficiently many resources as to cause your application to
+lose performance.
+
+
+One way of guarding against this possibility is to use the
+pcre2_pattern_info() function to check the compiled pattern's options for
+PCRE2_UTF. Alternatively, you can set the PCRE2_NEVER_UTF option when calling
+pcre2_compile(). This causes a compile time error if the pattern contains
+a UTF-setting sequence.
+
+
+The use of Unicode properties for character types such as \d can also be
+enabled from within the pattern, by specifying "(*UCP)". This feature can be
+disallowed by setting the PCRE2_NEVER_UCP option.
+
+
+If your application is one that supports UTF, be aware that validity checking
+can take time. If the same data string is to be matched many times, you can use
+the PCRE2_NO_UTF_CHECK option for the second and subsequent matches to avoid
+running redundant checks.
+
+
+The use of the \C escape sequence in a UTF-8 or UTF-16 pattern can lead to
+problems, because it may leave the current matching point in the middle of a
+multi-code-unit character. The PCRE2_NEVER_BACKSLASH_C option can be used by an
+application to lock out the use of \C, causing a compile-time error if it is
+encountered. It is also possible to build PCRE2 with the use of \C permanently
+disabled.
+
+
+Another way that performance can be hit is by running a pattern that has a very
+large search tree against a string that will never match. Nested unlimited
+repeats in a pattern are a common example. PCRE2 provides some protection
+against this: see the pcre2_set_match_limit() function in the
+pcre2api
+page. There is a similar function called pcre2_set_depth_limit() that can
+be used to restrict the amount of memory that is used.
+
+
+
+The user documentation for PCRE2 comprises a number of different sections. In
+the "man" format, each of these is a separate "man page". In the HTML format,
+each is a separate page, linked from the index page. In the plain text format,
+the descriptions of the pcre2grep and pcre2test programs are in
+files called pcre2grep.txt and pcre2test.txt, respectively. The
+remaining sections, except for the pcre2demo section (which is a program
+listing), and the short pages for individual functions, are concatenated in
+pcre2.txt, for ease of searching. The sections are as follows:
+
+ pcre2 this document
+ pcre2-config show PCRE2 installation configuration information
+ pcre2api details of PCRE2's native C API
+ pcre2build building PCRE2
+ pcre2callout details of the pattern callout feature
+ pcre2compat discussion of Perl compatibility
+ pcre2convert details of pattern conversion functions
+ pcre2demo a demonstration C program that uses PCRE2
+ pcre2grep description of the pcre2grep command (8-bit only)
+ pcre2jit discussion of just-in-time optimization support
+ pcre2limits details of size and other limits
+ pcre2matching discussion of the two matching algorithms
+ pcre2partial details of the partial matching facility
+ pcre2pattern syntax and semantics of supported regular expression patterns
+ pcre2perform discussion of performance issues
+ pcre2posix the POSIX-compatible C API for the 8-bit library
+ pcre2sample discussion of the pcre2demo program
+ pcre2serialize details of pattern serialization
+ pcre2syntax quick syntax reference
+ pcre2test description of the pcre2test command
+ pcre2unicode discussion of Unicode and UTF support
+
+In the "man" and HTML formats, there is also a short page for each C library
+function, listing its arguments and results.
+
+
+
+The current maintainers of PCRE2 are Nicholas Wilson and Zoltan Herczeg.
+
+
+PCRE2 was written by Philip Hazel, of the University Computing Service,
+Cambridge, England. Many others have also contributed.
+
+
+To contact the maintainers, please use the GitHub issues tracker or PCRE2
+mailing list, as described at the project page:
+https://github.com/PCRE2Project/pcre2
+
+
+
+Last updated: 22 February 2025
+
+Copyright © 1997-2021 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_callout_enumerate.html b/doc/html/pcre2_callout_enumerate.html
new file mode 100644
index 0000000..6f4aec9
--- /dev/null
+++ b/doc/html/pcre2_callout_enumerate.html
@@ -0,0 +1,63 @@
+
+
+pcre2_callout_enumerate specification
+
+
+pcre2_callout_enumerate man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_callout_enumerate(const pcre2_code *code,
+ int (*callback)(pcre2_callout_enumerate_block *, void *),
+ void *callout_data);
+
+
+DESCRIPTION
+
+
+This function scans a compiled regular expression and calls the callback()
+function for each callout within the pattern. The yield of the function is zero
+for success and non-zero otherwise. The arguments are:
+
+ code Points to the compiled pattern
+ callback The callback function
+ callout_data User data that is passed to the callback
+
+The callback() function is passed a pointer to a data block containing
+the following fields (not necessarily in this order):
+
+ uint32_t version Block version number
+ uint32_t callout_number Number for numbered callouts
+ PCRE2_SIZE pattern_position Offset to next item in pattern
+ PCRE2_SIZE next_item_length Length of next item in pattern
+ PCRE2_SIZE callout_string_offset Offset to string within pattern
+ PCRE2_SIZE callout_string_length Length of callout string
+ PCRE2_SPTR callout_string Points to callout string or is NULL
+
+The second argument passed to the callback() function is the callout data
+that was passed to pcre2_callout_enumerate(). The callback()
+function must return zero for success. Any other value causes the pattern scan
+to stop, with the value being passed back as the result of
+pcre2_callout_enumerate().
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_code_copy.html b/doc/html/pcre2_code_copy.html
new file mode 100644
index 0000000..0dbecbb
--- /dev/null
+++ b/doc/html/pcre2_code_copy.html
@@ -0,0 +1,43 @@
+
+
+pcre2_code_copy specification
+
+
+pcre2_code_copy man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+pcre2_code *pcre2_code_copy(const pcre2_code *code);
+
+
+DESCRIPTION
+
+
+This function makes a copy of the memory used for a compiled pattern, excluding
+any memory used by the JIT compiler. Without a subsequent call to
+pcre2_jit_compile(), the copy can be used only for non-JIT matching. The
+pointer to the character tables is copied, not the tables themselves (see
+pcre2_code_copy_with_tables()). The yield of the function is NULL if
+code is NULL or if sufficient memory cannot be obtained.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_code_copy_with_tables.html b/doc/html/pcre2_code_copy_with_tables.html
new file mode 100644
index 0000000..3fb3885
--- /dev/null
+++ b/doc/html/pcre2_code_copy_with_tables.html
@@ -0,0 +1,44 @@
+
+
+pcre2_code_copy_with_tables specification
+
+
+pcre2_code_copy_with_tables man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+pcre2_code *pcre2_code_copy_with_tables(const pcre2_code *code);
+
+
+DESCRIPTION
+
+
+This function makes a copy of the memory used for a compiled pattern, excluding
+any memory used by the JIT compiler. Without a subsequent call to
+pcre2_jit_compile(), the copy can be used only for non-JIT matching.
+Unlike pcre2_code_copy(), a separate copy of the character tables is also
+made, with the new code pointing to it. This memory will be automatically freed
+when pcre2_code_free() is called. The yield of the function is NULL if
+code is NULL or if sufficient memory cannot be obtained.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_code_free.html b/doc/html/pcre2_code_free.html
new file mode 100644
index 0000000..8fad4a9
--- /dev/null
+++ b/doc/html/pcre2_code_free.html
@@ -0,0 +1,42 @@
+
+
+pcre2_code_free specification
+
+
+pcre2_code_free man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+void pcre2_code_free(pcre2_code *code);
+
+
+DESCRIPTION
+
+
+If code is NULL, this function does nothing. Otherwise, code must
+point to a compiled pattern. This function frees its memory, including any
+memory used by the JIT compiler. If the compiled pattern was created by a call
+to pcre2_code_copy_with_tables(), the memory for the character tables is
+also freed.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_compile.html b/doc/html/pcre2_compile.html
new file mode 100644
index 0000000..59ec537
--- /dev/null
+++ b/doc/html/pcre2_compile.html
@@ -0,0 +1,120 @@
+
+
+pcre2_compile specification
+
+
+pcre2_compile man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+pcre2_code *pcre2_compile(PCRE2_SPTR pattern, PCRE2_SIZE length,
+ uint32_t options, int *errorcode, PCRE2_SIZE *erroroffset,
+ pcre2_compile_context *ccontext);
+
+
+DESCRIPTION
+
+
+This function compiles a regular expression pattern into an internal form. Its
+arguments are:
+
+ pattern A string containing expression to be compiled
+ length The length of the string or PCRE2_ZERO_TERMINATED
+ options Primary option bits
+ errorcode Where to put an error code
+ erroffset Where to put an error offset
+ ccontext Pointer to a compile context or NULL
+
+The length of the pattern and any error offset that is returned are in code
+units, not characters. A NULL pattern with zero length is treated as an empty
+string. A compile context is needed only if you want to provide custom memory
+allocation functions, or to provide an external function for system stack size
+checking (see pcre2_set_compile_recursion_guard()), or to change one or
+more of these parameters:
+
+ What \R matches (Unicode newlines, or CR, LF, CRLF only);
+ PCRE2's character tables;
+ The newline character sequence;
+ The compile time nested parentheses limit;
+ The maximum pattern length (in code units) that is allowed;
+ The additional options bits.
+
+The primary option bits are:
+
+ PCRE2_ANCHORED Force pattern anchoring
+ PCRE2_ALLOW_EMPTY_CLASS Allow empty classes
+ PCRE2_ALT_BSUX Alternative handling of \u, \U, and \x
+ PCRE2_ALT_CIRCUMFLEX Alternative handling of ^ in multiline mode
+ PCRE2_ALT_EXTENDED_CLASS Alternative extended character class syntax
+ PCRE2_ALT_VERBNAMES Process backslashes in verb names
+ PCRE2_AUTO_CALLOUT Compile automatic callouts
+ PCRE2_CASELESS Do caseless matching
+ PCRE2_DOLLAR_ENDONLY $ not to match newline at end
+ PCRE2_DOTALL . matches anything including NL
+ PCRE2_DUPNAMES Allow duplicate names for subpatterns
+ PCRE2_ENDANCHORED Pattern can match only at end of subject
+ PCRE2_EXTENDED Ignore white space and # comments
+ PCRE2_FIRSTLINE Force matching to be before newline
+ PCRE2_LITERAL Pattern characters are all literal
+ PCRE2_MATCH_INVALID_UTF Enable support for matching invalid UTF
+ PCRE2_MATCH_UNSET_BACKREF Match unset backreferences
+ PCRE2_MULTILINE ^ and $ match newlines within data
+ PCRE2_NEVER_BACKSLASH_C Lock out the use of \C in patterns
+ PCRE2_NEVER_UCP Lock out PCRE2_UCP, e.g. via (*UCP)
+ PCRE2_NEVER_UTF Lock out PCRE2_UTF, e.g. via (*UTF)
+ PCRE2_NO_AUTO_CAPTURE Disable numbered capturing paren-
+ theses (named ones available)
+ PCRE2_NO_AUTO_POSSESS Disable auto-possessification
+ PCRE2_NO_DOTSTAR_ANCHOR Disable automatic anchoring for .*
+ PCRE2_NO_START_OPTIMIZE Disable match-time start optimizations
+ PCRE2_NO_UTF_CHECK Do not check the pattern for UTF validity
+ (only relevant if PCRE2_UTF is set)
+ PCRE2_UCP Use Unicode properties for \d, \w, etc.
+ PCRE2_UNGREEDY Invert greediness of quantifiers
+ PCRE2_USE_OFFSET_LIMIT Enable offset limit for unanchored matching
+ PCRE2_UTF Treat pattern and subjects as UTF strings
+
+PCRE2 must be built with Unicode support (the default) in order to use
+PCRE2_UTF, PCRE2_UCP and related options.
+
+
+Additional options may be set in the compile context via the
+pcre2_set_compile_extra_options
+function.
+
+
+If either of errorcode or erroroffset is NULL, the function returns
+NULL immediately. Otherwise, the yield of this function is a pointer to a
+private data structure that contains the compiled pattern, or NULL if an error
+was detected. In the error case, a text error message can be obtained by
+passing the value returned via the errorcode argument to the
+pcre2_get_error_message() function. The offset (in code units) where the
+error was encountered is returned via the erroroffset argument.
+
+
+If there is no error, the value passed via errorcode returns the message
+"no error" if passed to pcre2_get_error_message(), and the value passed
+via erroroffset is zero.
+
+
+There is a complete description of the PCRE2 native API, with more detail on
+each option, in the
+pcre2api
+page, and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_compile_context_copy.html b/doc/html/pcre2_compile_context_copy.html
new file mode 100644
index 0000000..d413015
--- /dev/null
+++ b/doc/html/pcre2_compile_context_copy.html
@@ -0,0 +1,41 @@
+
+
+pcre2_compile_context_copy specification
+
+
+pcre2_compile_context_copy man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+pcre2_compile_context *pcre2_compile_context_copy(
+ pcre2_compile_context *ccontext);
+
+
+DESCRIPTION
+
+
+This function makes a new copy of a compile context, using the memory
+allocation function that was used for the original context. The result is NULL
+if the memory cannot be obtained.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_compile_context_create.html b/doc/html/pcre2_compile_context_create.html
new file mode 100644
index 0000000..5433b3e
--- /dev/null
+++ b/doc/html/pcre2_compile_context_create.html
@@ -0,0 +1,42 @@
+
+
+pcre2_compile_context_create specification
+
+
+pcre2_compile_context_create man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+pcre2_compile_context *pcre2_compile_context_create(
+ pcre2_general_context *gcontext);
+
+
+DESCRIPTION
+
+
+This function creates and initializes a new compile context. If its argument is
+NULL, malloc() is used to get the necessary memory; otherwise the memory
+allocation function within the general context is used. The result is NULL if
+the memory could not be obtained.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_compile_context_free.html b/doc/html/pcre2_compile_context_free.html
new file mode 100644
index 0000000..8d30527
--- /dev/null
+++ b/doc/html/pcre2_compile_context_free.html
@@ -0,0 +1,41 @@
+
+
+pcre2_compile_context_free specification
+
+
+pcre2_compile_context_free man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+void pcre2_compile_context_free(pcre2_compile_context *ccontext);
+
+
+DESCRIPTION
+
+
+This function frees the memory occupied by a compile context, using the memory
+freeing function from the general context with which it was created, or
+free() if that was not set. If the argument is NULL, the function returns
+immediately without doing anything.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_config.html b/doc/html/pcre2_config.html
new file mode 100644
index 0000000..e45542c
--- /dev/null
+++ b/doc/html/pcre2_config.html
@@ -0,0 +1,85 @@
+
+
+pcre2_config specification
+
+
+pcre2_config man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_config(uint32_t what, void *where);
+
+
+DESCRIPTION
+
+
+This function makes it possible for a client program to find out which optional
+features are available in the version of the PCRE2 library it is using. The
+arguments are as follows:
+
+ what A code specifying what information is required
+ where Points to where to put the information
+
+If where is NULL, the function returns the amount of memory needed for
+the requested information. When the information is a string, the value is in
+code units; for other types of data it is in bytes.
+
+
+If where is not NULL, for PCRE2_CONFIG_JITTARGET,
+PCRE2_CONFIG_UNICODE_VERSION, and PCRE2_CONFIG_VERSION it must point to a
+buffer that is large enough to hold the string. For all other codes it must
+point to a uint32_t integer variable. The available codes are:
+
+ PCRE2_CONFIG_BSR Indicates what \R matches by default:
+ PCRE2_BSR_UNICODE
+ PCRE2_BSR_ANYCRLF
+ PCRE2_CONFIG_COMPILED_WIDTHS Which of 8/16/32 support was compiled
+ PCRE2_CONFIG_DEPTHLIMIT Default backtracking depth limit
+ PCRE2_CONFIG_EFFECTIVE_LINKSIZE How many bytes are used for link size
+ PCRE2_CONFIG_HEAPLIMIT Default heap memory limit
+ PCRE2_CONFIG_JIT Availability of just-in-time compiler support (1=yes 0=no)
+ PCRE2_CONFIG_JITTARGET Information (a string) about the target architecture for the JIT compiler
+ PCRE2_CONFIG_LINKSIZE Configured internal link size (2, 3, 4)
+ PCRE2_CONFIG_MATCHLIMIT Default internal resource limit
+ PCRE2_CONFIG_NEVER_BACKSLASH_C Whether or not \C is disabled
+ PCRE2_CONFIG_NEWLINE Code for the default newline sequence:
+ PCRE2_NEWLINE_CR
+ PCRE2_NEWLINE_LF
+ PCRE2_NEWLINE_CRLF
+ PCRE2_NEWLINE_ANY
+ PCRE2_NEWLINE_ANYCRLF
+ PCRE2_NEWLINE_NUL
+ PCRE2_CONFIG_PARENSLIMIT Default parentheses nesting limit
+ PCRE2_CONFIG_RECURSIONLIMIT Obsolete: use PCRE2_CONFIG_DEPTHLIMIT
+ PCRE2_CONFIG_STACKRECURSE Obsolete: always returns 0
+ PCRE2_CONFIG_UNICODE Availability of Unicode support (1=yes 0=no)
+ PCRE2_CONFIG_UNICODE_VERSION The Unicode version (a string)
+ PCRE2_CONFIG_VERSION The PCRE2 version (a string)
+
+The function yields a non-negative value on success or the negative value
+PCRE2_ERROR_BADOPTION otherwise. This is also the result for the
+PCRE2_CONFIG_JITTARGET code if JIT support is not available. When a string is
+requested, the function returns the number of code units used, including the
+terminating zero.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_convert_context_copy.html b/doc/html/pcre2_convert_context_copy.html
new file mode 100644
index 0000000..5f6be6a
--- /dev/null
+++ b/doc/html/pcre2_convert_context_copy.html
@@ -0,0 +1,40 @@
+
+
+pcre2_convert_context_copy specification
+
+
+pcre2_convert_context_copy man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+pcre2_convert_context *pcre2_convert_context_copy(
+ pcre2_convert_context *cvcontext);
+
+
+DESCRIPTION
+
+
+This function is part of an experimental set of pattern conversion functions.
+It makes a new copy of a convert context, using the memory allocation function
+that was used for the original context. The result is NULL if the memory cannot
+be obtained.
+
+
+The pattern conversion functions are described in the
+pcre2convert
+documentation.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_convert_context_create.html b/doc/html/pcre2_convert_context_create.html
new file mode 100644
index 0000000..d5ab22a
--- /dev/null
+++ b/doc/html/pcre2_convert_context_create.html
@@ -0,0 +1,41 @@
+
+
+pcre2_convert_context_create specification
+
+
+pcre2_convert_context_create man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+pcre2_convert_context *pcre2_convert_context_create(
+ pcre2_general_context *gcontext);
+
+
+DESCRIPTION
+
+
+This function is part of an experimental set of pattern conversion functions.
+It creates and initializes a new convert context. If its argument is
+NULL, malloc() is used to get the necessary memory; otherwise the memory
+allocation function within the general context is used. The result is NULL if
+the memory could not be obtained.
+
+
+The pattern conversion functions are described in the
+pcre2convert
+documentation.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_convert_context_free.html b/doc/html/pcre2_convert_context_free.html
new file mode 100644
index 0000000..cc19e79
--- /dev/null
+++ b/doc/html/pcre2_convert_context_free.html
@@ -0,0 +1,40 @@
+
+
+pcre2_convert_context_free specification
+
+
+pcre2_convert_context_free man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+void pcre2_convert_context_free(pcre2_convert_context *cvcontext);
+
+
+DESCRIPTION
+
+
+This function is part of an experimental set of pattern conversion functions.
+It frees the memory occupied by a convert context, using the memory
+freeing function from the general context with which it was created, or
+free() if that was not set. If the argument is NULL, the function returns
+immediately without doing anything.
+
+
+The pattern conversion functions are described in the
+pcre2convert
+documentation.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_converted_pattern_free.html b/doc/html/pcre2_converted_pattern_free.html
new file mode 100644
index 0000000..8f082f4
--- /dev/null
+++ b/doc/html/pcre2_converted_pattern_free.html
@@ -0,0 +1,40 @@
+
+
+pcre2_converted_pattern_free specification
+
+
+pcre2_converted_pattern_free man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+void pcre2_converted_pattern_free(PCRE2_UCHAR *converted_pattern);
+
+
+DESCRIPTION
+
+
+This function is part of an experimental set of pattern conversion functions.
+It frees the memory occupied by a converted pattern that was obtained by
+calling pcre2_pattern_convert() with arguments that caused it to place
+the converted pattern into newly obtained heap memory. If the argument is NULL,
+the function returns immediately without doing anything.
+
+
+The pattern conversion functions are described in the
+pcre2convert
+documentation.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_dfa_match.html b/doc/html/pcre2_dfa_match.html
new file mode 100644
index 0000000..0f36de5
--- /dev/null
+++ b/doc/html/pcre2_dfa_match.html
@@ -0,0 +1,86 @@
+
+
+pcre2_dfa_match specification
+
+
+pcre2_dfa_match man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_dfa_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext,
+ int *workspace, PCRE2_SIZE wscount);
+
+
+DESCRIPTION
+
+
+This function matches a compiled regular expression against a given subject
+string, using an alternative matching algorithm that scans the subject string
+just once (except when processing lookaround assertions). This function is
+not Perl-compatible (the Perl-compatible matching function is
+pcre2_match()). The arguments for this function are:
+
+ code Points to the compiled pattern
+ subject Points to the subject string
+ length Length of the subject string
+ startoffset Offset in the subject at which to start matching
+ options Option bits
+ match_data Points to a match data block, for results
+ mcontext Points to a match context, or is NULL
+ workspace Points to a vector of ints used as working space
+ wscount Number of elements in the vector
+
+The size of output vector needed to contain all the results depends on the
+number of simultaneous matches, not on the number of parentheses in the
+pattern. Using pcre2_match_data_create_from_pattern() to create the match
+data block is therefore not advisable when using this function.
+
+
+A match context is needed only if you want to set up a callout function or
+specify the heap limit or the match or the recursion depth limits. The
+length and startoffset values are code units, not characters. The
+options are:
+
+ PCRE2_ANCHORED Match only at the first position
+ PCRE2_COPY_MATCHED_SUBJECT
+ On success, make a private subject copy
+ PCRE2_ENDANCHORED Pattern can match only at end of subject
+ PCRE2_NOTBOL Subject is not the beginning of a line
+ PCRE2_NOTEOL Subject is not the end of a line
+ PCRE2_NOTEMPTY An empty string is not a valid match
+ PCRE2_NOTEMPTY_ATSTART An empty string at the start of the subject is not a valid match
+ PCRE2_NO_UTF_CHECK Do not check the subject for UTF validity (only relevant if PCRE2_UTF
+ was set at compile time)
+ PCRE2_PARTIAL_HARD Return PCRE2_ERROR_PARTIAL for a partial match even if there is a full match
+ PCRE2_PARTIAL_SOFT Return PCRE2_ERROR_PARTIAL for a partial match if no full matches are found
+ PCRE2_DFA_RESTART Restart after a partial match
+ PCRE2_DFA_SHORTEST Return only the shortest match
+
+There are restrictions on what may appear in a pattern when using this matching
+function. Details are given in the
+pcre2matching
+documentation. For details of partial matching, see the
+pcre2partial
+page. There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_general_context_copy.html b/doc/html/pcre2_general_context_copy.html
new file mode 100644
index 0000000..fb2c296
--- /dev/null
+++ b/doc/html/pcre2_general_context_copy.html
@@ -0,0 +1,42 @@
+
+
+pcre2_general_context_copy specification
+
+
+pcre2_general_context_copy man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+pcre2_general_context *pcre2_general_context_copy(
+ pcre2_general_context *gcontext);
+
+
+DESCRIPTION
+
+
+This function makes a new copy of a general context, using the memory
+allocation functions in the context, if set, to get the necessary memory.
+Otherwise malloc() is used. The result is NULL if the memory cannot be
+obtained.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_general_context_create.html b/doc/html/pcre2_general_context_create.html
new file mode 100644
index 0000000..808bbcc
--- /dev/null
+++ b/doc/html/pcre2_general_context_create.html
@@ -0,0 +1,44 @@
+
+
+pcre2_general_context_create specification
+
+
+pcre2_general_context_create man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+pcre2_general_context *pcre2_general_context_create(
+ void *(*private_malloc)(size_t, void *),
+ void (*private_free)(void *, void *), void *memory_data);
+
+
+DESCRIPTION
+
+
+This function creates and initializes a general context. The arguments define
+custom memory management functions and a data value that is passed to them when
+they are called. The private_malloc() function is used to get memory for
+the context. If either of the first two arguments is NULL, the system memory
+management function is used. The result is NULL if no memory could be obtained.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_general_context_free.html b/doc/html/pcre2_general_context_free.html
new file mode 100644
index 0000000..e370f1c
--- /dev/null
+++ b/doc/html/pcre2_general_context_free.html
@@ -0,0 +1,40 @@
+
+
+pcre2_general_context_free specification
+
+
+pcre2_general_context_free man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+void pcre2_general_context_free(pcre2_general_context *gcontext);
+
+
+DESCRIPTION
+
+
+This function frees the memory occupied by a general context, using the memory
+freeing function within the context, if set. If the argument is NULL, the
+function returns immediately without doing anything.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_get_error_message.html b/doc/html/pcre2_get_error_message.html
new file mode 100644
index 0000000..904e24d
--- /dev/null
+++ b/doc/html/pcre2_get_error_message.html
@@ -0,0 +1,51 @@
+
+
+pcre2_get_error_message specification
+
+
+pcre2_get_error_message man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_get_error_message(int errorcode, PCRE2_UCHAR *buffer,
+ PCRE2_SIZE bufflen);
+
+
+DESCRIPTION
+
+
+This function provides a textual error message for each PCRE2 error code.
+Compilation errors are positive numbers; UTF formatting errors and matching
+errors are negative numbers. The arguments are:
+
+ errorcode an error code (positive or negative)
+ buffer where to put the message
+ bufflen the length of the buffer (code units)
+
+The function returns the length of the message in code units, excluding the
+trailing zero, or the negative error code PCRE2_ERROR_NOMEMORY if the buffer is
+too small. In this case, the returned message is truncated (but still with a
+trailing zero). If errorcode does not contain a recognized error code
+number, the negative value PCRE2_ERROR_BADDATA is returned.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_get_mark.html b/doc/html/pcre2_get_mark.html
new file mode 100644
index 0000000..fe15fc5
--- /dev/null
+++ b/doc/html/pcre2_get_mark.html
@@ -0,0 +1,47 @@
+
+
+pcre2_get_mark specification
+
+
+pcre2_get_mark man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+PCRE2_SPTR pcre2_get_mark(pcre2_match_data *match_data);
+
+
+DESCRIPTION
+
+
+After a call of pcre2_match() that was passed the match block that is
+this function's argument, this function returns a pointer to the last (*MARK),
+(*PRUNE), or (*THEN) name that was encountered during the matching process. The
+name is zero-terminated, and is within the compiled pattern. The length of the
+name is in the preceding code unit. If no name is available, NULL is returned.
+
+
+After a successful match, the name that is returned is the last one on the
+matching path. After a failed match or a partial match, the last encountered
+name is returned.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_get_match_data_heapframes_size.html b/doc/html/pcre2_get_match_data_heapframes_size.html
new file mode 100644
index 0000000..17ace9c
--- /dev/null
+++ b/doc/html/pcre2_get_match_data_heapframes_size.html
@@ -0,0 +1,40 @@
+
+
+pcre2_get_match_data_heapframes_size specification
+
+
+pcre2_get_match_data_heapframes_size man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+PCRE2_SIZE pcre2_get_match_data_heapframes_size(
+ pcre2_match_data *match_data);
+
+
+DESCRIPTION
+
+
+This function returns the size, in bytes, of the heapframes data block that is
+owned by its argument.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_get_match_data_size.html b/doc/html/pcre2_get_match_data_size.html
new file mode 100644
index 0000000..d191a90
--- /dev/null
+++ b/doc/html/pcre2_get_match_data_size.html
@@ -0,0 +1,39 @@
+
+
+pcre2_get_match_data_size specification
+
+
+pcre2_get_match_data_size man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+PCRE2_SIZE pcre2_get_match_data_size(pcre2_match_data *match_data);
+
+
+DESCRIPTION
+
+
+This function returns the size, in bytes, of the match data block that is its
+argument.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_get_ovector_count.html b/doc/html/pcre2_get_ovector_count.html
new file mode 100644
index 0000000..fed1cdf
--- /dev/null
+++ b/doc/html/pcre2_get_ovector_count.html
@@ -0,0 +1,39 @@
+
+
+pcre2_get_ovector_count specification
+
+
+pcre2_get_ovector_count man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+uint32_t pcre2_get_ovector_count(pcre2_match_data *match_data);
+
+
+DESCRIPTION
+
+
+This function returns the number of pairs of offsets in the ovector that forms
+part of the given match data block.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_get_ovector_pointer.html b/doc/html/pcre2_get_ovector_pointer.html
new file mode 100644
index 0000000..2b76b7c
--- /dev/null
+++ b/doc/html/pcre2_get_ovector_pointer.html
@@ -0,0 +1,40 @@
+
+
+pcre2_get_ovector_pointer specification
+
+
+pcre2_get_ovector_pointer man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+PCRE2_SIZE *pcre2_get_ovector_pointer(pcre2_match_data *match_data);
+
+
+DESCRIPTION
+
+
+This function returns a pointer to the vector of offsets that forms part of the
+given match data block. The number of pairs can be found by calling
+pcre2_get_ovector_count().
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_get_startchar.html b/doc/html/pcre2_get_startchar.html
new file mode 100644
index 0000000..56f0fee
--- /dev/null
+++ b/doc/html/pcre2_get_startchar.html
@@ -0,0 +1,44 @@
+
+
+pcre2_get_startchar specification
+
+
+pcre2_get_startchar man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+PCRE2_SIZE pcre2_get_startchar(pcre2_match_data *match_data);
+
+
+DESCRIPTION
+
+
+After a successful call of pcre2_match() that was passed the match block
+that is this function's argument, this function returns the code unit offset of
+the character at which the successful match started. For a non-partial match,
+this can be different to the value of ovector[0] if the pattern contains
+the \K escape sequence. After a partial match, however, this value is always
+the same as ovector[0] because \K does not affect the result of a
+partial match.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_jit_compile.html b/doc/html/pcre2_jit_compile.html
new file mode 100644
index 0000000..edf5b39
--- /dev/null
+++ b/doc/html/pcre2_jit_compile.html
@@ -0,0 +1,74 @@
+
+
+pcre2_jit_compile specification
+
+
+pcre2_jit_compile man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_jit_compile(pcre2_code *code, uint32_t options);
+
+
+DESCRIPTION
+
+
+This function requests JIT compilation, which, if the just-in-time compiler is
+available, further processes a compiled pattern into machine code that executes
+much faster than the pcre2_match() interpretive matching function. Full
+details are given in the
+pcre2jit
+documentation.
+
+
+The availability of JIT support can be tested by calling
+pcre2_compile_jit() with a single option PCRE2_JIT_TEST_ALLOC (the
+code argument is ignored, so a NULL value is accepted). Such a call
+returns zero if JIT is available and has a working allocator. Otherwise
+it returns PCRE2_ERROR_NOMEMORY if JIT is available but cannot allocate
+executable memory, or PCRE2_ERROR_JIT_UNSUPPORTED if JIT support is not
+compiled.
+
+
+Otherwise, the first argument must be a pointer that was returned by a
+successful call to pcre2_compile(), and the second must contain one or
+more of the following bits:
+
+ PCRE2_JIT_COMPLETE compile code for full matching
+ PCRE2_JIT_PARTIAL_SOFT compile code for soft partial matching
+ PCRE2_JIT_PARTIAL_HARD compile code for hard partial matching
+
+There is also an obsolete option called PCRE2_JIT_INVALID_UTF, which has been
+superseded by the pcre2_compile() option PCRE2_MATCH_INVALID_UTF. The old
+option is deprecated and may be removed in the future.
+
+
+The yield of the function when called with any of the three options above is 0
+for success, or a negative error code otherwise. In particular,
+PCRE2_ERROR_JIT_BADOPTION is returned if JIT is not supported or if an unknown
+bit is set in options. The function can also return PCRE2_ERROR_NOMEMORY
+if JIT is unable to allocate executable memory for the compiler, even if it was
+because of a system security restriction. In a few cases, the function may
+return with PCRE2_ERROR_JIT_UNSUPPORTED for unsupported features.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_jit_free_unused_memory.html b/doc/html/pcre2_jit_free_unused_memory.html
new file mode 100644
index 0000000..0ee2f13
--- /dev/null
+++ b/doc/html/pcre2_jit_free_unused_memory.html
@@ -0,0 +1,43 @@
+
+
+pcre2_jit_free_unused_memory specification
+
+
+pcre2_jit_free_unused_memory man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+void pcre2_jit_free_unused_memory(pcre2_general_context *gcontext);
+
+
+DESCRIPTION
+
+
+This function frees unused JIT executable memory. The argument is a general
+context, for custom memory management, or NULL for standard memory management.
+JIT memory allocation retains some memory in order to improve future JIT
+compilation speed. In low memory conditions,
+pcre2_jit_free_unused_memory() can be used to cause this memory to be
+freed.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_jit_match.html b/doc/html/pcre2_jit_match.html
new file mode 100644
index 0000000..0294e6b
--- /dev/null
+++ b/doc/html/pcre2_jit_match.html
@@ -0,0 +1,70 @@
+
+
+pcre2_jit_match specification
+
+
+pcre2_jit_match man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_jit_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext);
+
+
+DESCRIPTION
+
+
+This function matches a compiled regular expression that has been successfully
+processed by the JIT compiler against a given subject string, using a matching
+algorithm that is similar to Perl's. It is a "fast path" interface to JIT, and
+it bypasses some of the sanity checks that pcre2_match() applies.
+
+
+In UTF mode, the subject string is not checked for UTF validity. Unless
+PCRE2_MATCH_INVALID_UTF was set when the pattern was compiled, passing an
+invalid UTF string results in undefined behaviour. Your program may crash or
+loop or give wrong results. In the absence of PCRE2_MATCH_INVALID_UTF you
+should only call pcre2_jit_match() in UTF mode if you are sure the
+subject is valid.
+
+
+The arguments for pcre2_jit_match() are exactly the same as for
+pcre2_match(),
+except that the subject string must be specified with a length;
+PCRE2_ZERO_TERMINATED is not supported.
+
+
+The supported options are PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY,
+PCRE2_NOTEMPTY_ATSTART, PCRE2_PARTIAL_HARD, and PCRE2_PARTIAL_SOFT. Unsupported
+options are ignored.
+
+
+The return values are the same as for pcre2_match() plus
+PCRE2_ERROR_JIT_BADOPTION if a matching mode (partial or complete) is requested
+that was not compiled. For details of partial matching, see the
+pcre2partial
+page.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the JIT API in the
+pcre2jit
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_jit_stack_assign.html b/doc/html/pcre2_jit_stack_assign.html
new file mode 100644
index 0000000..1e83d98
--- /dev/null
+++ b/doc/html/pcre2_jit_stack_assign.html
@@ -0,0 +1,75 @@
+
+
+pcre2_jit_stack_assign specification
+
+
+pcre2_jit_stack_assign man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+void pcre2_jit_stack_assign(pcre2_match_context *mcontext,
+ pcre2_jit_callback callback_function, void *callback_data);
+
+
+DESCRIPTION
+
+
+This function provides control over the memory used by JIT as a run-time stack
+when pcre2_match() or pcre2_jit_match() is called with a pattern
+that has been successfully processed by the JIT compiler. The information that
+determines which stack is used is put into a match context that is subsequently
+passed to a matching function. The arguments of this function are:
+
+ mcontext a pointer to a match context
+ callback a callback function
+ callback_data a JIT stack or a value to be passed to the callback
+
+
+
+If mcontext is NULL, the function returns immediately, without doing
+anything.
+
+
+If callback is NULL and callback_data is NULL, an internal 32KiB
+block on the machine stack is used.
+
+
+If callback is NULL and callback_data is not NULL,
+callback_data must be a valid JIT stack, the result of calling
+pcre2_jit_stack_create().
+
+
+If callback not NULL, it is called with callback_data as an
+argument at the start of matching, in order to set up a JIT stack. If the
+result is NULL, the internal 32KiB stack is used; otherwise the return value
+must be a valid JIT stack, the result of calling
+pcre2_jit_stack_create().
+
+
+You may safely use the same JIT stack for multiple patterns, as long as they
+are all matched in the same thread. In a multithread application, each thread
+must use its own JIT stack. For more details, see the
+pcre2jit
+page.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_jit_stack_create.html b/doc/html/pcre2_jit_stack_create.html
new file mode 100644
index 0000000..0c28a13
--- /dev/null
+++ b/doc/html/pcre2_jit_stack_create.html
@@ -0,0 +1,50 @@
+
+
+pcre2_jit_stack_create specification
+
+
+pcre2_jit_stack_create man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+pcre2_jit_stack *pcre2_jit_stack_create(size_t startsize,
+ size_t maxsize, pcre2_general_context *gcontext);
+
+
+DESCRIPTION
+
+
+This function is used to create a stack for use by the code compiled by the JIT
+compiler. The first two arguments are a starting size for the stack, and a
+maximum size to which it is allowed to grow. The final argument is a general
+context, for memory allocation functions, or NULL for standard memory
+allocation. The result can be passed to the JIT run-time code by calling
+pcre2_jit_stack_assign() to associate the stack with a compiled pattern,
+which can then be processed by pcre2_match() or pcre2_jit_match().
+A maximum stack size of 512KiB to 1MiB should be more than enough for any
+pattern. If the stack couldn't be allocated or the values passed were not
+reasonable, NULL will be returned. For more details, see the
+pcre2jit
+page.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_jit_stack_free.html b/doc/html/pcre2_jit_stack_free.html
new file mode 100644
index 0000000..bebdbdd
--- /dev/null
+++ b/doc/html/pcre2_jit_stack_free.html
@@ -0,0 +1,43 @@
+
+
+pcre2_jit_stack_free specification
+
+
+pcre2_jit_stack_free man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+void pcre2_jit_stack_free(pcre2_jit_stack *jit_stack);
+
+
+DESCRIPTION
+
+
+This function is used to free a JIT stack that was created by
+pcre2_jit_stack_create() when it is no longer needed. If the argument is
+NULL, the function returns immediately without doing anything. For more
+details, see the
+pcre2jit
+page.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_maketables.html b/doc/html/pcre2_maketables.html
new file mode 100644
index 0000000..06ec34f
--- /dev/null
+++ b/doc/html/pcre2_maketables.html
@@ -0,0 +1,48 @@
+
+
+pcre2_maketables specification
+
+
+pcre2_maketables man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+const uint8_t *pcre2_maketables(pcre2_general_context *gcontext);
+
+
+DESCRIPTION
+
+
+This function builds a set of character tables for character code points that
+are less than 256. These can be passed to pcre2_compile() in a compile
+context in order to override the internal, built-in tables (which were either
+defaulted or made by pcre2_maketables() when PCRE2 was compiled). See the
+pcre2_set_character_tables()
+page. You might want to do this if you are using a non-standard locale.
+
+
+If the argument is NULL, malloc() is used to get memory for the tables.
+Otherwise it must point to a general context, which can supply pointers to a
+custom memory manager. The function yields a pointer to the tables.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_maketables_free.html b/doc/html/pcre2_maketables_free.html
new file mode 100644
index 0000000..5532f0f
--- /dev/null
+++ b/doc/html/pcre2_maketables_free.html
@@ -0,0 +1,44 @@
+
+
+pcre2_maketables_free specification
+
+
+pcre2_maketables_free man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+void pcre2_maketables_free(pcre2_general_context *gcontext,
+ const uint8_t *tables);
+
+
+DESCRIPTION
+
+
+This function discards a set of character tables that were created by a call
+to
+pcre2_maketables().
+
+
+The gcontext parameter should match what was used in that call to
+account for any custom allocators that might be in use; if it is NULL
+the system free() is used.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_match.html b/doc/html/pcre2_match.html
new file mode 100644
index 0000000..7f40a56
--- /dev/null
+++ b/doc/html/pcre2_match.html
@@ -0,0 +1,87 @@
+
+
+pcre2_match specification
+
+
+pcre2_match man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext);
+
+
+DESCRIPTION
+
+
+This function matches a compiled regular expression against a given subject
+string, using a matching algorithm that is similar to Perl's. It returns
+offsets to what it has matched and to captured substrings via the
+match_data block, which can be processed by functions with names that
+start with pcre2_get_ovector_...() or pcre2_substring_...(). The
+return from pcre2_match() is one more than the highest numbered capturing
+pair that has been set (for example, 1 if there are no captures), zero if the
+vector of offsets is too small, or a negative error code for no match and other
+errors. The function arguments are:
+
+ code Points to the compiled pattern
+ subject Points to the subject string
+ length Length of the subject string
+ startoffset Offset in the subject at which to start matching
+ options Option bits
+ match_data Points to a match data block, for results
+ mcontext Points to a match context, or is NULL
+
+A match context is needed only if you want to:
+
+ Set up a callout function
+ Set a matching offset limit
+ Change the heap memory limit
+ Change the backtracking match limit
+ Change the backtracking depth limit
+ Set custom memory management specifically for the match
+
+The length and startoffset values are code units, not characters.
+The length may be given as PCRE2_ZERO_TERMINATED for a subject that is
+terminated by a binary zero code unit. The options are:
+
+ PCRE2_ANCHORED Match only at the first position
+ PCRE2_COPY_MATCHED_SUBJECT
+ On success, make a private subject copy
+ PCRE2_DISABLE_RECURSELOOP_CHECK
+ Only useful in rare cases; use with care
+ PCRE2_ENDANCHORED Pattern can match only at end of subject
+ PCRE2_NOTBOL Subject string is not the beginning of a line
+ PCRE2_NOTEOL Subject string is not the end of a line
+ PCRE2_NOTEMPTY An empty string is not a valid match
+ PCRE2_NOTEMPTY_ATSTART An empty string at the start of the subject is not a valid match
+ PCRE2_NO_JIT Do not use JIT matching
+ PCRE2_NO_UTF_CHECK Do not check the subject for UTF validity (only relevant if PCRE2_UTF
+ was set at compile time)
+ PCRE2_PARTIAL_HARD Return PCRE2_ERROR_PARTIAL for a partial match even if there is a full match
+ PCRE2_PARTIAL_SOFT Return PCRE2_ERROR_PARTIAL for a partial match if no full matches are found
+
+For details of partial matching, see the
+pcre2partial
+page. There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_match_context_copy.html b/doc/html/pcre2_match_context_copy.html
new file mode 100644
index 0000000..068f7f9
--- /dev/null
+++ b/doc/html/pcre2_match_context_copy.html
@@ -0,0 +1,41 @@
+
+
+pcre2_match_context_copy specification
+
+
+pcre2_match_context_copy man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+pcre2_match_context *pcre2_match_context_copy(
+ pcre2_match_context *mcontext);
+
+
+DESCRIPTION
+
+
+This function makes a new copy of a match context, using the memory
+allocation function that was used for the original context. The result is NULL
+if the memory cannot be obtained.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_match_context_create.html b/doc/html/pcre2_match_context_create.html
new file mode 100644
index 0000000..5d0f4d5
--- /dev/null
+++ b/doc/html/pcre2_match_context_create.html
@@ -0,0 +1,42 @@
+
+
+pcre2_match_context_create specification
+
+
+pcre2_match_context_create man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+pcre2_match_context *pcre2_match_context_create(
+ pcre2_general_context *gcontext);
+
+
+DESCRIPTION
+
+
+This function creates and initializes a new match context. If its argument is
+NULL, malloc() is used to get the necessary memory; otherwise the memory
+allocation function within the general context is used. The result is NULL if
+the memory could not be obtained.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_match_context_free.html b/doc/html/pcre2_match_context_free.html
new file mode 100644
index 0000000..7bf3237
--- /dev/null
+++ b/doc/html/pcre2_match_context_free.html
@@ -0,0 +1,41 @@
+
+
+pcre2_match_context_free specification
+
+
+pcre2_match_context_free man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+void pcre2_match_context_free(pcre2_match_context *mcontext);
+
+
+DESCRIPTION
+
+
+This function frees the memory occupied by a match context, using the memory
+freeing function from the general context with which it was created, or
+free() if that was not set. If the argument is NULL, the function returns
+immediately without doing anything.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_match_data_create.html b/doc/html/pcre2_match_data_create.html
new file mode 100644
index 0000000..96f7968
--- /dev/null
+++ b/doc/html/pcre2_match_data_create.html
@@ -0,0 +1,50 @@
+
+
+pcre2_match_data_create specification
+
+
+pcre2_match_data_create man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+pcre2_match_data *pcre2_match_data_create(uint32_t ovecsize,
+ pcre2_general_context *gcontext);
+
+
+DESCRIPTION
+
+
+This function creates a new match data block, which is used for holding the
+result of a match. The first argument specifies the number of pairs of offsets
+that are required. These form the "output vector" (ovector) within the match
+data block, and are used to identify the matched string and any captured
+substrings when matching with pcre2_match(), or a number of different
+matches at the same point when used with pcre2_dfa_match(). There is
+always one pair of offsets; if ovecsize is zero, it is treated as one.
+
+
+The second argument points to a general context, for custom memory management,
+or is NULL for system memory management. The result of the function is NULL if
+the memory for the block could not be obtained.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_match_data_create_from_pattern.html b/doc/html/pcre2_match_data_create_from_pattern.html
new file mode 100644
index 0000000..73e7bdd
--- /dev/null
+++ b/doc/html/pcre2_match_data_create_from_pattern.html
@@ -0,0 +1,53 @@
+
+
+pcre2_match_data_create_from_pattern specification
+
+
+pcre2_match_data_create_from_pattern man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+pcre2_match_data *pcre2_match_data_create_from_pattern(
+ const pcre2_code *code, pcre2_general_context *gcontext);
+
+
+DESCRIPTION
+
+
+This function creates a new match data block for holding the result of a match.
+If the first argument is NULL, this function returns NULL, otherwise the first
+argument points to a compiled pattern. The number of capturing parentheses
+within the pattern is used to compute the number of pairs of offsets that are
+required in the match data block. These form the "output vector" (ovector)
+within the match data block, and are used to identify the matched string and
+any captured substrings when matching with pcre2_match(). If you are
+using pcre2_dfa_match(), which uses the output vector in a different way,
+you should use pcre2_match_data_create() instead of this function.
+
+
+The second argument points to a general context, for custom memory management,
+or is NULL to use the same memory allocator that was used for the compiled
+pattern. The result of the function is NULL if the memory for the block could
+not be obtained or if NULL was provided as the first argument.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_match_data_free.html b/doc/html/pcre2_match_data_free.html
new file mode 100644
index 0000000..8893bf8
--- /dev/null
+++ b/doc/html/pcre2_match_data_free.html
@@ -0,0 +1,48 @@
+
+
+pcre2_match_data_free specification
+
+
+pcre2_match_data_free man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+void pcre2_match_data_free(pcre2_match_data *match_data);
+
+
+DESCRIPTION
+
+
+If match_data is NULL, this function does nothing. Otherwise,
+match_data must point to a match data block, which this function frees,
+using the memory freeing function from the general context or compiled pattern
+with which it was created, or free() if that was not set. If the match
+data block was previously passed to pcre2_match(), it will have an
+attached heapframe vector; this is also freed.
+
+
+If the PCRE2_COPY_MATCHED_SUBJECT was used for a successful match using this
+match data block, the copy of the subject that was referenced within the block
+is also freed.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_next_match.html b/doc/html/pcre2_next_match.html
new file mode 100644
index 0000000..f5f8c46
--- /dev/null
+++ b/doc/html/pcre2_next_match.html
@@ -0,0 +1,55 @@
+
+
+pcre2_next_match specification
+
+
+pcre2_next_match man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_next_match(pcre2_match_data *match_data,
+ PCRE2_SIZE *pstart_offset, uint32_t *poptions);
+
+
+DESCRIPTION
+
+
+This function can be called after one of the match functions
+(pcre2_match(), pcre2_dfa_match(), or pcre2_jit_match()), and
+must be provided with the same match_data parameter. It outputs the
+appropriate parameters for searching for the next match in the same subject
+string, and is suitable for applications providing "global" matching behaviour
+(for example, replacing all matches in the subject, or splitting the subject on
+all matches, or simply counting the number of matches).
+
+
+It returns 0 ("false") if there is no need to make any further match attempts,
+or 1 ("true") if another match should be attempted.
+
+
+The *pstart_offset and *poptions are set if the function returns 1.
+The *pstart_offset should be passed to the next match attempt directly,
+and the *poptions should be passed to the next match attempt by combining
+with the application's match options using OR.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_pattern_convert.html b/doc/html/pcre2_pattern_convert.html
new file mode 100644
index 0000000..58635ad
--- /dev/null
+++ b/doc/html/pcre2_pattern_convert.html
@@ -0,0 +1,70 @@
+
+
+pcre2_pattern_convert specification
+
+
+pcre2_pattern_convert man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_pattern_convert(PCRE2_SPTR pattern, PCRE2_SIZE length,
+ uint32_t options, PCRE2_UCHAR **buffer,
+ PCRE2_SIZE *blength, pcre2_convert_context *cvcontext);
+
+
+DESCRIPTION
+
+
+This function is part of an experimental set of pattern conversion functions.
+It converts a foreign pattern (for example, a glob) into a PCRE2 regular
+expression pattern. Its arguments are:
+
+ pattern The foreign pattern
+ length The length of the input pattern or PCRE2_ZERO_TERMINATED
+ options Option bits
+ buffer Pointer to pointer to output buffer, or NULL
+ blength Pointer to output length field
+ cvcontext Pointer to a convert context or NULL
+
+The length of the converted pattern (excluding the terminating zero) is
+returned via blength. If buffer is NULL, the function just returns
+the output length. If buffer points to a NULL pointer, heap memory is
+obtained for the converted pattern, using the allocator in the context if
+present (or else malloc()), and the field pointed to by buffer is
+updated. If buffer points to a non-NULL field, that must point to a
+buffer whose size is in the variable pointed to by blength. This value is
+updated.
+
+
+The option bits are:
+
+ PCRE2_CONVERT_UTF Input is UTF
+ PCRE2_CONVERT_NO_UTF_CHECK Do not check UTF validity
+ PCRE2_CONVERT_POSIX_BASIC Convert POSIX basic pattern
+ PCRE2_CONVERT_POSIX_EXTENDED Convert POSIX extended pattern
+ PCRE2_CONVERT_GLOB ) Convert
+ PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR ) various types
+ PCRE2_CONVERT_GLOB_NO_STARSTAR ) of glob
+
+The return value from pcre2_pattern_convert() is zero on success or a
+non-zero PCRE2 error code.
+
+
+The pattern conversion functions are described in the
+pcre2convert
+documentation.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_pattern_info.html b/doc/html/pcre2_pattern_info.html
new file mode 100644
index 0000000..42427af
--- /dev/null
+++ b/doc/html/pcre2_pattern_info.html
@@ -0,0 +1,109 @@
+
+
+pcre2_pattern_info specification
+
+
+pcre2_pattern_info man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_pattern_info(const pcre2_code *code, uint32_t what,
+ void *where);
+
+
+DESCRIPTION
+
+
+This function returns information about a compiled pattern. Its arguments are:
+
+ code Pointer to a compiled regular expression pattern
+ what What information is required
+ where Where to put the information
+
+The recognized values for the what argument, and the information they
+request are as follows:
+
+ PCRE2_INFO_ALLOPTIONS Final options after compiling
+ PCRE2_INFO_ARGOPTIONS Options passed to pcre2_compile()
+ PCRE2_INFO_BACKREFMAX Number of highest backreference
+ PCRE2_INFO_BSR What \R matches:
+ PCRE2_BSR_UNICODE: Unicode line endings
+ PCRE2_BSR_ANYCRLF: CR, LF, or CRLF only
+ PCRE2_INFO_CAPTURECOUNT Number of capturing subpatterns
+ PCRE2_INFO_DEPTHLIMIT Backtracking depth limit if set, otherwise PCRE2_ERROR_UNSET
+ PCRE2_INFO_EXTRAOPTIONS Extra options that were passed in the
+ compile context
+ PCRE2_INFO_FIRSTBITMAP Bitmap of first code units, or NULL
+ PCRE2_INFO_FIRSTCODETYPE Type of start-of-match information
+ 0 nothing set
+ 1 first code unit is set
+ 2 start of string or after newline
+ PCRE2_INFO_FIRSTCODEUNIT First code unit when type is 1
+ PCRE2_INFO_FRAMESIZE Size of backtracking frame
+ PCRE2_INFO_HASBACKSLASHC Return 1 if pattern contains \C
+ PCRE2_INFO_HASCRORLF Return 1 if explicit CR or LF matches exist in the pattern
+ PCRE2_INFO_HEAPLIMIT Heap memory limit if set, otherwise PCRE2_ERROR_UNSET
+ PCRE2_INFO_JCHANGED Return 1 if (?J) or (?-J) was used
+ PCRE2_INFO_JITSIZE Size of JIT compiled code, or 0
+ PCRE2_INFO_LASTCODETYPE Type of must-be-present information
+ 0 nothing set
+ 1 code unit is set
+ PCRE2_INFO_LASTCODEUNIT Last code unit when type is 1
+ PCRE2_INFO_MATCHEMPTY 1 if the pattern can match an empty string, 0 otherwise
+ PCRE2_INFO_MATCHLIMIT Match limit if set, otherwise PCRE2_ERROR_UNSET
+ PCRE2_INFO_MAXLOOKBEHIND Length (in characters) of the longest lookbehind assertion
+ PCRE2_INFO_MINLENGTH Lower bound length of matching strings
+ PCRE2_INFO_NAMECOUNT Number of named subpatterns
+ PCRE2_INFO_NAMEENTRYSIZE Size of name table entries
+ PCRE2_INFO_NAMETABLE Pointer to name table
+ PCRE2_CONFIG_NEWLINE Code for the newline sequence:
+ PCRE2_NEWLINE_CR
+ PCRE2_NEWLINE_LF
+ PCRE2_NEWLINE_CRLF
+ PCRE2_NEWLINE_ANY
+ PCRE2_NEWLINE_ANYCRLF
+ PCRE2_NEWLINE_NUL
+ PCRE2_INFO_RECURSIONLIMIT Obsolete synonym for PCRE2_INFO_DEPTHLIMIT
+ PCRE2_INFO_SIZE Size of compiled pattern
+
+If where is NULL, the function returns the amount of memory needed for
+the requested information, in bytes. Otherwise, the where argument must
+point to an unsigned 32-bit integer (uint32_t variable), except for the
+following what values, when it must point to a variable of the type
+shown:
+
+ PCRE2_INFO_FIRSTBITMAP const uint8_t *
+ PCRE2_INFO_JITSIZE size_t
+ PCRE2_INFO_NAMETABLE PCRE2_SPTR
+ PCRE2_INFO_SIZE size_t
+
+The yield of the function is zero on success or:
+
+ PCRE2_ERROR_NULL the argument code is NULL
+ PCRE2_ERROR_BADMAGIC the "magic number" was not found
+ PCRE2_ERROR_BADOPTION the value of what is invalid
+ PCRE2_ERROR_BADMODE the pattern was compiled in the wrong mode
+ PCRE2_ERROR_UNSET the requested information is not set
+
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_serialize_decode.html b/doc/html/pcre2_serialize_decode.html
new file mode 100644
index 0000000..d275df8
--- /dev/null
+++ b/doc/html/pcre2_serialize_decode.html
@@ -0,0 +1,65 @@
+
+
+pcre2_serialize_decode specification
+
+
+pcre2_serialize_decode man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int32_t pcre2_serialize_decode(pcre2_code **codes,
+ int32_t number_of_codes, const uint8_t *bytes,
+ pcre2_general_context *gcontext);
+
+
+DESCRIPTION
+
+
+This function decodes a serialized set of compiled patterns back into a list of
+individual patterns. This is possible only on a host that is running the same
+version of PCRE2, with the same code unit width, and the host must also have
+the same endianness, pointer width and PCRE2_SIZE type. The arguments for
+pcre2_serialize_decode() are:
+
+ codes pointer to a vector in which to build the list
+ number_of_codes number of slots in the vector
+ bytes the serialized byte stream
+ gcontext pointer to a general context or NULL
+
+The bytes argument must point to a block of data that was originally
+created by pcre2_serialize_encode(), though it may have been saved on
+disc or elsewhere in the meantime. If there are more codes in the serialized
+data than slots in the list, only those compiled patterns that will fit are
+decoded. The yield of the function is the number of decoded patterns, or one of
+the following negative error codes:
+
+ PCRE2_ERROR_BADDATA number_of_codes is zero or less
+ PCRE2_ERROR_BADMAGIC mismatch of id bytes in bytes
+ PCRE2_ERROR_BADMODE mismatch of variable unit size or PCRE version
+ PCRE2_ERROR_NOMEMORY memory allocation failed
+ PCRE2_ERROR_NULL codes or bytes is NULL
+
+PCRE2_ERROR_BADMAGIC may mean that the data is corrupt, or that it was compiled
+on a system with different endianness.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the serialization functions in the
+pcre2serialize
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_serialize_encode.html b/doc/html/pcre2_serialize_encode.html
new file mode 100644
index 0000000..d25bbd8
--- /dev/null
+++ b/doc/html/pcre2_serialize_encode.html
@@ -0,0 +1,66 @@
+
+
+pcre2_serialize_encode specification
+
+
+pcre2_serialize_encode man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int32_t pcre2_serialize_encode(const pcre2_code **codes,
+ int32_t number_of_codes, uint8_t **serialized_bytes,
+ PCRE2_SIZE *serialized_size, pcre2_general_context *gcontext);
+
+
+DESCRIPTION
+
+
+This function encodes a list of compiled patterns into a byte stream that can
+be saved on disc or elsewhere. Note that this is not an abstract format like
+Java or .NET. Conversion of the byte stream back into usable compiled patterns
+can only happen on a host that is running the same version of PCRE2, with the
+same code unit width, and the host must also have the same endianness, pointer
+width and PCRE2_SIZE type. The arguments for pcre2_serialize_encode()
+are:
+
+ codes pointer to a vector containing the list
+ number_of_codes number of slots in the vector
+ serialized_bytes set to point to the serialized byte stream
+ serialized_size set to the number of bytes in the byte stream
+ gcontext pointer to a general context or NULL
+
+The context argument is used to obtain memory for the byte stream. When the
+serialized data is no longer needed, it must be freed by calling
+pcre2_serialize_free(). The yield of the function is the number of
+serialized patterns, or one of the following negative error codes:
+
+ PCRE2_ERROR_BADDATA number_of_codes is zero or less
+ PCRE2_ERROR_BADMAGIC mismatch of id bytes in one of the patterns
+ PCRE2_ERROR_MEMORY memory allocation failed
+ PCRE2_ERROR_MIXEDTABLES the patterns do not all use the same tables
+ PCRE2_ERROR_NULL an argument other than gcontext is NULL
+
+PCRE2_ERROR_BADMAGIC means either that a pattern's code has been corrupted, or
+that a slot in the vector does not point to a compiled pattern.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the serialization functions in the
+pcre2serialize
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_serialize_free.html b/doc/html/pcre2_serialize_free.html
new file mode 100644
index 0000000..aea20fd
--- /dev/null
+++ b/doc/html/pcre2_serialize_free.html
@@ -0,0 +1,41 @@
+
+
+pcre2_serialize_free specification
+
+
+pcre2_serialize_free man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+void pcre2_serialize_free(uint8_t *bytes);
+
+
+DESCRIPTION
+
+
+This function frees the memory that was obtained by
+pcre2_serialize_encode() to hold a serialized byte stream. The argument
+must point to such a byte stream or be NULL, in which case the function returns
+without doing anything.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the serialization functions in the
+pcre2serialize
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_serialize_get_number_of_codes.html b/doc/html/pcre2_serialize_get_number_of_codes.html
new file mode 100644
index 0000000..3ddaa02
--- /dev/null
+++ b/doc/html/pcre2_serialize_get_number_of_codes.html
@@ -0,0 +1,49 @@
+
+
+pcre2_serialize_get_number_of_codes specification
+
+
+pcre2_serialize_get_number_of_codes man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int32_t pcre2_serialize_get_number_of_codes(const uint8_t *bytes);
+
+
+DESCRIPTION
+
+
+The bytes argument must point to a serialized byte stream that was
+originally created by pcre2_serialize_encode() (though it may have been
+saved on disc or elsewhere in the meantime). The function returns the number of
+serialized patterns in the byte stream, or one of the following negative error
+codes:
+
+ PCRE2_ERROR_BADMAGIC mismatch of id bytes in bytes
+ PCRE2_ERROR_BADMODE mismatch of variable unit size or PCRE version
+ PCRE2_ERROR_NULL the argument is NULL
+
+PCRE2_ERROR_BADMAGIC may mean that the data is corrupt, or that it was compiled
+on a system with different endianness.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the serialization functions in the
+pcre2serialize
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_bsr.html b/doc/html/pcre2_set_bsr.html
new file mode 100644
index 0000000..2b47bef
--- /dev/null
+++ b/doc/html/pcre2_set_bsr.html
@@ -0,0 +1,42 @@
+
+
+pcre2_set_bsr specification
+
+
+pcre2_set_bsr man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_bsr(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+
+DESCRIPTION
+
+
+This function sets the convention for processing \R within a compile context.
+The second argument must be one of PCRE2_BSR_ANYCRLF or PCRE2_BSR_UNICODE. The
+result is zero for success or PCRE2_ERROR_BADDATA if the second argument is
+invalid.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_callout.html b/doc/html/pcre2_set_callout.html
new file mode 100644
index 0000000..e74a8f5
--- /dev/null
+++ b/doc/html/pcre2_set_callout.html
@@ -0,0 +1,43 @@
+
+
+pcre2_set_callout specification
+
+
+pcre2_set_callout man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_callout_block *),
+ void *callout_data);
+
+
+DESCRIPTION
+
+
+This function sets the callout fields in a match context (the first argument).
+The second argument specifies a callout function, and the third argument is an
+opaque data item that is passed to it. The result of this function is always
+zero.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_character_tables.html b/doc/html/pcre2_set_character_tables.html
new file mode 100644
index 0000000..98420bf
--- /dev/null
+++ b/doc/html/pcre2_set_character_tables.html
@@ -0,0 +1,45 @@
+
+
+pcre2_set_character_tables specification
+
+
+pcre2_set_character_tables man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_character_tables(pcre2_compile_context *ccontext,
+ const uint8_t *tables);
+
+
+DESCRIPTION
+
+
+This function sets a pointer to custom character tables within a compile
+context. The second argument must point to a set of PCRE2 character tables or
+be NULL to request the default tables. The result is always zero. Character
+tables can be created by calling pcre2_maketables() or by running the
+pcre2_dftables maintenance command in binary mode (see the
+pcre2build
+documentation).
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_compile_extra_options.html b/doc/html/pcre2_set_compile_extra_options.html
new file mode 100644
index 0000000..d6c25cf
--- /dev/null
+++ b/doc/html/pcre2_set_compile_extra_options.html
@@ -0,0 +1,58 @@
+
+
+pcre2_set_compile_extra_options specification
+
+
+pcre2_set_compile_extra_options man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_compile_extra_options(pcre2_compile_context *ccontext,
+ uint32_t extra_options);
+
+
+DESCRIPTION
+
+
+This function sets additional option bits for pcre2_compile() that are
+housed in a compile context. It completely replaces all the bits. The extra
+options are:
+
+ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK Allow \K in lookarounds
+ PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES Allow \x{d800} to \x{dfff} in UTF-8 and UTF-32 modes
+ PCRE2_EXTRA_ALT_BSUX Extended alternate \u, \U, and \x handling
+ PCRE2_EXTRA_ASCII_BSD \d remains ASCII in UCP mode
+ PCRE2_EXTRA_ASCII_BSS \s remains ASCII in UCP mode
+ PCRE2_EXTRA_ASCII_BSW \w remains ASCII in UCP mode
+ PCRE2_EXTRA_ASCII_DIGIT [:digit:] and [:xdigit:] POSIX classes remain ASCII in UCP mode
+ PCRE2_EXTRA_ASCII_POSIX POSIX classes remain ASCII in UCP mode
+ PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL Treat all invalid escapes as a literal following character
+ PCRE2_EXTRA_CASELESS_RESTRICT Disable mixed ASCII/non-ASCII case folding
+ PCRE2_EXTRA_ESCAPED_CR_IS_LF Interpret \r as \n
+ PCRE2_EXTRA_MATCH_LINE Pattern matches whole lines
+ PCRE2_EXTRA_MATCH_WORD Pattern matches "words"
+ PCRE2_EXTRA_NEVER_CALLOUT Disallow callouts in pattern
+ PCRE2_EXTRA_NO_BS0 Disallow \0 (but not \00 or \000)
+ PCRE2_EXTRA_PYTHON_OCTAL Use Python rules for octal
+ PCRE2_EXTRA_TURKISH_CASING Use Turkish I case folding
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_compile_recursion_guard.html b/doc/html/pcre2_set_compile_recursion_guard.html
new file mode 100644
index 0000000..d392792
--- /dev/null
+++ b/doc/html/pcre2_set_compile_recursion_guard.html
@@ -0,0 +1,46 @@
+
+
+pcre2_set_compile_recursion_guard specification
+
+
+pcre2_set_compile_recursion_guard man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_compile_recursion_guard(pcre2_compile_context *ccontext,
+ int (*guard_function)(uint32_t, void *), void *user_data);
+
+
+DESCRIPTION
+
+
+This function defines, within a compile context, a function that is called
+whenever pcre2_compile() starts to compile a parenthesized part of a
+pattern. The first argument to the function gives the current depth of
+parenthesis nesting, and the second is user data that is supplied when the
+function is set up. The callout function should return zero if all is well, or
+non-zero to force an error. This feature is provided so that applications can
+check the available system stack space, in order to avoid running out. The
+result of pcre2_set_compile_recursion_guard() is always zero.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_depth_limit.html b/doc/html/pcre2_set_depth_limit.html
new file mode 100644
index 0000000..631d1c1
--- /dev/null
+++ b/doc/html/pcre2_set_depth_limit.html
@@ -0,0 +1,40 @@
+
+
+pcre2_set_depth_limit specification
+
+
+pcre2_set_depth_limit man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_depth_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+
+DESCRIPTION
+
+
+This function sets the backtracking depth limit field in a match context. The
+result is always zero.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_glob_escape.html b/doc/html/pcre2_set_glob_escape.html
new file mode 100644
index 0000000..0b4a853
--- /dev/null
+++ b/doc/html/pcre2_set_glob_escape.html
@@ -0,0 +1,43 @@
+
+
+pcre2_set_glob_escape specification
+
+
+pcre2_set_glob_escape man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_glob_escape(pcre2_convert_context *cvcontext,
+ uint32_t escape_char);
+
+
+DESCRIPTION
+
+
+This function is part of an experimental set of pattern conversion functions.
+It sets the escape character that is used when converting globs. The second
+argument must either be zero (meaning there is no escape character) or a
+punctuation character whose code point is less than 256. The default is grave
+accent if running under Windows, otherwise backslash. The result of the
+function is zero for success or PCRE2_ERROR_BADDATA if the second argument is
+invalid.
+
+
+The pattern conversion functions are described in the
+pcre2convert
+documentation.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_glob_separator.html b/doc/html/pcre2_set_glob_separator.html
new file mode 100644
index 0000000..1d6bdaf
--- /dev/null
+++ b/doc/html/pcre2_set_glob_separator.html
@@ -0,0 +1,42 @@
+
+
+pcre2_set_glob_separator specification
+
+
+pcre2_set_glob_separator man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_glob_separator(pcre2_convert_context *cvcontext,
+ uint32_t separator_char);
+
+
+DESCRIPTION
+
+
+This function is part of an experimental set of pattern conversion functions.
+It sets the component separator character that is used when converting globs.
+The second argument must be one of the characters forward slash, backslash, or
+dot. The default is backslash when running under Windows, otherwise forward
+slash. The result of the function is zero for success or PCRE2_ERROR_BADDATA if
+the second argument is invalid.
+
+
+The pattern conversion functions are described in the
+pcre2convert
+documentation.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_heap_limit.html b/doc/html/pcre2_set_heap_limit.html
new file mode 100644
index 0000000..a9b53a8
--- /dev/null
+++ b/doc/html/pcre2_set_heap_limit.html
@@ -0,0 +1,40 @@
+
+
+pcre2_set_heap_limit specification
+
+
+pcre2_set_heap_limit man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_heap_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+
+DESCRIPTION
+
+
+This function sets the backtracking heap limit field in a match context. The
+result is always zero.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_match_limit.html b/doc/html/pcre2_set_match_limit.html
new file mode 100644
index 0000000..a8de8ae
--- /dev/null
+++ b/doc/html/pcre2_set_match_limit.html
@@ -0,0 +1,40 @@
+
+
+pcre2_set_match_limit specification
+
+
+pcre2_set_match_limit man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_match_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+
+DESCRIPTION
+
+
+This function sets the match limit field in a match context. The result is
+always zero.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_max_pattern_compiled_length.html b/doc/html/pcre2_set_max_pattern_compiled_length.html
new file mode 100644
index 0000000..abc1ca7
--- /dev/null
+++ b/doc/html/pcre2_set_max_pattern_compiled_length.html
@@ -0,0 +1,44 @@
+
+
+pcre2_set_max_pattern_compiled_length specification
+
+
+pcre2_set_max_pattern_compiled_length man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_max_pattern_compiled_length(
+ pcre2_compile_context *ccontext, PCRE2_SIZE value);
+
+
+DESCRIPTION
+
+
+This function sets, in a compile context, the maximum size (in bytes) for the
+memory needed to hold the compiled version of a pattern that is using this
+context. The result is always zero. If a pattern that is passed to
+pcre2_compile() referencing this context needs more memory, an error is
+generated. The default is the largest number that a PCRE2_SIZE variable can
+hold, which is effectively unlimited.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_max_pattern_length.html b/doc/html/pcre2_set_max_pattern_length.html
new file mode 100644
index 0000000..d5fe6aa
--- /dev/null
+++ b/doc/html/pcre2_set_max_pattern_length.html
@@ -0,0 +1,43 @@
+
+
+pcre2_set_max_pattern_length specification
+
+
+pcre2_set_max_pattern_length man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_max_pattern_length(pcre2_compile_context *ccontext,
+ PCRE2_SIZE value);
+
+
+DESCRIPTION
+
+
+This function sets, in a compile context, the maximum text length (in code
+units) of the pattern that can be compiled. The result is always zero. If a
+longer pattern is passed to pcre2_compile() there is an immediate error
+return. The default is effectively unlimited, being the largest value a
+PCRE2_SIZE variable can hold.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_max_varlookbehind.html b/doc/html/pcre2_set_max_varlookbehind.html
new file mode 100644
index 0000000..4aca6f0
--- /dev/null
+++ b/doc/html/pcre2_set_max_varlookbehind.html
@@ -0,0 +1,42 @@
+
+
+pcre2_set_max_varlookbehind specification
+
+
+pcre2_set_max_varlookbehind man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_max_varlookbehind(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+
+DESCRIPTION
+
+
+This sets a maximum length for the number of characters matched by a
+variable-length lookbehind assertion. The default is set when PCRE2 is built,
+with the ultimate default being 255, the same as Perl. Lookbehind assertions
+without a bounding length are not supported. The result is always zero.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_newline.html b/doc/html/pcre2_set_newline.html
new file mode 100644
index 0000000..34722ff
--- /dev/null
+++ b/doc/html/pcre2_set_newline.html
@@ -0,0 +1,51 @@
+
+
+pcre2_set_newline specification
+
+
+pcre2_set_newline man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_newline(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+
+DESCRIPTION
+
+
+This function sets the newline convention within a compile context. This
+specifies which character(s) are recognized as newlines when compiling and
+matching patterns. The second argument must be one of:
+
+ PCRE2_NEWLINE_CR Carriage return only
+ PCRE2_NEWLINE_LF Linefeed only
+ PCRE2_NEWLINE_CRLF CR followed by LF only
+ PCRE2_NEWLINE_ANYCRLF Any of the above
+ PCRE2_NEWLINE_ANY Any Unicode newline sequence
+ PCRE2_NEWLINE_NUL The NUL character (binary zero)
+
+The result is zero for success or PCRE2_ERROR_BADDATA if the second argument is
+invalid.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_offset_limit.html b/doc/html/pcre2_set_offset_limit.html
new file mode 100644
index 0000000..51c4e76
--- /dev/null
+++ b/doc/html/pcre2_set_offset_limit.html
@@ -0,0 +1,40 @@
+
+
+pcre2_set_offset_limit specification
+
+
+pcre2_set_offset_limit man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_offset_limit(pcre2_match_context *mcontext,
+ PCRE2_SIZE value);
+
+
+DESCRIPTION
+
+
+This function sets the offset limit field in a match context. The result is
+always zero.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_optimize.html b/doc/html/pcre2_set_optimize.html
new file mode 100644
index 0000000..4b839c6
--- /dev/null
+++ b/doc/html/pcre2_set_optimize.html
@@ -0,0 +1,57 @@
+
+
+pcre2_set_optimize specification
+
+
+pcre2_set_optimize man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_optimize(pcre2_compile_context *ccontext,
+ uint32_t directive);
+
+
+DESCRIPTION
+
+
+This function controls which performance optimizations will be applied
+by pcre2_compile(). It can be called multiple times with the same compile
+context; the effects are cumulative, with the effects of later calls taking
+precedence over earlier ones.
+
+
+The result is zero for success, PCRE2_ERROR_NULL if ccontext is NULL,
+or PCRE2_ERROR_BADOPTION if directive is unknown. The latter could be
+useful to detect if a certain optimization is available.
+
+
+The list of possible values for the directive parameter are:
+
+ PCRE2_OPTIMIZATION_FULL Enable all optimizations (default)
+ PCRE2_OPTIMIZATION_NONE Disable all optimizations
+ PCRE2_AUTO_POSSESS Enable auto-possessification
+ PCRE2_AUTO_POSSESS_OFF Disable auto-possessification
+ PCRE2_DOTSTAR_ANCHOR Enable implicit dotstar anchoring
+ PCRE2_DOTSTAR_ANCHOR_OFF Disable implicit dotstar anchoring
+ PCRE2_START_OPTIMIZE Enable start-up optimizations at match time
+ PCRE2_START_OPTIMIZE_OFF Disable start-up optimizations at match time
+
+There is a complete description of the PCRE2 native API, including detailed
+descriptions directive parameter values in the
+pcre2api
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_parens_nest_limit.html b/doc/html/pcre2_set_parens_nest_limit.html
new file mode 100644
index 0000000..133a63b
--- /dev/null
+++ b/doc/html/pcre2_set_parens_nest_limit.html
@@ -0,0 +1,40 @@
+
+
+pcre2_set_parens_nest_limit specification
+
+
+pcre2_set_parens_nest_limit man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_parens_nest_limit(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+
+DESCRIPTION
+
+
+This function sets, in a compile context, the maximum depth of nested
+parentheses in a pattern. The result is always zero.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_recursion_limit.html b/doc/html/pcre2_set_recursion_limit.html
new file mode 100644
index 0000000..998676e
--- /dev/null
+++ b/doc/html/pcre2_set_recursion_limit.html
@@ -0,0 +1,40 @@
+
+
+pcre2_set_recursion_limit specification
+
+
+pcre2_set_recursion_limit man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_recursion_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+
+DESCRIPTION
+
+
+This function is obsolete and should not be used in new code. Use
+pcre2_set_depth_limit() instead.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_recursion_memory_management.html b/doc/html/pcre2_set_recursion_memory_management.html
new file mode 100644
index 0000000..98742d2
--- /dev/null
+++ b/doc/html/pcre2_set_recursion_memory_management.html
@@ -0,0 +1,42 @@
+
+
+pcre2_set_recursion_memory_management specification
+
+
+pcre2_set_recursion_memory_management man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_recursion_memory_management(
+ pcre2_match_context *mcontext,
+ void *(*private_malloc)(size_t, void *),
+ void (*private_free)(void *, void *), void *memory_data);
+
+
+DESCRIPTION
+
+
+From release 10.30 onwards, this function is obsolete and does nothing. The
+result is always zero.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_substitute_callout.html b/doc/html/pcre2_set_substitute_callout.html
new file mode 100644
index 0000000..c5ece21
--- /dev/null
+++ b/doc/html/pcre2_set_substitute_callout.html
@@ -0,0 +1,43 @@
+
+
+pcre2_set_substitute_callout specification
+
+
+pcre2_set_substitute_callout man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_substitute_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_substitute_callout_block *, void *),
+ void *callout_data);
+
+
+DESCRIPTION
+
+
+This function sets the substitute callout fields in a match context (the first
+argument). The second argument specifies a callout function, and the third
+argument is an opaque data item that is passed to it. The result of this
+function is always zero.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_set_substitute_case_callout.html b/doc/html/pcre2_set_substitute_case_callout.html
new file mode 100644
index 0000000..1e22cd9
--- /dev/null
+++ b/doc/html/pcre2_set_substitute_case_callout.html
@@ -0,0 +1,45 @@
+
+
+pcre2_set_substitute_case_callout specification
+
+
+pcre2_set_substitute_case_callout man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_set_substitute_case_callout(pcre2_match_context *mcontext,
+ PCRE2_SIZE (*callout_function)(PCRE2_SPTR, PCRE2_SIZE,
+ PCRE2_UCHAR *, PCRE2_SIZE,
+ int, void *),
+ void *callout_data);
+
+
+DESCRIPTION
+
+
+This function sets the substitute case callout fields in a match context (the
+first argument). The second argument specifies a callout function, and the third
+argument is an opaque data item that is passed to it. The result of this
+function is always zero.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_substitute.html b/doc/html/pcre2_substitute.html
new file mode 100644
index 0000000..8fa9df0
--- /dev/null
+++ b/doc/html/pcre2_substitute.html
@@ -0,0 +1,112 @@
+
+
+pcre2_substitute specification
+
+
+pcre2_substitute man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_substitute(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext, PCRE2_SPTR replacement,
+ PCRE2_SIZE rlength, PCRE2_UCHAR *outputbuffer,
+ PCRE2_SIZE *outlengthptr);
+
+
+DESCRIPTION
+
+
+This function matches a compiled regular expression against a given subject
+string, using a matching algorithm that is similar to Perl's. It then makes a
+copy of the subject, substituting a replacement string for what was matched.
+Its arguments are:
+
+ code Points to the compiled pattern
+ subject Points to the subject string
+ length Length of the subject string
+ startoffset Offset in the subject at which to start matching
+ options Option bits
+ match_data Points to a match data block, or is NULL
+ mcontext Points to a match context, or is NULL
+ replacement Points to the replacement string
+ rlength Length of the replacement string
+ outputbuffer Points to the output buffer
+ outlengthptr Points to the length of the output buffer
+
+A match data block is needed only if you want to inspect the data from the
+final match that is returned in that block or if PCRE2_SUBSTITUTE_MATCHED is
+set. A match context is needed only if you want to:
+
+ Set up a callout function
+ Set a matching offset limit
+ Change the backtracking match limit
+ Change the backtracking depth limit
+ Set custom memory management in the match context
+
+The length, startoffset and rlength values are code units,
+not characters, as is the contents of the variable pointed at by
+outlengthptr. This variable must contain the length of the output buffer
+when the function is called. If the function is successful, the value is
+changed to the length of the new string, excluding the trailing zero that is
+automatically added.
+
+
+The subject and replacement lengths can be given as PCRE2_ZERO_TERMINATED for
+zero-terminated strings. The options are:
+
+ PCRE2_ANCHORED Match only at the first position
+ PCRE2_ENDANCHORED Match only at end of subject
+ PCRE2_NOTBOL Subject is not the beginning of a line
+ PCRE2_NOTEOL Subject is not the end of a line
+ PCRE2_NOTEMPTY An empty string is not a valid match
+ PCRE2_NOTEMPTY_ATSTART An empty string at the start of the subject is not a valid match
+ PCRE2_NO_JIT Do not use JIT matching
+ PCRE2_NO_UTF_CHECK Do not check for UTF validity in the subject or replacement
+ (only relevant if PCRE2_UTF was set at compile time)
+ PCRE2_SUBSTITUTE_EXTENDED Do extended replacement processing
+ PCRE2_SUBSTITUTE_GLOBAL Replace all occurrences in the subject
+ PCRE2_SUBSTITUTE_LITERAL The replacement string is literal
+ PCRE2_SUBSTITUTE_MATCHED Use pre-existing match data for first match
+ PCRE2_SUBSTITUTE_OVERFLOW_LENGTH If overflow, compute needed length
+ PCRE2_SUBSTITUTE_REPLACEMENT_ONLY Return only replacement string(s)
+ PCRE2_SUBSTITUTE_UNKNOWN_UNSET Treat unknown group as unset
+ PCRE2_SUBSTITUTE_UNSET_EMPTY Simple unset insert = empty string
+
+If PCRE2_SUBSTITUTE_LITERAL is set, PCRE2_SUBSTITUTE_EXTENDED,
+PCRE2_SUBSTITUTE_UNKNOWN_UNSET, and PCRE2_SUBSTITUTE_UNSET_EMPTY are ignored.
+
+
+If PCRE2_SUBSTITUTE_MATCHED is set, match_data must be non-NULL; its
+contents must be the result of a call to pcre2_match() (or
+pcre2_jit_match()) using the same pattern, subject pointer, effective
+subject length, start offset, and match options.
+
+
+The function returns the number of substitutions, which may be zero if there
+are no matches. The result may be greater than one only when
+PCRE2_SUBSTITUTE_GLOBAL is set. In the event of an error, a negative error code
+is returned.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_substring_copy_byname.html b/doc/html/pcre2_substring_copy_byname.html
new file mode 100644
index 0000000..64427ce
--- /dev/null
+++ b/doc/html/pcre2_substring_copy_byname.html
@@ -0,0 +1,58 @@
+
+
+pcre2_substring_copy_byname specification
+
+
+pcre2_substring_copy_byname man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_substring_copy_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_UCHAR *buffer, PCRE2_SIZE *bufflen);
+
+
+DESCRIPTION
+
+
+This is a convenience function for extracting a captured substring, identified
+by name, into a given buffer. The arguments are:
+
+ match_data The match data block for the match
+ name Name of the required substring
+ buffer Buffer to receive the string
+ bufflen Length of buffer (code units)
+
+The bufflen variable is updated to contain the length of the extracted
+string, excluding the trailing zero. The yield of the function is zero for
+success or one of the following error numbers:
+
+ PCRE2_ERROR_NOSUBSTRING there are no groups of that name
+ PCRE2_ERROR_UNAVAILBLE the ovector was too small for that group
+ PCRE2_ERROR_UNSET the group did not participate in the match
+ PCRE2_ERROR_NOMEMORY the buffer is not big enough
+
+If there is more than one group with the given name, the first one that is set
+is returned. In this situation PCRE2_ERROR_UNSET means that no group with the
+given name was set.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_substring_copy_bynumber.html b/doc/html/pcre2_substring_copy_bynumber.html
new file mode 100644
index 0000000..496bee4
--- /dev/null
+++ b/doc/html/pcre2_substring_copy_bynumber.html
@@ -0,0 +1,57 @@
+
+
+pcre2_substring_copy_bynumber specification
+
+
+pcre2_substring_copy_bynumber man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_substring_copy_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_UCHAR *buffer,
+ PCRE2_SIZE *bufflen);
+
+
+DESCRIPTION
+
+
+This is a convenience function for extracting a captured substring into a given
+buffer. The arguments are:
+
+ match_data The match data block for the match
+ number Number of the required substring
+ buffer Buffer to receive the string
+ bufflen Length of buffer
+
+The bufflen variable is updated with the length of the extracted string,
+excluding the terminating zero. The yield of the function is zero for success
+or one of the following error numbers:
+
+ PCRE2_ERROR_NOSUBSTRING there are no groups of that number
+ PCRE2_ERROR_UNAVAILBLE the ovector was too small for that group
+ PCRE2_ERROR_UNSET the group did not participate in the match
+ PCRE2_ERROR_NOMEMORY the buffer is too small
+
+
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_substring_free.html b/doc/html/pcre2_substring_free.html
new file mode 100644
index 0000000..ea884ec
--- /dev/null
+++ b/doc/html/pcre2_substring_free.html
@@ -0,0 +1,41 @@
+
+
+pcre2_substring_free specification
+
+
+pcre2_substring_free man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+void pcre2_substring_free(PCRE2_UCHAR *buffer);
+
+
+DESCRIPTION
+
+
+This is a convenience function for freeing the memory obtained by a previous
+call to pcre2_substring_get_byname() or
+pcre2_substring_get_bynumber(). Its only argument is a pointer to the
+string. If the argument is NULL, the function does nothing.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_substring_get_byname.html b/doc/html/pcre2_substring_get_byname.html
new file mode 100644
index 0000000..66ab078
--- /dev/null
+++ b/doc/html/pcre2_substring_get_byname.html
@@ -0,0 +1,60 @@
+
+
+pcre2_substring_get_byname specification
+
+
+pcre2_substring_get_byname man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_substring_get_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_UCHAR **bufferptr, PCRE2_SIZE *bufflen);
+
+
+DESCRIPTION
+
+
+This is a convenience function for extracting a captured substring by name into
+newly acquired memory. The arguments are:
+
+ match_data The match data for the match
+ name Name of the required substring
+ bufferptr Where to put the string pointer
+ bufflen Where to put the string length
+
+The memory in which the substring is placed is obtained by calling the same
+memory allocation function that was used for the match data block. The
+convenience function pcre2_substring_free() can be used to free it when
+it is no longer needed. The yield of the function is zero for success or one of
+the following error numbers:
+
+ PCRE2_ERROR_NOSUBSTRING there are no groups of that name
+ PCRE2_ERROR_UNAVAILBLE the ovector was too small for that group
+ PCRE2_ERROR_UNSET the group did not participate in the match
+ PCRE2_ERROR_NOMEMORY memory could not be obtained
+
+If there is more than one group with the given name, the first one that is set
+is returned. In this situation PCRE2_ERROR_UNSET means that no group with the
+given name was set.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_substring_get_bynumber.html b/doc/html/pcre2_substring_get_bynumber.html
new file mode 100644
index 0000000..d9f0d0c
--- /dev/null
+++ b/doc/html/pcre2_substring_get_bynumber.html
@@ -0,0 +1,58 @@
+
+
+pcre2_substring_get_bynumber specification
+
+
+pcre2_substring_get_bynumber man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_substring_get_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_UCHAR **bufferptr, PCRE2_SIZE *bufflen);
+
+
+DESCRIPTION
+
+
+This is a convenience function for extracting a captured substring by number
+into newly acquired memory. The arguments are:
+
+ match_data The match data for the match
+ number Number of the required substring
+ bufferptr Where to put the string pointer
+ bufflen Where to put the string length
+
+The memory in which the substring is placed is obtained by calling the same
+memory allocation function that was used for the match data block. The
+convenience function pcre2_substring_free() can be used to free it when
+it is no longer needed. The yield of the function is zero for success or one of
+the following error numbers:
+
+ PCRE2_ERROR_NOSUBSTRING there are no groups of that number
+ PCRE2_ERROR_UNAVAILBLE the ovector was too small for that group
+ PCRE2_ERROR_UNSET the group did not participate in the match
+ PCRE2_ERROR_NOMEMORY memory could not be obtained
+
+
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_substring_length_byname.html b/doc/html/pcre2_substring_length_byname.html
new file mode 100644
index 0000000..4b7fa79
--- /dev/null
+++ b/doc/html/pcre2_substring_length_byname.html
@@ -0,0 +1,48 @@
+
+
+pcre2_substring_length_byname specification
+
+
+pcre2_substring_length_byname man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_substring_length_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_SIZE *length);
+
+
+DESCRIPTION
+
+
+This function returns the length of a matched substring, identified by name.
+The arguments are:
+
+ match_data The match data block for the match
+ name The substring name
+ length Where to return the length, or NULL
+
+The third argument may be NULL if all you want to know is whether or not a
+substring is set. The yield is zero on success, or a negative error code
+otherwise.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_substring_length_bynumber.html b/doc/html/pcre2_substring_length_bynumber.html
new file mode 100644
index 0000000..51371fa
--- /dev/null
+++ b/doc/html/pcre2_substring_length_bynumber.html
@@ -0,0 +1,48 @@
+
+
+pcre2_substring_length_bynumber specification
+
+
+pcre2_substring_length_bynumber man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_substring_length_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_SIZE *length);
+
+
+DESCRIPTION
+
+
+This function returns the length of a matched substring, identified by number.
+The arguments are:
+
+ match_data The match data block for the match
+ number The substring number
+ length Where to return the length, or NULL
+
+The third argument may be NULL if all you want to know is whether or not a
+substring is set. The yield is zero on success, or a negative error code
+otherwise. After a partial match, only substring 0 is available.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_substring_list_free.html b/doc/html/pcre2_substring_list_free.html
new file mode 100644
index 0000000..0606116
--- /dev/null
+++ b/doc/html/pcre2_substring_list_free.html
@@ -0,0 +1,41 @@
+
+
+pcre2_substring_list_free specification
+
+
+pcre2_substring_list_free man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+void pcre2_substring_list_free(PCRE2_UCHAR **list);
+
+
+DESCRIPTION
+
+
+This is a convenience function for freeing the store obtained by a previous
+call to pcre2substring_list_get(). Its only argument is a pointer to
+the list of string pointers. If the argument is NULL, the function returns
+immediately, without doing anything.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_substring_list_get.html b/doc/html/pcre2_substring_list_get.html
new file mode 100644
index 0000000..5d22331
--- /dev/null
+++ b/doc/html/pcre2_substring_list_get.html
@@ -0,0 +1,56 @@
+
+
+pcre2_substring_list_get specification
+
+
+pcre2_substring_list_get man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_substring_list_get(pcre2_match_data *match_data,
+" PCRE2_UCHAR ***listptr, PCRE2_SIZE **lengthsptr);
+
+
+DESCRIPTION
+
+
+This is a convenience function for extracting all the captured substrings after
+a pattern match. It builds a list of pointers to the strings, and (optionally)
+a second list that contains their lengths (in code units), excluding a
+terminating zero that is added to each of them. All this is done in a single
+block of memory that is obtained using the same memory allocation function that
+was used to get the match data block. The convenience function
+pcre2_substring_list_free() can be used to free it when it is no longer
+needed. The arguments are:
+
+ match_data The match data block
+ listptr Where to put a pointer to the list
+ lengthsptr Where to put a pointer to the lengths, or NULL
+
+A pointer to a list of pointers is put in the variable whose address is in
+listptr. The list is terminated by a NULL pointer. If lengthsptr is
+not NULL, a matching list of lengths is created, and its address is placed in
+lengthsptr. The yield of the function is zero on success or
+PCRE2_ERROR_NOMEMORY if sufficient memory could not be obtained.
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_substring_nametable_scan.html b/doc/html/pcre2_substring_nametable_scan.html
new file mode 100644
index 0000000..ae35328
--- /dev/null
+++ b/doc/html/pcre2_substring_nametable_scan.html
@@ -0,0 +1,53 @@
+
+
+pcre2_substring_nametable_scan specification
+
+
+pcre2_substring_nametable_scan man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_substring_nametable_scan(const pcre2_code *code,
+ PCRE2_SPTR name, PCRE2_SPTR *first, PCRE2_SPTR *last);
+
+
+DESCRIPTION
+
+
+This convenience function finds, for a compiled pattern, the first and last
+entries for a given name in the table that translates capture group names into
+numbers.
+
+ code Compiled regular expression
+ name Name whose entries required
+ first Where to return a pointer to the first entry
+ last Where to return a pointer to the last entry
+
+When the name is found in the table, if first is NULL, the function
+returns a group number, but if there is more than one matching entry, it is not
+defined which one. Otherwise, when both pointers have been set, the yield of
+the function is the length of each entry in code units. If the name is not
+found, PCRE2_ERROR_NOSUBSTRING is returned.
+
+
+There is a complete description of the PCRE2 native API, including the format of
+the table entries, in the
+pcre2api
+page, and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2_substring_number_from_name.html b/doc/html/pcre2_substring_number_from_name.html
new file mode 100644
index 0000000..f00cef6
--- /dev/null
+++ b/doc/html/pcre2_substring_number_from_name.html
@@ -0,0 +1,50 @@
+
+
+pcre2_substring_number_from_name specification
+
+
+pcre2_substring_number_from_name man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SYNOPSIS
+
+
+#include <pcre2.h>
+
+
+int pcre2_substring_number_from_name(const pcre2_code *code,
+ PCRE2_SPTR name);
+
+
+DESCRIPTION
+
+
+This convenience function finds the number of a named substring capturing
+parenthesis in a compiled pattern, provided that it is a unique name. The
+function arguments are:
+
+ code Compiled regular expression
+ name Name whose number is required
+
+The yield of the function is the number of the parenthesis if the name is
+found, or PCRE2_ERROR_NOSUBSTRING if it is not found. When duplicate names are
+allowed (PCRE2_DUPNAMES is set), if the name is not unique,
+PCRE2_ERROR_NOUNIQUESUBSTRING is returned. You can obtain the list of numbers
+with the same name by calling pcre2_substring_nametable_scan().
+
+
+There is a complete description of the PCRE2 native API in the
+pcre2api
+page and a description of the POSIX API in the
+pcre2posix
+page.
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2api.html b/doc/html/pcre2api.html
new file mode 100644
index 0000000..8b6f7fc
--- /dev/null
+++ b/doc/html/pcre2api.html
@@ -0,0 +1,4649 @@
+
+
+pcre2api specification
+
+
+pcre2api man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+#include <pcre2.h>
+
+
+PCRE2 is a new API for PCRE, starting at release 10.0. This document contains a
+description of all its native functions. See the
+pcre2
+document for an overview of all the PCRE2 documentation.
+
+
+
+pcre2_code *pcre2_compile(PCRE2_SPTR pattern, PCRE2_SIZE length,
+ uint32_t options, int *errorcode, PCRE2_SIZE *erroroffset,
+ pcre2_compile_context *ccontext);
+
+
+void pcre2_code_free(pcre2_code *code);
+
+
+pcre2_match_data *pcre2_match_data_create(uint32_t ovecsize,
+ pcre2_general_context *gcontext);
+
+
+pcre2_match_data *pcre2_match_data_create_from_pattern(
+ const pcre2_code *code, pcre2_general_context *gcontext);
+
+
+int pcre2_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext);
+
+
+int pcre2_dfa_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext,
+ int *workspace, PCRE2_SIZE wscount);
+
+
+void pcre2_match_data_free(pcre2_match_data *match_data);
+
+
+
+PCRE2_SPTR pcre2_get_mark(pcre2_match_data *match_data);
+
+
+PCRE2_SIZE pcre2_get_match_data_size(pcre2_match_data *match_data);
+
+
+PCRE2_SIZE pcre2_get_match_data_heapframes_size(
+ pcre2_match_data *match_data);
+
+
+uint32_t pcre2_get_ovector_count(pcre2_match_data *match_data);
+
+
+PCRE2_SIZE *pcre2_get_ovector_pointer(pcre2_match_data *match_data);
+
+
+PCRE2_SIZE pcre2_get_startchar(pcre2_match_data *match_data);
+
+
+
+pcre2_general_context *pcre2_general_context_create(
+ void *(*private_malloc)(PCRE2_SIZE, void *),
+ void (*private_free)(void *, void *), void *memory_data);
+
+
+pcre2_general_context *pcre2_general_context_copy(
+ pcre2_general_context *gcontext);
+
+
+void pcre2_general_context_free(pcre2_general_context *gcontext);
+
+
+
+pcre2_compile_context *pcre2_compile_context_create(
+ pcre2_general_context *gcontext);
+
+
+pcre2_compile_context *pcre2_compile_context_copy(
+ pcre2_compile_context *ccontext);
+
+
+void pcre2_compile_context_free(pcre2_compile_context *ccontext);
+
+
+int pcre2_set_bsr(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+
+int pcre2_set_character_tables(pcre2_compile_context *ccontext,
+ const uint8_t *tables);
+
+
+int pcre2_set_compile_extra_options(pcre2_compile_context *ccontext,
+ uint32_t extra_options);
+
+
+int pcre2_set_max_pattern_length(pcre2_compile_context *ccontext,
+ PCRE2_SIZE value);
+
+
+int pcre2_set_max_pattern_compiled_length(
+ pcre2_compile_context *ccontext, PCRE2_SIZE value);
+
+
+int pcre2_set_max_varlookbehind(pcre2_compile_contest *ccontext,
+ uint32_t value);
+
+
+int pcre2_set_newline(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+
+int pcre2_set_parens_nest_limit(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+
+int pcre2_set_compile_recursion_guard(pcre2_compile_context *ccontext,
+ int (*guard_function)(uint32_t, void *), void *user_data);
+
+
+int pcre2_set_optimize(pcre2_compile_context *ccontext,
+ uint32_t directive);
+
+
+
+pcre2_match_context *pcre2_match_context_create(
+ pcre2_general_context *gcontext);
+
+
+pcre2_match_context *pcre2_match_context_copy(
+ pcre2_match_context *mcontext);
+
+
+void pcre2_match_context_free(pcre2_match_context *mcontext);
+
+
+int pcre2_set_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_callout_block *, void *),
+ void *callout_data);
+
+
+int pcre2_set_substitute_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_substitute_callout_block *, void *),
+ void *callout_data);
+
+
+int pcre2_set_substitute_case_callout(pcre2_match_context *mcontext,
+ PCRE2_SIZE (*callout_function)(PCRE2_SPTR, PCRE2_SIZE,
+ PCRE2_UCHAR *, PCRE2_SIZE,
+ int, void *),
+ void *callout_data);
+
+
+int pcre2_set_offset_limit(pcre2_match_context *mcontext,
+ PCRE2_SIZE value);
+
+
+int pcre2_set_heap_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+
+int pcre2_set_match_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+
+int pcre2_set_depth_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+
+
+int pcre2_substring_copy_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_UCHAR *buffer, PCRE2_SIZE *bufflen);
+
+
+int pcre2_substring_copy_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_UCHAR *buffer,
+ PCRE2_SIZE *bufflen);
+
+
+void pcre2_substring_free(PCRE2_UCHAR *buffer);
+
+
+int pcre2_substring_get_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_UCHAR **bufferptr, PCRE2_SIZE *bufflen);
+
+
+int pcre2_substring_get_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_UCHAR **bufferptr,
+ PCRE2_SIZE *bufflen);
+
+
+int pcre2_substring_length_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_SIZE *length);
+
+
+int pcre2_substring_length_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_SIZE *length);
+
+
+int pcre2_substring_nametable_scan(const pcre2_code *code,
+ PCRE2_SPTR name, PCRE2_SPTR *first, PCRE2_SPTR *last);
+
+
+int pcre2_substring_number_from_name(const pcre2_code *code,
+ PCRE2_SPTR name);
+
+
+void pcre2_substring_list_free(PCRE2_UCHAR **list);
+
+
+int pcre2_substring_list_get(pcre2_match_data *match_data,
+ PCRE2_UCHAR ***listptr, PCRE2_SIZE **lengthsptr);
+
+
+
+int pcre2_substitute(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext, PCRE2_SPTR replacement,
+ PCRE2_SIZE rlength, PCRE2_UCHAR *outputbuffer,
+ PCRE2_SIZE *outlengthptr);
+
+
+
+int pcre2_jit_compile(pcre2_code *code, uint32_t options);
+
+
+int pcre2_jit_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext);
+
+
+void pcre2_jit_free_unused_memory(pcre2_general_context *gcontext);
+
+
+pcre2_jit_stack *pcre2_jit_stack_create(size_t startsize,
+ size_t maxsize, pcre2_general_context *gcontext);
+
+
+void pcre2_jit_stack_assign(pcre2_match_context *mcontext,
+ pcre2_jit_callback callback_function, void *callback_data);
+
+
+void pcre2_jit_stack_free(pcre2_jit_stack *jit_stack);
+
+
+
+int32_t pcre2_serialize_decode(pcre2_code **codes,
+ int32_t number_of_codes, const uint8_t *bytes,
+ pcre2_general_context *gcontext);
+
+
+int32_t pcre2_serialize_encode(const pcre2_code **codes,
+ int32_t number_of_codes, uint8_t **serialized_bytes,
+ PCRE2_SIZE *serialized_size, pcre2_general_context *gcontext);
+
+
+void pcre2_serialize_free(uint8_t *bytes);
+
+
+int32_t pcre2_serialize_get_number_of_codes(const uint8_t *bytes);
+
+
+
+pcre2_code *pcre2_code_copy(const pcre2_code *code);
+
+
+pcre2_code *pcre2_code_copy_with_tables(const pcre2_code *code);
+
+
+int pcre2_get_error_message(int errorcode, PCRE2_UCHAR *buffer,
+ PCRE2_SIZE bufflen);
+
+
+const uint8_t *pcre2_maketables(pcre2_general_context *gcontext);
+
+
+void pcre2_maketables_free(pcre2_general_context *gcontext,
+ const uint8_t *tables);
+
+
+int pcre2_pattern_info(const pcre2_code *code, uint32_t what,
+ void *where);
+
+
+int pcre2_callout_enumerate(const pcre2_code *code,
+ int (*callback)(pcre2_callout_enumerate_block *, void *),
+ void *user_data);
+
+
+int pcre2_config(uint32_t what, void *where);
+
+
+
+int pcre2_set_recursion_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+
+int pcre2_set_recursion_memory_management(
+ pcre2_match_context *mcontext,
+ void *(*private_malloc)(size_t, void *),
+ void (*private_free)(void *, void *), void *memory_data);
+
+
+These functions became obsolete at release 10.30 and are retained only for
+backward compatibility. They should not be used in new code. The first is
+replaced by pcre2_set_depth_limit(); the second is no longer needed and
+has no effect (it always returns zero).
+
+
+
+pcre2_convert_context *pcre2_convert_context_create(
+ pcre2_general_context *gcontext);
+
+
+pcre2_convert_context *pcre2_convert_context_copy(
+ pcre2_convert_context *cvcontext);
+
+
+void pcre2_convert_context_free(pcre2_convert_context *cvcontext);
+
+
+int pcre2_set_glob_escape(pcre2_convert_context *cvcontext,
+ uint32_t escape_char);
+
+
+int pcre2_set_glob_separator(pcre2_convert_context *cvcontext,
+ uint32_t separator_char);
+
+
+int pcre2_pattern_convert(PCRE2_SPTR pattern, PCRE2_SIZE length,
+ uint32_t options, PCRE2_UCHAR **buffer,
+ PCRE2_SIZE *blength, pcre2_convert_context *cvcontext);
+
+
+void pcre2_converted_pattern_free(PCRE2_UCHAR *converted_pattern);
+
+
+These functions provide a way of converting non-PCRE2 patterns into
+patterns that can be processed by pcre2_compile(). This facility is
+experimental and may be changed in future releases. At present, "globs" and
+POSIX basic and extended patterns can be converted. Details are given in the
+pcre2convert
+documentation.
+
+
+
+There are three PCRE2 libraries, supporting 8-bit, 16-bit, and 32-bit code
+units, respectively. However, there is just one header file, pcre2.h.
+This contains the function prototypes and other definitions for all three
+libraries. One, two, or all three can be installed simultaneously. On Unix-like
+systems the libraries are called libpcre2-8, libpcre2-16, and
+libpcre2-32, and they can also co-exist with the original PCRE libraries.
+Every PCRE2 function comes in three different forms, one for each library, for
+example:
+
+ pcre2_compile_8()
+ pcre2_compile_16()
+ pcre2_compile_32()
+
+There are also three different sets of data types:
+
+ PCRE2_UCHAR8, PCRE2_UCHAR16, PCRE2_UCHAR32
+ PCRE2_SPTR8, PCRE2_SPTR16, PCRE2_SPTR32
+
+The UCHAR types define unsigned code units of the appropriate widths.
+For example, PCRE2_UCHAR16 is usually defined as `uint16_t'.
+The SPTR types are pointers to constants of the equivalent UCHAR types,
+that is, they are pointers to vectors of unsigned code units.
+
+
+Character strings are passed to a PCRE2 library as sequences of unsigned
+integers in code units of the appropriate width. The length of a string may
+be given as a number of code units, or the string may be specified as
+zero-terminated.
+
+
+Many applications use only one code unit width. For their convenience, macros
+are defined whose names are the generic forms such as pcre2_compile() and
+PCRE2_SPTR. These macros use the value of the macro PCRE2_CODE_UNIT_WIDTH to
+generate the appropriate width-specific function and macro names.
+PCRE2_CODE_UNIT_WIDTH is not defined by default. An application must define it
+to be 8, 16, or 32 before including pcre2.h in order to make use of the
+generic names.
+
+
+Applications that use more than one code unit width can be linked with more
+than one PCRE2 library, but must define PCRE2_CODE_UNIT_WIDTH to be 0 before
+including pcre2.h, and then use the real function names. Any code that is
+to be included in an environment where the value of PCRE2_CODE_UNIT_WIDTH is
+unknown should also use the real function names. (Unfortunately, it is not
+possible in C code to save and restore the value of a macro.)
+
+
+If PCRE2_CODE_UNIT_WIDTH is not defined before including pcre2.h, a
+compiler error occurs.
+
+
+When using multiple libraries in an application, you must take care when
+processing any particular pattern to use only functions from a single library.
+For example, if you want to run a match using a pattern that was compiled with
+pcre2_compile_16(), you must do so with pcre2_match_16(), not
+pcre2_match_8() or pcre2_match_32().
+
+
+In the function summaries above, and in the rest of this document and other
+PCRE2 documents, functions and data types are described using their generic
+names, without the _8, _16, or _32 suffix.
+
+
+
+PCRE2 has its own native API, which is described in this document. There are
+also some wrapper functions for the 8-bit library that correspond to the
+POSIX regular expression API, but they do not give access to all the
+functionality of PCRE2 and they are not thread-safe. They are described in the
+pcre2posix
+documentation. Both these APIs define a set of C function calls.
+
+
+The native API C data types, function prototypes, option values, and error
+codes are defined in the header file pcre2.h, which also contains
+definitions of PCRE2_MAJOR and PCRE2_MINOR, the major and minor release numbers
+for the library. Applications can use these to include support for different
+releases of PCRE2.
+
+
+In a Windows environment, if you want to statically link an application program
+against a non-dll PCRE2 library, you must define PCRE2_STATIC before including
+pcre2.h.
+
+
+The functions pcre2_compile() and pcre2_match() are used for
+compiling and matching regular expressions in a Perl-compatible manner. A
+sample program that demonstrates the simplest way of using them is provided in
+the file called pcre2demo.c in the PCRE2 source distribution. A listing
+of this program is given in the
+pcre2demo
+documentation, and the
+pcre2sample
+documentation describes how to compile and run it.
+
+
+The compiling and matching functions recognize various options that are passed
+as bits in an options argument. There are also some more complicated parameters
+such as custom memory management functions and resource limits that are passed
+in "contexts" (which are just memory blocks, described below). Simple
+applications do not need to make use of contexts.
+
+
+Just-in-time (JIT) compiler support is an optional feature of PCRE2 that can be
+built in appropriate hardware environments. It greatly speeds up the matching
+performance of many patterns. Programs can request that it be used if
+available by calling pcre2_jit_compile() after a pattern has been
+successfully compiled by pcre2_compile(). This does nothing if JIT
+support is not available.
+
+
+More complicated programs might need to make use of the specialist functions
+pcre2_jit_stack_create(), pcre2_jit_stack_free(), and
+pcre2_jit_stack_assign() in order to control the JIT code's memory usage.
+
+
+JIT matching is automatically used by pcre2_match() if it is available,
+unless the PCRE2_NO_JIT option is set. There is also a direct interface for JIT
+matching, which gives improved performance at the expense of less sanity
+checking. The JIT-specific functions are discussed in the
+pcre2jit
+documentation.
+
+
+A second matching function, pcre2_dfa_match(), which is not
+Perl-compatible, is also provided. This uses a different algorithm for the
+matching. The alternative algorithm finds all possible matches (at a given
+point in the subject), and scans the subject just once (unless there are
+lookaround assertions). However, this algorithm does not return captured
+substrings. A description of the two matching algorithms and their advantages
+and disadvantages is given in the
+pcre2matching
+documentation. There is no JIT support for pcre2_dfa_match().
+
+
+In addition to the main compiling and matching functions, there are convenience
+functions for extracting captured substrings from a subject string that has
+been matched by pcre2_match(). They are:
+
+ pcre2_substring_copy_byname()
+ pcre2_substring_copy_bynumber()
+ pcre2_substring_get_byname()
+ pcre2_substring_get_bynumber()
+ pcre2_substring_list_get()
+ pcre2_substring_length_byname()
+ pcre2_substring_length_bynumber()
+ pcre2_substring_nametable_scan()
+ pcre2_substring_number_from_name()
+
+pcre2_substring_free() and pcre2_substring_list_free() are also
+provided, to free memory used for extracted strings. If either of these
+functions is called with a NULL argument, the function returns immediately
+without doing anything.
+
+
+The function pcre2_substitute() can be called to match a pattern and
+return a copy of the subject string with substitutions for parts that were
+matched.
+
+
+Functions whose names begin with pcre2_serialize_ are used for saving
+compiled patterns on disc or elsewhere, and reloading them later.
+
+
+Finally, there are functions for finding out information about a compiled
+pattern (pcre2_pattern_info()) and about the configuration with which
+PCRE2 was built (pcre2_config()) and that it is using.
+
+
+Functions with names ending with _free() are used for freeing memory
+blocks of various sorts. In all cases, if one of these functions is called with
+a NULL argument, it does nothing.
+
+
+
+The PCRE2 API uses string lengths and offsets into strings of code units in
+several places. These values are always of type PCRE2_SIZE, which is an
+unsigned integer type, currently always defined as size_t. The largest
+value that can be stored in such a type (that is ~(PCRE2_SIZE)0) is reserved
+as a special indicator for zero-terminated strings and unset offsets.
+Therefore, the longest string that can be handled is one less than this
+maximum. Note that string lengths are always given in code units. Only in the
+8-bit library is such a length the same as the number of bytes in the string.
+
+
+
+PCRE2 supports five different conventions for indicating line breaks in
+strings: a single CR (carriage return) character, a single LF (linefeed)
+character, the two-character sequence CRLF, any of the three preceding, or any
+Unicode newline sequence. The Unicode newline sequences are the three just
+mentioned, plus the single characters VT (vertical tab, U+000B), FF (form feed,
+U+000C), NEL (next line, U+0085), LS (line separator, U+2028), and PS
+(paragraph separator, U+2029).
+
+
+Each of the first three conventions is used by at least one operating system as
+its standard newline sequence. When PCRE2 is built, a default can be specified.
+If it is not, the default is set to LF, which is the Unix standard. However,
+the newline convention can be changed by an application when calling
+pcre2_compile(), or it can be specified by special text at the start of
+the pattern itself; this overrides any other settings. See the
+pcre2pattern
+page for details of the special character sequences.
+
+
+In the PCRE2 documentation the word "newline" is used to mean "the character or
+pair of characters that indicate a line break". The choice of newline
+convention affects the handling of the dot, circumflex, and dollar
+metacharacters, the handling of #-comments in /x mode, and, when CRLF is a
+recognized line ending sequence, the match position advancement for a
+non-anchored pattern. There is more detail about this in the
+section on pcre2_match() options
+below.
+
+
+The choice of newline convention does not affect the interpretation of
+the \n or \r escape sequences, nor does it affect what \R matches; this has
+its own separate convention.
+
+
+
+In a multithreaded application it is important to keep thread-specific data
+separate from data that can be shared between threads. The PCRE2 library code
+itself is thread-safe: it contains no static or global variables. The API is
+designed to be fairly simple for non-threaded applications while at the same
+time ensuring that multithreaded applications can use it.
+
+
+There are several different blocks of data that are used to pass information
+between the application and the PCRE2 libraries.
+
+
+The compiled pattern
+
+
+A pointer to the compiled form of a pattern is returned to the user when
+pcre2_compile() is successful. The data in the compiled pattern is fixed,
+and does not change when the pattern is matched. Therefore, it is thread-safe,
+that is, the same compiled pattern can be used by more than one thread
+simultaneously. For example, an application can compile all its patterns at the
+start, before forking off multiple threads that use them. However, if the
+just-in-time (JIT) optimization feature is being used, it needs separate memory
+stack areas for each thread. See the
+pcre2jit
+documentation for more details.
+
+
+In a more complicated situation, where patterns are compiled only when they are
+first needed, but are still shared between threads, pointers to compiled
+patterns must be protected from simultaneous writing by multiple threads. This
+is somewhat tricky to do correctly. If you know that writing to a pointer is
+atomic in your environment, you can use logic like this:
+
+ Get a read-only (shared) lock (mutex) for pointer
+ if (pointer == NULL)
+ {
+ Get a write (unique) lock for pointer
+ if (pointer == NULL) pointer = pcre2_compile(...
+ }
+ Release the lock
+ Use pointer in pcre2_match()
+
+Of course, testing for compilation errors should also be included in the code.
+
+
+The reason for checking the pointer a second time is as follows: Several
+threads may have acquired the shared lock and tested the pointer for being
+NULL, but only one of them will be given the write lock, with the rest kept
+waiting. The winning thread will compile the pattern and store the result.
+After this thread releases the write lock, another thread will get it, and if
+it does not retest pointer for being NULL, will recompile the pattern and
+overwrite the pointer, creating a memory leak and possibly causing other
+issues.
+
+
+In an environment where writing to a pointer may not be atomic, the above logic
+is not sufficient. The thread that is doing the compiling may be descheduled
+after writing only part of the pointer, which could cause other threads to use
+an invalid value. Instead of checking the pointer itself, a separate "pointer
+is valid" flag (that can be updated atomically) must be used:
+
+ Get a read-only (shared) lock (mutex) for pointer
+ if (!pointer_is_valid)
+ {
+ Get a write (unique) lock for pointer
+ if (!pointer_is_valid)
+ {
+ pointer = pcre2_compile(...
+ pointer_is_valid = TRUE
+ }
+ }
+ Release the lock
+ Use pointer in pcre2_match()
+
+If JIT is being used, but the JIT compilation is not being done immediately
+(perhaps waiting to see if the pattern is used often enough), similar logic is
+required. JIT compilation updates a value within the compiled code block, so a
+thread must gain unique write access to the pointer before calling
+pcre2_jit_compile(). Alternatively, pcre2_code_copy() or
+pcre2_code_copy_with_tables() can be used to obtain a private copy of the
+compiled code before calling the JIT compiler.
+
+
+Context blocks
+
+
+The next main section below introduces the idea of "contexts" in which PCRE2
+functions are called. A context is nothing more than a collection of parameters
+that control the way PCRE2 operates. Grouping a number of parameters together
+in a context is a convenient way of passing them to a PCRE2 function without
+using lots of arguments. The parameters that are stored in contexts are in some
+sense "advanced features" of the API. Many straightforward applications will
+not need to use contexts.
+
+
+In a multithreaded application, if the parameters in a context are values that
+are never changed, the same context can be used by all the threads. However, if
+any thread needs to change any value in a context, it must make its own
+thread-specific copy.
+
+
+Match blocks
+
+
+The matching functions need a block of memory for storing the results of a
+match. This includes details of what was matched, as well as additional
+information such as the name of a (*MARK) setting. Each thread must provide its
+own copy of this memory.
+
+
+
+Some PCRE2 functions have a lot of parameters, many of which are used only by
+specialist applications, for example, those that use custom memory management
+or non-standard character tables. To keep function argument lists at a
+reasonable size, and at the same time to keep the API extensible, "uncommon"
+parameters are passed to certain functions in a context instead of
+directly. A context is just a block of memory that holds the parameter values.
+Applications that do not need to adjust any of the context parameters can pass
+NULL when a context pointer is required.
+
+
+There are three different types of context: a general context that is relevant
+for several PCRE2 operations, a compile-time context, and a match-time context.
+
+
+The general context
+
+
+At present, this context just contains pointers to (and data for) external
+memory management functions that are called from several places in the PCRE2
+library. The context is named `general' rather than specifically `memory'
+because in future other fields may be added. If you do not want to supply your
+own custom memory management functions, you do not need to bother with a
+general context. A general context is created by:
+
+
+pcre2_general_context *pcre2_general_context_create(
+ void *(*private_malloc)(PCRE2_SIZE, void *),
+ void (*private_free)(void *, void *), void *memory_data);
+
+
+The two function pointers specify custom memory management functions, whose
+prototypes are:
+
+ void *private_malloc(PCRE2_SIZE, void *);
+ void private_free(void *, void *);
+
+Whenever code in PCRE2 calls these functions, the final argument is the value
+of memory_data. Either of the first two arguments of the creation
+function may be NULL, in which case the system memory management functions
+malloc() and free() are used. (This is not currently useful, as
+there are no other fields in a general context, but in future there might be.)
+The private_malloc() function is used (if supplied) to obtain memory for
+storing the context, and all three values are saved as part of the context.
+
+
+Whenever PCRE2 creates a data block of any kind, the block contains a pointer
+to the free() function that matches the malloc() function that was
+used. When the time comes to free the block, this function is called.
+
+
+A general context can be copied by calling:
+
+
+pcre2_general_context *pcre2_general_context_copy(
+ pcre2_general_context *gcontext);
+
+
+The memory used for a general context should be freed by calling:
+
+
+void pcre2_general_context_free(pcre2_general_context *gcontext);
+
+
+If this function is passed a NULL argument, it returns immediately without
+doing anything.
+
+
+The compile context
+
+
+A compile context is required if you want to provide an external function for
+stack checking during compilation or to change the default values of any of the
+following compile-time parameters:
+
+ What \R matches (Unicode newlines or CR, LF, CRLF only)
+ PCRE2's character tables
+ The newline character sequence
+ The compile time nested parentheses limit
+ The maximum length of the pattern string
+ The extra options bits (none set by default)
+ Which performance optimizations the compiler should apply
+
+A compile context is also required if you are using custom memory management.
+If none of these apply, just pass NULL as the context argument of
+pcre2_compile().
+
+
+A compile context is created, copied, and freed by the following functions:
+
+
+pcre2_compile_context *pcre2_compile_context_create(
+ pcre2_general_context *gcontext);
+
+
+pcre2_compile_context *pcre2_compile_context_copy(
+ pcre2_compile_context *ccontext);
+
+
+void pcre2_compile_context_free(pcre2_compile_context *ccontext);
+
+
+A compile context is created with default values for its parameters. These can
+be changed by calling the following functions, which return 0 on success, or
+PCRE2_ERROR_BADDATA if invalid data is detected.
+
+
+int pcre2_set_bsr(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+
+The value must be PCRE2_BSR_ANYCRLF, to specify that \R matches only CR, LF,
+or CRLF, or PCRE2_BSR_UNICODE, to specify that \R matches any Unicode line
+ending sequence. The value is used by the JIT compiler and by the two
+interpreted matching functions, pcre2_match() and
+pcre2_dfa_match().
+
+
+int pcre2_set_character_tables(pcre2_compile_context *ccontext,
+ const uint8_t *tables);
+
+
+The value must be the result of a call to pcre2_maketables(), whose only
+argument is a general context. This function builds a set of character tables
+in the current locale.
+
+
+int pcre2_set_compile_extra_options(pcre2_compile_context *ccontext,
+ uint32_t extra_options);
+
+
+As PCRE2 has developed, almost all the 32 option bits that are available in
+the options argument of pcre2_compile() have been used up. To avoid
+running out, the compile context contains a set of extra option bits which are
+used for some newer, assumed rarer, options. This function sets those bits. It
+always sets all the bits (either on or off). It does not modify any existing
+setting. The available options are defined in the section entitled "Extra
+compile options"
+below.
+
+
+int pcre2_set_max_pattern_length(pcre2_compile_context *ccontext,
+ PCRE2_SIZE value);
+
+
+This sets a maximum length, in code units, for any pattern string that is
+compiled with this context. If the pattern is longer, an error is generated.
+This facility is provided so that applications that accept patterns from
+external sources can limit their size. The default is the largest number that a
+PCRE2_SIZE variable can hold, which is effectively unlimited.
+
+
+int pcre2_set_max_pattern_compiled_length(
+ pcre2_compile_context *ccontext, PCRE2_SIZE value);
+
+
+This sets a maximum size, in bytes, for the memory needed to hold the compiled
+version of a pattern that is compiled with this context. If the pattern needs
+more memory, an error is generated. This facility is provided so that
+applications that accept patterns from external sources can limit the amount of
+memory they use. The default is the largest number that a PCRE2_SIZE variable
+can hold, which is effectively unlimited.
+
+
+int pcre2_set_max_varlookbehind(pcre2_compile_contest *ccontext,
+ uint32_t value);
+
+
+This sets a maximum length for the number of characters matched by a
+variable-length lookbehind assertion. The default is set when PCRE2 is built,
+with the ultimate default being 255, the same as Perl. Lookbehind assertions
+without a bounding length are not supported.
+
+
+int pcre2_set_newline(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+
+This specifies which characters or character sequences are to be recognized as
+newlines. The value must be one of PCRE2_NEWLINE_CR (carriage return only),
+PCRE2_NEWLINE_LF (linefeed only), PCRE2_NEWLINE_CRLF (the two-character
+sequence CR followed by LF), PCRE2_NEWLINE_ANYCRLF (any of the above),
+PCRE2_NEWLINE_ANY (any Unicode newline sequence), or PCRE2_NEWLINE_NUL (the
+NUL character, that is a binary zero).
+
+
+A pattern can override the value set in the compile context by starting with a
+sequence such as (*CRLF). See the
+pcre2pattern
+page for details.
+
+
+When a pattern is compiled with the PCRE2_EXTENDED or PCRE2_EXTENDED_MORE
+option, the newline convention affects the recognition of the end of internal
+comments starting with #. The value is saved with the compiled pattern for
+subsequent use by the JIT compiler and by the two interpreted matching
+functions, pcre2_match() and pcre2_dfa_match().
+
+
+int pcre2_set_parens_nest_limit(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+
+This parameter adjusts the limit, set when PCRE2 is built (default 250), on the
+depth of parenthesis nesting in a pattern. This limit stops rogue patterns
+using up too much system stack when being compiled. The limit applies to
+parentheses of all kinds, not just capturing parentheses.
+
+
+int pcre2_set_compile_recursion_guard(pcre2_compile_context *ccontext,
+ int (*guard_function)(uint32_t, void *), void *user_data);
+
+
+There is at least one application that runs PCRE2 in threads with very limited
+system stack, where running out of stack is to be avoided at all costs. The
+parenthesis limit above cannot take account of how much stack is actually
+available during compilation. For a finer control, you can supply a function
+that is called whenever pcre2_compile() starts to compile a parenthesized
+part of a pattern. This function can check the actual stack size (or anything
+else that it wants to, of course).
+
+
+The first argument to the callout function gives the current depth of
+nesting, and the second is user data that is set up by the last argument of
+pcre2_set_compile_recursion_guard(). The callout function should return
+zero if all is well, or non-zero to force an error.
+
+
+int pcre2_set_optimize(pcre2_compile_context *ccontext,
+ uint32_t directive);
+
+
+PCRE2 can apply various performance optimizations during compilation, in order
+to make matching faster. For example, the compiler might convert some regex
+constructs into an equivalent construct which pcre2_match() can execute
+faster. By default, all available optimizations are enabled. However, in rare
+cases, one might wish to disable specific optimizations. For example, if it is
+known that some optimizations cannot benefit a certain regex, it might be
+desirable to disable them, in order to speed up compilation.
+
+
+The permitted values of directive are as follows:
+
+ PCRE2_OPTIMIZATION_FULL
+
+Enable all optional performance optimizations. This is the default value.
+
+ PCRE2_OPTIMIZATION_NONE
+
+Disable all optional performance optimizations.
+
+ PCRE2_AUTO_POSSESS
+ PCRE2_AUTO_POSSESS_OFF
+
+Enable/disable "auto-possessification" of variable quantifiers such as * and +.
+This optimization, for example, turns a+b into a++b in order to avoid
+backtracks into a+ that can never be successful. However, if callouts are in
+use, auto-possessification means that some callouts are never taken. You can
+disable this optimization if you want the matching functions to do a full,
+unoptimized search and run all the callouts.
+
+ PCRE2_DOTSTAR_ANCHOR
+ PCRE2_DOTSTAR_ANCHOR_OFF
+
+Enable/disable an optimization that is applied when .* is the first significant
+item in a top-level branch of a pattern, and all the other branches also start
+with .* or with \A or \G or ^. Such a pattern is automatically anchored if
+PCRE2_DOTALL is set for all the .* items and PCRE2_MULTILINE is not set for any
+^ items. Otherwise, the fact that any match must start either at the start of
+the subject or following a newline is remembered. Like other optimizations,
+this can cause callouts to be skipped.
+
+
+Dotstar anchor optimization is automatically disabled for .* if it is inside an
+atomic group or a capture group that is the subject of a backreference, or if
+the pattern contains (*PRUNE) or (*SKIP).
+
+ PCRE2_START_OPTIMIZE
+ PCRE2_START_OPTIMIZE_OFF
+
+Enable/disable optimizations which cause matching functions to scan the subject
+string for specific code unit values before attempting a match. For example, if
+it is known that an unanchored match must start with a specific value, the
+matching code searches the subject for that value, and fails immediately if it
+cannot find it, without actually running the main matching function. This means
+that a special item such as (*COMMIT) at the start of a pattern is not
+considered until after a suitable starting point for the match has been found.
+Also, when callouts or (*MARK) items are in use, these "start-up" optimizations
+can cause them to be skipped if the pattern is never actually used. The start-up
+optimizations are in effect a pre-scan of the subject that takes place before
+the pattern is run.
+
+
+Disabling start-up optimizations ensures that in cases where the result is "no
+match", the callouts do occur, and that items such as (*COMMIT) and (*MARK) are
+considered at every possible starting position in the subject string.
+
+
+Disabling start-up optimizations may change the outcome of a matching operation.
+Consider the pattern
+
+ (*COMMIT)ABC
+
+When this is compiled, PCRE2 records the fact that a match must start with the
+character "A". Suppose the subject string is "DEFABC". The start-up
+optimization scans along the subject, finds "A" and runs the first match
+attempt from there. The (*COMMIT) item means that the pattern must match the
+current starting position, which in this case, it does. However, if the same
+match is run without start-up optimizations, the initial scan along the subject
+string does not happen. The first match attempt is run starting from "D" and
+when this fails, (*COMMIT) prevents any further matches being tried, so the
+overall result is "no match".
+
+
+Another start-up optimization makes use of a minimum length for a matching
+subject, which is recorded when possible. Consider the pattern
+
+ (*MARK:1)B(*MARK:2)(X|Y)
+
+The minimum length for a match is two characters. If the subject is "XXBB", the
+"starting character" optimization skips "XX", then tries to match "BB", which
+is long enough. In the process, (*MARK:2) is encountered and remembered. When
+the match attempt fails, the next "B" is found, but there is only one character
+left, so there are no more attempts, and "no match" is returned with the "last
+mark seen" set to "2". Without start-up optimizations, however, matches are
+tried at every possible starting position, including at the end of the subject,
+where (*MARK:1) is encountered, but there is no "B", so the "last mark seen"
+that is returned is "1". In this case, the optimizations do not affect the
+overall match result, which is still "no match", but they do affect the
+auxiliary information that is returned.
+
+
+The match context
+
+
+A match context is required if you want to:
+
+ Set up a callout function
+ Set an offset limit for matching an unanchored pattern
+ Change the limit on the amount of heap used when matching
+ Change the backtracking match limit
+ Change the backtracking depth limit
+ Set custom memory management specifically for the match
+
+If none of these apply, just pass NULL as the context argument of
+pcre2_match(), pcre2_dfa_match(), or pcre2_jit_match().
+
+
+A match context is created, copied, and freed by the following functions:
+
+
+pcre2_match_context *pcre2_match_context_create(
+ pcre2_general_context *gcontext);
+
+
+pcre2_match_context *pcre2_match_context_copy(
+ pcre2_match_context *mcontext);
+
+
+void pcre2_match_context_free(pcre2_match_context *mcontext);
+
+
+A match context is created with default values for its parameters. These can
+be changed by calling the following functions, which return 0 on success, or
+PCRE2_ERROR_BADDATA if invalid data is detected.
+
+
+int pcre2_set_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_callout_block *, void *),
+ void *callout_data);
+
+
+This sets up a callout function for PCRE2 to call at specified points
+during a matching operation. Details are given in the
+pcre2callout
+documentation.
+
+
+int pcre2_set_substitute_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_substitute_callout_block *, void *),
+ void *callout_data);
+
+
+This sets up a callout function for PCRE2 to call after each substitution
+made by pcre2_substitute(). Details are given in the section entitled
+"Creating a new string with substitutions"
+below.
+
+
+int pcre2_set_substitute_case_callout(pcre2_match_context *mcontext,
+ PCRE2_SIZE (*callout_function)(PCRE2_SPTR, PCRE2_SIZE,
+ PCRE2_UCHAR *, PCRE2_SIZE,
+ int, void *),
+ void *callout_data);
+
+
+This sets up a callout function for PCRE2 to call when performing case
+transformations inside pcre2_substitute(). Details are given in the
+section entitled "Creating a new string with substitutions"
+below.
+
+
+int pcre2_set_offset_limit(pcre2_match_context *mcontext,
+ PCRE2_SIZE value);
+
+
+The offset_limit parameter limits how far an unanchored search can
+advance in the subject string. The default value is PCRE2_UNSET. The
+pcre2_match() and pcre2_dfa_match() functions return
+PCRE2_ERROR_NOMATCH if a match with a starting point before or at the given
+offset is not found. The pcre2_substitute() function makes no more
+substitutions.
+
+
+For example, if the pattern /abc/ is matched against "123abc" with an offset
+limit less than 3, the result is PCRE2_ERROR_NOMATCH. A match can never be
+found if the startoffset argument of pcre2_match(),
+pcre2_dfa_match(), or pcre2_substitute() is greater than the offset
+limit set in the match context.
+
+
+When using this facility, you must set the PCRE2_USE_OFFSET_LIMIT option when
+calling pcre2_compile() so that when JIT is in use, different code can be
+compiled. If a match is started with a non-default match limit when
+PCRE2_USE_OFFSET_LIMIT is not set, an error is generated.
+
+
+The offset limit facility can be used to track progress when searching large
+subject strings or to limit the extent of global substitutions. See also the
+PCRE2_FIRSTLINE option, which requires a match to start before or at the first
+newline that follows the start of matching in the subject. If this is set with
+an offset limit, a match must occur in the first line and also within the
+offset limit. In other words, whichever limit comes first is used.
+
+
+int pcre2_set_heap_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+
+The heap_limit parameter specifies, in units of kibibytes (1024 bytes),
+the maximum amount of heap memory that pcre2_match() may use to hold
+backtracking information when running an interpretive match. This limit also
+applies to pcre2_dfa_match(), which may use the heap when processing
+patterns with a lot of nested pattern recursion or lookarounds or atomic
+groups. This limit does not apply to matching with the JIT optimization, which
+has its own memory control arrangements (see the
+pcre2jit
+documentation for more details). If the limit is reached, the negative error
+code PCRE2_ERROR_HEAPLIMIT is returned. The default limit can be set when PCRE2
+is built; if it is not, the default is set very large and is essentially
+unlimited.
+
+
+A value for the heap limit may also be supplied by an item at the start of a
+pattern of the form
+
+ (*LIMIT_HEAP=ddd)
+
+where ddd is a decimal number. However, such a setting is ignored unless ddd is
+less than the limit set by the caller of pcre2_match() or, if no such
+limit is set, less than the default.
+
+
+The pcre2_match() function always needs some heap memory, so setting a
+value of zero guarantees a "heap limit exceeded" error. Details of how
+pcre2_match() uses the heap are given in the
+pcre2perform
+documentation.
+
+
+For pcre2_dfa_match(), a vector on the system stack is used when
+processing pattern recursions, lookarounds, or atomic groups, and only if this
+is not big enough is heap memory used. In this case, setting a value of zero
+disables the use of the heap.
+
+
+int pcre2_set_match_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+
+The match_limit parameter provides a means of preventing PCRE2 from using
+up too many computing resources when processing patterns that are not going to
+match, but which have a very large number of possibilities in their search
+trees. The classic example is a pattern that uses nested unlimited repeats.
+
+
+There is an internal counter in pcre2_match() that is incremented each
+time round its main matching loop. If this value reaches the match limit,
+pcre2_match() returns the negative value PCRE2_ERROR_MATCHLIMIT. This has
+the effect of limiting the amount of backtracking that can take place. For
+patterns that are not anchored, the count restarts from zero for each position
+in the subject string. This limit also applies to pcre2_dfa_match(),
+though the counting is done in a different way.
+
+
+When pcre2_match() is called with a pattern that was successfully
+processed by pcre2_jit_compile(), the way in which matching is executed
+is entirely different. However, there is still the possibility of runaway
+matching that goes on for a very long time, and so the match_limit value
+is also used in this case (but in a different way) to limit how long the
+matching can continue.
+
+
+The default value for the limit can be set when PCRE2 is built; the default is
+10 million, which handles all but the most extreme cases. A value for the match
+limit may also be supplied by an item at the start of a pattern of the form
+
+ (*LIMIT_MATCH=ddd)
+
+where ddd is a decimal number. However, such a setting is ignored unless ddd is
+less than the limit set by the caller of pcre2_match() or
+pcre2_dfa_match() or, if no such limit is set, less than the default.
+
+
+int pcre2_set_depth_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+
+This parameter limits the depth of nested backtracking in pcre2_match().
+Each time a nested backtracking point is passed, a new memory frame is used
+to remember the state of matching at that point. Thus, this parameter
+indirectly limits the amount of memory that is used in a match. However,
+because the size of each memory frame depends on the number of capturing
+parentheses, the actual memory limit varies from pattern to pattern. This limit
+was more useful in versions before 10.30, where function recursion was used for
+backtracking.
+
+
+The depth limit is not relevant, and is ignored, when matching is done using
+JIT compiled code. However, it is supported by pcre2_dfa_match(), which
+uses it to limit the depth of nested internal recursive function calls that
+implement atomic groups, lookaround assertions, and pattern recursions. This
+limits, indirectly, the amount of system stack that is used. It was more useful
+in versions before 10.32, when stack memory was used for local workspace
+vectors for recursive function calls. From version 10.32, only local variables
+are allocated on the stack and as each call uses only a few hundred bytes, even
+a small stack can support quite a lot of recursion.
+
+
+If the depth of internal recursive function calls is great enough, local
+workspace vectors are allocated on the heap from version 10.32 onwards, so the
+depth limit also indirectly limits the amount of heap memory that is used. A
+recursive pattern such as /(.(?2))((?1)|)/, when matched to a very long string
+using pcre2_dfa_match(), can use a great deal of memory. However, it is
+probably better to limit heap usage directly by calling
+pcre2_set_heap_limit().
+
+
+The default value for the depth limit can be set when PCRE2 is built; if it is
+not, the default is set to the same value as the default for the match limit.
+If the limit is exceeded, pcre2_match() or pcre2_dfa_match()
+returns PCRE2_ERROR_DEPTHLIMIT. A value for the depth limit may also be
+supplied by an item at the start of a pattern of the form
+
+ (*LIMIT_DEPTH=ddd)
+
+where ddd is a decimal number. However, such a setting is ignored unless ddd is
+less than the limit set by the caller of pcre2_match() or
+pcre2_dfa_match() or, if no such limit is set, less than the default.
+
+
+
+int pcre2_config(uint32_t what, void *where);
+
+
+The function pcre2_config() makes it possible for a PCRE2 client to find
+the value of certain configuration parameters and to discover which optional
+features have been compiled into the PCRE2 library. The
+pcre2build
+documentation has more details about these features.
+
+
+The first argument for pcre2_config() specifies which information is
+required. The second argument is a pointer to memory into which the information
+is placed. If NULL is passed, the function returns the amount of memory that is
+needed for the requested information. For calls that return numerical values,
+the value is in bytes; when requesting these values, where should point
+to appropriately aligned memory. For calls that return strings, the required
+length is given in code units, not counting the terminating zero.
+
+
+When requesting information, the returned value from pcre2_config() is
+non-negative on success, or the negative error code PCRE2_ERROR_BADOPTION if
+the value in the first argument is not recognized. The following information is
+available:
+
+ PCRE2_CONFIG_BSR
+
+The output is a uint32_t integer whose value indicates what character
+sequences the \R escape sequence matches by default. A value of
+PCRE2_BSR_UNICODE means that \R matches any Unicode line ending sequence; a
+value of PCRE2_BSR_ANYCRLF means that \R matches only CR, LF, or CRLF. The
+default can be overridden when a pattern is compiled.
+
+ PCRE2_CONFIG_COMPILED_WIDTHS
+
+The output is a uint32_t integer whose lower bits indicate which code unit
+widths were selected when PCRE2 was built. The 1-bit indicates 8-bit support,
+and the 2-bit and 4-bit indicate 16-bit and 32-bit support, respectively.
+
+ PCRE2_CONFIG_DEPTHLIMIT
+
+The output is a uint32_t integer that gives the default limit for the depth of
+nested backtracking in pcre2_match() or the depth of nested recursions,
+lookarounds, and atomic groups in pcre2_dfa_match(). Further details are
+given with pcre2_set_depth_limit() above.
+
+ PCRE2_CONFIG_EFFECTIVE_LINKSIZE
+
+The output is a uint32_t integer that contains the number of bytes the library
+uses for internal linkage in compiled regular expressions. Its value is derived
+from the value that was provided at build time and that is described below by
+PCRE2_CONFIG_LINKSIZE.
+
+ PCRE2_CONFIG_HEAPLIMIT
+
+The output is a uint32_t integer that gives, in kibibytes, the default limit
+for the amount of heap memory used by pcre2_match() or
+pcre2_dfa_match(). Further details are given with
+pcre2_set_heap_limit() above.
+
+ PCRE2_CONFIG_JIT
+
+The output is a uint32_t integer that is set to one if support for just-in-time
+compiling is included in the library; otherwise it is set to zero. Note that
+having the support in the library does not guarantee that JIT will be used for
+any given match, and neither does it guarantee that JIT will actually be able
+to function, because it may not be able to allocate executable memory in some
+environments. There is a special call to pcre2_jit_compile() that can be
+used to check this. See the
+pcre2jit
+documentation for more details.
+
+ PCRE2_CONFIG_JITTARGET
+
+The where argument should point to a code-unit-aligned buffer. All
+previous versions of PCRE2 have required no more than 128 code units of buffer
+capacity. However, this requirement is not guaranteed to be maintained, so
+applications should call pcre2_config() with where set to NULL to
+receive the required buffer size, then assert or allocate a suitably-size buffer
+for a second call to pcre2_config(). The buffer is filled with a string
+that contains the name of the architecture for which the JIT compiler is
+configured at build time, for example, a 64-bit ARM CPU that supports the
+Armv8.1 extension writes "ARM-64 (LSE) 64bit (little endian + unaligned)". If
+JIT support is not available, PCRE2_ERROR_BADOPTION is returned; otherwise the
+number of code units used is returned. This is the length of the string plus one
+unit for the terminating zero.
+
+ PCRE2_CONFIG_LINKSIZE
+
+The output is a uint32_t integer that contains the number of bytes the library
+was instructed to use for internal linkage in compiled regular expressions.
+When PCRE2 is configured, the value can be set to 2, 3, or 4, with the default
+being 2 for most libraries.
+
+
+The actual number of bytes used depends on the size of the code units that the
+library supports and can be higher. See PCRE2_CONFIG_EFFECTIVE_LINKSIZE above
+for details.
+
+
+The default value of 2 for the 8-bit and 16-bit libraries is sufficient for all
+but the most massive patterns, since it allows the size of the compiled pattern
+to be up to 65535 code units. Larger values allow larger regular expressions to
+be compiled by those two libraries, but at the expense of slower matching.
+
+ PCRE2_CONFIG_MATCHLIMIT
+
+The output is a uint32_t integer that gives the default match limit for
+pcre2_match(). Further details are given with
+pcre2_set_match_limit() above.
+
+ PCRE2_CONFIG_NEWLINE
+
+The output is a uint32_t integer whose value specifies the default character
+sequence that is recognized as meaning "newline". The values are:
+
+ PCRE2_NEWLINE_CR Carriage return (CR)
+ PCRE2_NEWLINE_LF Linefeed (LF)
+ PCRE2_NEWLINE_CRLF Carriage return, linefeed (CRLF)
+ PCRE2_NEWLINE_ANY Any Unicode line ending
+ PCRE2_NEWLINE_ANYCRLF Any of CR, LF, or CRLF
+ PCRE2_NEWLINE_NUL The NUL character (binary zero)
+
+The default should normally correspond to the standard sequence for your
+operating system.
+
+ PCRE2_CONFIG_NEVER_BACKSLASH_C
+
+The output is a uint32_t integer that is set to one if the use of \C was
+permanently disabled when PCRE2 was built; otherwise it is set to zero.
+
+ PCRE2_CONFIG_PARENSLIMIT
+
+The output is a uint32_t integer that gives the maximum depth of nesting
+of parentheses (of any kind) in a pattern. This limit is imposed to cap the
+amount of system stack used when a pattern is compiled. It is specified when
+PCRE2 is built; the default is 250. This limit does not take into account the
+stack that may already be used by the calling application. For finer control
+over compilation stack usage, see pcre2_set_compile_recursion_guard().
+
+ PCRE2_CONFIG_STACKRECURSE
+
+This parameter is obsolete and should not be used in new code. The output is a
+uint32_t integer that is always set to zero.
+
+ PCRE2_CONFIG_TABLES_LENGTH
+
+The output is a uint32_t integer that gives the length of PCRE2's character
+processing tables in bytes. For details of these tables see the
+section on locale support
+below.
+
+ PCRE2_CONFIG_UNICODE_VERSION
+
+The where argument should point to a code-unit-aligned buffer. All
+previous versions of PCRE2 have required no more than 24 code units of buffer
+capacity. However, applications should call pcre2_config() with
+where set to NULL to receive the required buffer size, then assert or
+allocate a suitably-size buffer for a second call to pcre2_config(). If
+PCRE2 has been compiled without Unicode support, the buffer is filled with the
+text "Unicode not supported". Otherwise, the Unicode version string (for
+example, "8.0.0") is written. The number of code units used is returned. This is
+the length of the string plus one unit for the terminating zero.
+
+ PCRE2_CONFIG_UNICODE
+
+The output is a uint32_t integer that is set to one if Unicode support is
+available; otherwise it is set to zero. Unicode support implies UTF support.
+
+ PCRE2_CONFIG_VERSION
+
+The where argument should point to a code-unit-aligned buffer. All
+previous versions of PCRE2 have required no more than 24 code units of buffer
+capacity. However, applications should call pcre2_config() with
+where set to NULL to receive the required buffer size, then assert or
+allocate a suitably-size buffer for a second call to pcre2_config(). The
+buffer is filled with the PCRE2 version string, zero-terminated. The number of
+code units used is returned. This is the length of the string plus one unit for
+the terminating zero.
+
+
+
+pcre2_code *pcre2_compile(PCRE2_SPTR pattern, PCRE2_SIZE length,
+ uint32_t options, int *errorcode, PCRE2_SIZE *erroroffset,
+ pcre2_compile_context *ccontext);
+
+
+void pcre2_code_free(pcre2_code *code);
+
+
+pcre2_code *pcre2_code_copy(const pcre2_code *code);
+
+
+pcre2_code *pcre2_code_copy_with_tables(const pcre2_code *code);
+
+
+The pcre2_compile() function compiles a pattern into an internal form.
+The pattern is defined by a pointer to a string of code units and a length in
+code units. If the pattern is zero-terminated, the length can be specified as
+PCRE2_ZERO_TERMINATED. A NULL pattern pointer with a length of zero is treated
+as an empty string (NULL with a non-zero length causes an error return). The
+function returns a pointer to a block of memory that contains the compiled
+pattern and related data, or NULL if an error occurred.
+
+
+If the compile context argument ccontext is NULL, memory for the compiled
+pattern is obtained by calling malloc(). Otherwise, it is obtained from
+the same memory function that was used for the compile context. The caller must
+free the memory by calling pcre2_code_free() when it is no longer needed.
+If pcre2_code_free() is called with a NULL argument, it returns
+immediately, without doing anything.
+
+
+The function pcre2_code_copy() makes a copy of the compiled code in new
+memory, using the same memory allocator as was used for the original. However,
+if the code has been processed by the JIT compiler (see
+below),
+the JIT information cannot be copied (because it is position-dependent).
+The new copy can initially be used only for non-JIT matching, though it can be
+passed to pcre2_jit_compile() if required. If pcre2_code_copy() is
+called with a NULL argument, it returns NULL.
+
+
+The pcre2_code_copy() function provides a way for individual threads in a
+multithreaded application to acquire a private copy of shared compiled code.
+However, it does not make a copy of the character tables used by the compiled
+pattern; the new pattern code points to the same tables as the original code.
+(See
+"Locale Support"
+below for details of these character tables.) In many applications the same
+tables are used throughout, so this behaviour is appropriate. Nevertheless,
+there are occasions when a copy of a compiled pattern and the relevant tables
+are needed. The pcre2_code_copy_with_tables() provides this facility.
+Copies of both the code and the tables are made, with the new code pointing to
+the new tables. The memory for the new tables is automatically freed when
+pcre2_code_free() is called for the new copy of the compiled code. If
+pcre2_code_copy_with_tables() is called with a NULL argument, it returns
+NULL.
+
+
+NOTE: When one of the matching functions is called, pointers to the compiled
+pattern and the subject string are set in the match data block so that they can
+be referenced by the substring extraction functions after a successful match.
+After running a match, you must not free a compiled pattern or a subject string
+until after all operations on the
+match data block
+have taken place, unless, in the case of the subject string, you have used the
+PCRE2_COPY_MATCHED_SUBJECT option, which is described in the section entitled
+"Option bits for pcre2_match()"
+below.
+
+
+The options argument for pcre2_compile() contains various bit
+settings that affect the compilation. It should be zero if none of them are
+required. The available options are described below. Some of them (in
+particular, those that are compatible with Perl, but some others as well) can
+also be set and unset from within the pattern (see the detailed description in
+the
+pcre2pattern
+documentation).
+
+
+For those options that can be different in different parts of the pattern, the
+contents of the options argument specifies their settings at the start of
+compilation. The PCRE2_ANCHORED, PCRE2_ENDANCHORED, and PCRE2_NO_UTF_CHECK
+options can be set at the time of matching as well as at compile time.
+
+
+Some additional options and less frequently required compile-time parameters
+(for example, the newline setting) can be provided in a compile context (as
+described
+above).
+
+
+If errorcode or erroroffset is NULL, pcre2_compile() returns
+NULL immediately. Otherwise, the variables to which these point are set to an
+error code and an offset (number of code units) within the pattern,
+respectively, when pcre2_compile() returns NULL because a compilation
+error has occurred.
+
+
+There are over 100 positive error codes that pcre2_compile() may return
+if it finds an error in the pattern. There are also some negative error codes
+that are used for invalid UTF strings when validity checking is in force. These
+are the same as given by pcre2_match() and pcre2_dfa_match(), and
+are described in the
+pcre2unicode
+documentation. There is no separate documentation for the positive error codes,
+because the textual error messages that are obtained by calling the
+pcre2_get_error_message() function (see "Obtaining a textual error
+message"
+below)
+should be self-explanatory. Macro names starting with PCRE2_ERROR_ are defined
+for both positive and negative error codes in pcre2.h. When compilation
+is successful errorcode is set to a value that returns the message "no
+error" if passed to pcre2_get_error_message().
+
+
+The value returned in erroroffset is an indication of where in the
+pattern an error occurred. When there is no error, zero is returned. A non-zero
+value is not necessarily the furthest point in the pattern that was read. For
+example, after the error "lookbehind assertion is not fixed length", the error
+offset points to the start of the failing assertion. For an invalid UTF-8 or
+UTF-16 string, the offset is that of the first code unit of the failing
+character.
+
+
+Some errors are not detected until the whole pattern has been scanned; in these
+cases, the offset passed back is the length of the pattern. Note that the
+offset is in code units, not characters, even in a UTF mode. It may sometimes
+point into the middle of a UTF-8 or UTF-16 character.
+
+
+This code fragment shows a typical straightforward call to
+pcre2_compile():
+
+ pcre2_code *re;
+ PCRE2_SIZE erroffset;
+ int errorcode;
+ re = pcre2_compile(
+ "^A.*Z", /* the pattern */
+ PCRE2_ZERO_TERMINATED, /* the pattern is zero-terminated */
+ 0, /* default options */
+ &errorcode, /* for error code */
+ &erroffset, /* for error offset */
+ NULL); /* no compile context */
+
+
+
+
+Main compile options
+
+
+The following names for option bits are defined in the pcre2.h header
+file:
+
+ PCRE2_ANCHORED
+
+If this bit is set, the pattern is forced to be "anchored", that is, it is
+constrained to match only at the first matching point in the string that is
+being searched (the "subject string"). This effect can also be achieved by
+appropriate constructs in the pattern itself, which is the only way to do it in
+Perl.
+
+ PCRE2_ALLOW_EMPTY_CLASS
+
+By default, for compatibility with Perl, a closing square bracket that
+immediately follows an opening one is treated as a data character for the
+class. When PCRE2_ALLOW_EMPTY_CLASS is set, it terminates the class, which
+therefore contains no characters and so can never match.
+
+ PCRE2_ALT_BSUX
+
+This option request alternative handling of three escape sequences, which
+makes PCRE2's behaviour more like ECMAscript (aka JavaScript). When it is set:
+
+
+(1) \U matches an upper case "U" character; by default \U causes a compile
+time error (Perl uses \U to upper case subsequent characters).
+
+
+(2) \u matches a lower case "u" character unless it is followed by four
+hexadecimal digits, in which case the hexadecimal number defines the code point
+to match. By default, \u causes a compile time error (Perl uses it to upper
+case the following character).
+
+
+(3) \x matches a lower case "x" character unless it is followed by two
+hexadecimal digits, in which case the hexadecimal number defines the code point
+to match. By default, as in Perl, a hexadecimal number is always expected after
+\x, but it may have one or two digits.
+
+
+ECMAscript 6 added additional functionality to \u. This can be accessed using
+the PCRE2_EXTRA_ALT_BSUX extra option (see "Extra compile options"
+below).
+Note that this alternative escape handling applies only to patterns. Neither of
+these options affects the processing of replacement strings passed to
+pcre2_substitute().
+
+ PCRE2_ALT_CIRCUMFLEX
+
+In multiline mode (when PCRE2_MULTILINE is set), the circumflex metacharacter
+matches at the start of the subject (unless PCRE2_NOTBOL is set), and also
+after any internal newline. However, it does not match after a newline at the
+end of the subject, for compatibility with Perl. If you want a multiline
+circumflex also to match after a terminating newline, you must set
+PCRE2_ALT_CIRCUMFLEX.
+
+ PCRE2_ALT_EXTENDED_CLASS
+
+Alters the parsing of character classes to follow the extended syntax
+described by Unicode UTS#18. The PCRE2_ALT_EXTENDED_CLASS option has no impact
+on the behaviour of the Perl-specific "(?[...])" syntax for extended classes,
+but instead enables the alternative syntax of extended class behaviour inside
+ordinary "[...]" character classes. See the
+pcre2pattern
+documentation for details of the character classes supported.
+
+ PCRE2_ALT_VERBNAMES
+
+By default, for compatibility with Perl, the name in any verb sequence such as
+(*MARK:NAME) is any sequence of characters that does not include a closing
+parenthesis. The name is not processed in any way, and it is not possible to
+include a closing parenthesis in the name. However, if the PCRE2_ALT_VERBNAMES
+option is set, normal backslash processing is applied to verb names and only an
+unescaped closing parenthesis terminates the name. A closing parenthesis can be
+included in a name either as \) or between \Q and \E. If the PCRE2_EXTENDED
+or PCRE2_EXTENDED_MORE option is set with PCRE2_ALT_VERBNAMES, unescaped
+white space in verb names is skipped and #-comments are recognized, exactly as
+in the rest of the pattern.
+
+ PCRE2_AUTO_CALLOUT
+
+If this bit is set, pcre2_compile() automatically inserts callout items,
+all with number 255, before each pattern item, except immediately before or
+after an explicit callout in the pattern. For discussion of the callout
+facility, see the
+pcre2callout
+documentation.
+
+ PCRE2_CASELESS
+
+If this bit is set, letters in the pattern match both upper and lower case
+letters in the subject. It is equivalent to Perl's /i option, and it can be
+changed within a pattern by a (?i) option setting. If either PCRE2_UTF or
+PCRE2_UCP is set, Unicode properties are used for all characters with more than
+one other case, and for all characters whose code points are greater than
+U+007F.
+
+
+Note that there are two ASCII characters, K and S, that, in addition to
+their lower case ASCII equivalents, are case-equivalent with U+212A (Kelvin
+sign) and U+017F (long S) respectively. If you do not want this case
+equivalence, you can suppress it by setting PCRE2_EXTRA_CASELESS_RESTRICT.
+
+
+One language family, Turkish and Azeri, has its own case-insensitivity rules,
+which can be selected by setting PCRE2_EXTRA_TURKISH_CASING. This alters the
+behaviour of the 'i', 'I', U+0130 (capital I with dot above), and U+0131
+(small dotless i) characters.
+
+
+For lower valued characters with only one other case, a lookup table is used
+for speed. When neither PCRE2_UTF nor PCRE2_UCP is set, a lookup table is used
+for all code points less than 256, and higher code points (available only in
+16-bit or 32-bit mode) are treated as not having another case.
+
+
+From release 10.45 PCRE2_CASELESS also affects what some of the letter-related
+Unicode property escapes (\p and \P) match. The properties Lu (upper case
+letter), Ll (lower case letter), and Lt (title case letter) are all treated as
+LC (cased letter) when PCRE2_CASELESS is set.
+
+ PCRE2_DOLLAR_ENDONLY
+
+If this bit is set, a dollar metacharacter in the pattern matches only at the
+end of the subject string. Without this option, a dollar also matches
+immediately before a newline at the end of the string (but not before any other
+newlines). The PCRE2_DOLLAR_ENDONLY option is ignored if PCRE2_MULTILINE is
+set. There is no equivalent to this option in Perl, and no way to set it within
+a pattern.
+
+ PCRE2_DOTALL
+
+If this bit is set, a dot metacharacter in the pattern matches any character,
+including one that indicates a newline. However, it only ever matches one
+character, even if newlines are coded as CRLF. Without this option, a dot does
+not match when the current position in the subject is at a newline. This option
+is equivalent to Perl's /s option, and it can be changed within a pattern by a
+(?s) option setting. A negative class such as [^a] always matches newline
+characters, and the \N escape sequence always matches a non-newline character,
+independent of the setting of PCRE2_DOTALL.
+
+ PCRE2_DUPNAMES
+
+If this bit is set, names used to identify capture groups need not be unique.
+This can be helpful for certain types of pattern when it is known that only one
+instance of the named group can ever be matched. There are more details of
+named capture groups below; see also the
+pcre2pattern
+documentation.
+
+ PCRE2_ENDANCHORED
+
+If this bit is set, the end of any pattern match must be right at the end of
+the string being searched (the "subject string"). If the pattern match
+succeeds by reaching (*ACCEPT), but does not reach the end of the subject, the
+match fails at the current starting point. For unanchored patterns, a new match
+is then tried at the next starting point. However, if the match succeeds by
+reaching the end of the pattern, but not the end of the subject, backtracking
+occurs and an alternative match may be found. Consider these two patterns:
+
+ .(*ACCEPT)|..
+ .|..
+
+If matched against "abc" with PCRE2_ENDANCHORED set, the first matches "c"
+whereas the second matches "bc". The effect of PCRE2_ENDANCHORED can also be
+achieved by appropriate constructs in the pattern itself, which is the only way
+to do it in Perl.
+
+
+For DFA matching with pcre2_dfa_match(), PCRE2_ENDANCHORED applies only
+to the first (that is, the longest) matched string. Other parallel matches,
+which are necessarily substrings of the first one, must obviously end before
+the end of the subject.
+
+ PCRE2_EXTENDED
+
+If this bit is set, most white space characters in the pattern are totally
+ignored except when escaped, inside a character class, or inside a \Q...\E
+sequence. However, white space is not allowed within sequences such as (?> that
+introduce various parenthesized groups, nor within numerical quantifiers such
+as {1,3}. Ignorable white space is permitted between an item and a following
+quantifier and between a quantifier and a following + that indicates
+possessiveness. PCRE2_EXTENDED is equivalent to Perl's /x option, and it can be
+changed within a pattern by a (?x) option setting.
+
+
+When PCRE2 is compiled without Unicode support, PCRE2_EXTENDED recognizes as
+white space only those characters with code points less than 256 that are
+flagged as white space in its low-character table. The table is normally
+created by
+pcre2_maketables(),
+which uses the isspace() function to identify space characters. In most
+ASCII environments, the relevant characters are those with code points 0x0009
+(tab), 0x000A (linefeed), 0x000B (vertical tab), 0x000C (formfeed), 0x000D
+(carriage return), and 0x0020 (space).
+
+
+When PCRE2 is compiled with Unicode support, in addition to these characters,
+five more Unicode "Pattern White Space" characters are recognized by
+PCRE2_EXTENDED. These are U+0085 (next line), U+200E (left-to-right mark),
+U+200F (right-to-left mark), U+2028 (line separator), and U+2029 (paragraph
+separator). This set of characters is the same as recognized by Perl's /x
+option. Note that the horizontal and vertical space characters that are matched
+by the \h and \v escapes in patterns are a much bigger set.
+
+
+As well as ignoring most white space, PCRE2_EXTENDED also causes characters
+between an unescaped # outside a character class and the next newline,
+inclusive, to be ignored, which makes it possible to include comments inside
+complicated patterns. Note that the end of this type of comment is a literal
+newline sequence in the pattern; escape sequences that happen to represent a
+newline do not count.
+
+
+Which characters are interpreted as newlines can be specified by a setting in
+the compile context that is passed to pcre2_compile() or by a special
+sequence at the start of the pattern, as described in the section entitled
+"Newline conventions"
+in the pcre2pattern documentation. A default is defined when PCRE2 is
+built.
+
+ PCRE2_EXTENDED_MORE
+
+This option has the effect of PCRE2_EXTENDED, but, in addition, unescaped space
+and horizontal tab characters are ignored inside a character class. Note: only
+these two characters are ignored, not the full set of pattern white space
+characters that are ignored outside a character class. PCRE2_EXTENDED_MORE is
+equivalent to Perl's /xx option, and it can be changed within a pattern by a
+(?xx) option setting.
+
+ PCRE2_FIRSTLINE
+
+If this option is set, the start of an unanchored pattern match must be before
+or at the first newline in the subject string following the start of matching,
+though the matched text may continue over the newline. If startoffset is
+non-zero, the limiting newline is not necessarily the first newline in the
+subject. For example, if the subject string is "abc\nxyz" (where \n
+represents a single-character newline) a pattern match for "yz" succeeds with
+PCRE2_FIRSTLINE if startoffset is greater than 3. See also
+PCRE2_USE_OFFSET_LIMIT, which provides a more general limiting facility. If
+PCRE2_FIRSTLINE is set with an offset limit, a match must occur in the first
+line and also within the offset limit. In other words, whichever limit comes
+first is used. This option has no effect for anchored patterns.
+
+ PCRE2_LITERAL
+
+If this option is set, all meta-characters in the pattern are disabled, and it
+is treated as a literal string. Matching literal strings with a regular
+expression engine is not the most efficient way of doing it. If you are doing a
+lot of literal matching and are worried about efficiency, you should consider
+using other approaches. The only other main options that are allowed with
+PCRE2_LITERAL are: PCRE2_ANCHORED, PCRE2_ENDANCHORED, PCRE2_AUTO_CALLOUT,
+PCRE2_CASELESS, PCRE2_FIRSTLINE, PCRE2_MATCH_INVALID_UTF,
+PCRE2_NO_START_OPTIMIZE, PCRE2_NO_UTF_CHECK, PCRE2_UTF, and
+PCRE2_USE_OFFSET_LIMIT. The extra options PCRE2_EXTRA_MATCH_LINE and
+PCRE2_EXTRA_MATCH_WORD are also supported. Any other options cause an error.
+
+ PCRE2_MATCH_INVALID_UTF
+
+This option forces PCRE2_UTF (see below) and also enables support for matching
+by pcre2_match() in subject strings that contain invalid UTF sequences.
+Note, however, that the 16-bit and 32-bit PCRE2 libraries process strings as
+sequences of uint16_t or uint32_t code points. They cannot find valid UTF
+sequences within an arbitrary string of bytes unless such sequences are
+suitably aligned. This facility is not supported for DFA matching. For details,
+see the
+pcre2unicode
+documentation.
+
+ PCRE2_MATCH_UNSET_BACKREF
+
+If this option is set, a backreference to an unset capture group matches an
+empty string (by default this causes the current matching alternative to fail).
+A pattern such as (\1)(a) succeeds when this option is set (assuming it can
+find an "a" in the subject), whereas it fails by default, for Perl
+compatibility. Setting this option makes PCRE2 behave more like ECMAscript (aka
+JavaScript).
+
+ PCRE2_MULTILINE
+
+By default, for the purposes of matching "start of line" and "end of line",
+PCRE2 treats the subject string as consisting of a single line of characters,
+even if it actually contains newlines. The "start of line" metacharacter (^)
+matches only at the start of the string, and the "end of line" metacharacter
+($) matches only at the end of the string, or before a terminating newline
+(except when PCRE2_DOLLAR_ENDONLY is set). Note, however, that unless
+PCRE2_DOTALL is set, the "any character" metacharacter (.) does not match at a
+newline. This behaviour (for ^, $, and dot) is the same as Perl.
+
+
+When PCRE2_MULTILINE it is set, the "start of line" and "end of line"
+constructs match immediately following or immediately before internal newlines
+in the subject string, respectively, as well as at the very start and end. This
+is equivalent to Perl's /m option, and it can be changed within a pattern by a
+(?m) option setting. Note that the "start of line" metacharacter does not match
+after a newline at the end of the subject, for compatibility with Perl.
+However, you can change this by setting the PCRE2_ALT_CIRCUMFLEX option. If
+there are no newlines in a subject string, or no occurrences of ^ or $ in a
+pattern, setting PCRE2_MULTILINE has no effect.
+
+ PCRE2_NEVER_BACKSLASH_C
+
+This option locks out the use of \C in the pattern that is being compiled.
+This escape can cause unpredictable behaviour in UTF-8 or UTF-16 modes, because
+it may leave the current matching point in the middle of a multi-code-unit
+character. This option may be useful in applications that process patterns from
+external sources. Note that there is also a build-time option that permanently
+locks out the use of \C.
+
+ PCRE2_NEVER_UCP
+
+This option locks out the use of Unicode properties for handling \B, \b, \D,
+\d, \S, \s, \W, \w, and some of the POSIX character classes, as described
+for the PCRE2_UCP option below. In particular, it prevents the creator of the
+pattern from enabling this facility by starting the pattern with (*UCP). This
+option may be useful in applications that process patterns from external
+sources. The option combination PCRE2_UCP and PCRE2_NEVER_UCP causes an error.
+
+ PCRE2_NEVER_UTF
+
+This option locks out interpretation of the pattern as UTF-8, UTF-16, or
+UTF-32, depending on which library is in use. In particular, it prevents the
+creator of the pattern from switching to UTF interpretation by starting the
+pattern with (*UTF). This option may be useful in applications that process
+patterns from external sources. The combination of PCRE2_UTF and
+PCRE2_NEVER_UTF causes an error.
+
+ PCRE2_NO_AUTO_CAPTURE
+
+If this option is set, it disables the use of numbered capturing parentheses in
+the pattern. Any opening parenthesis that is not followed by ? behaves as if it
+were followed by ?: but named parentheses can still be used for capturing (and
+they acquire numbers in the usual way). This is the same as Perl's /n option.
+Note that, when this option is set, references to capture groups
+(backreferences or recursion/subroutine calls) may only refer to named groups,
+though the reference can be by name or by number.
+
+ PCRE2_NO_AUTO_POSSESS
+
+If this (deprecated) option is set, it disables "auto-possessification", which
+is an optimization that, for example, turns a+b into a++b in order to avoid
+backtracks into a+ that can never be successful. However, if callouts are in
+use, auto-possessification means that some callouts are never taken. You can
+set this option if you want the matching functions to do a full unoptimized
+search and run all the callouts, but it is mainly provided for testing
+purposes.
+
+
+If a compile context is available, it is recommended to use
+pcre2_set_optimize() with the directive PCRE2_AUTO_POSSESS_OFF rather
+than the compile option PCRE2_NO_AUTO_POSSESS. Note that PCRE2_NO_AUTO_POSSESS
+takes precedence over the pcre2_set_optimize() optimization directives
+PCRE2_AUTO_POSSESS and PCRE2_AUTO_POSSESS_OFF.
+
+ PCRE2_NO_DOTSTAR_ANCHOR
+
+If this (deprecated) option is set, it disables an optimization that is applied
+when .* is the first significant item in a top-level branch of a pattern, and
+all the other branches also start with .* or with \A or \G or ^. The
+optimization is automatically disabled for .* if it is inside an atomic group
+or a capture group that is the subject of a backreference, or if the pattern
+contains (*PRUNE) or (*SKIP). When the optimization is not disabled, such a
+pattern is automatically anchored if PCRE2_DOTALL is set for all the .* items
+and PCRE2_MULTILINE is not set for any ^ items. Otherwise, the fact that any
+match must start either at the start of the subject or following a newline is
+remembered. Like other optimizations, this can cause callouts to be skipped.
+(If a compile context is available, it is recommended to use
+pcre2_set_optimize() with the directive PCRE2_DOTSTAR_ANCHOR_OFF
+instead.)
+
+ PCRE2_NO_START_OPTIMIZE
+
+This is an option whose main effect is at matching time. It does not change
+what pcre2_compile() generates, but it does affect the output of the JIT
+compiler. Setting this option is equivalent to calling
+pcre2_set_optimize() with the directive parameter set to
+PCRE2_START_OPTIMIZE_OFF.
+
+
+There are a number of optimizations that may occur at the start of a match, in
+order to speed up the process. For example, if it is known that an unanchored
+match must start with a specific code unit value, the matching code searches
+the subject for that value, and fails immediately if it cannot find it, without
+actually running the main matching function. The start-up optimizations are
+in effect a pre-scan of the subject that takes place before the pattern is run.
+
+
+Disabling the start-up optimizations may cause performance to suffer. However,
+this may be desirable for patterns which contain callouts or items such as
+(*COMMIT) and (*MARK). See the above description of PCRE2_START_OPTIMIZE_OFF
+for further details.
+
+ PCRE2_NO_UTF_CHECK
+
+When PCRE2_UTF is set, the validity of the pattern as a UTF string is
+automatically checked. There are discussions about the validity of
+UTF-8 strings,
+UTF-16 strings,
+and
+UTF-32 strings
+in the
+pcre2unicode
+document. If an invalid UTF sequence is found, pcre2_compile() returns a
+negative error code.
+
+
+If you know that your pattern is a valid UTF string, and you want to skip this
+check for performance reasons, you can set the PCRE2_NO_UTF_CHECK option. When
+it is set, the effect of passing an invalid UTF string as a pattern is
+undefined. It may cause your program to crash or loop.
+
+
+Note that this option can also be passed to pcre2_match() and
+pcre2_dfa_match(), to suppress UTF validity checking of the subject
+string.
+
+
+Note also that setting PCRE2_NO_UTF_CHECK at compile time does not disable the
+error that is given if an escape sequence for an invalid Unicode code point is
+encountered in the pattern. In particular, the so-called "surrogate" code
+points (0xd800 to 0xdfff) are invalid. If you want to allow escape sequences
+such as \x{d800} you can set the PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES extra
+option, as described in the section entitled "Extra compile options"
+below.
+However, this is possible only in UTF-8 and UTF-32 modes, because these values
+are not representable in UTF-16.
+
+ PCRE2_UCP
+
+This option has two effects. Firstly, it change the way PCRE2 processes \B,
+\b, \D, \d, \S, \s, \W, \w, and some of the POSIX character classes. By
+default, only ASCII characters are recognized, but if PCRE2_UCP is set, Unicode
+properties are used to classify characters. There are some PCRE2_EXTRA
+options (see below) that add finer control to this behaviour. More details are
+given in the section on
+generic character types
+in the
+pcre2pattern
+page.
+
+
+The second effect of PCRE2_UCP is to force the use of Unicode properties for
+upper/lower casing operations, even when PCRE2_UTF is not set. This makes it
+possible to process strings in the 16-bit UCS-2 code. This option is available
+only if PCRE2 has been compiled with Unicode support (which is the default).
+
+
+The PCRE2_EXTRA_CASELESS_RESTRICT option (see above) restricts caseless
+matching such that ASCII characters match only ASCII characters and non-ASCII
+characters match only non-ASCII characters. The PCRE2_EXTRA_TURKISH_CASING
+option (see above) alters the matching of the 'i' characters to follow their
+behaviour in Turkish and Azeri languages. For further details on
+PCRE2_EXTRA_CASELESS_RESTRICT and PCRE2_EXTRA_TURKISH_CASING, see the
+pcre2unicode
+page.
+
+ PCRE2_UNGREEDY
+
+This option inverts the "greediness" of the quantifiers so that they are not
+greedy by default, but become greedy if followed by "?". It is not compatible
+with Perl. It can also be set by a (?U) option setting within the pattern.
+
+ PCRE2_USE_OFFSET_LIMIT
+
+This option must be set for pcre2_compile() if
+pcre2_set_offset_limit() is going to be used to set a non-default offset
+limit in a match context for matches that use this pattern. An error is
+generated if an offset limit is set without this option. For more details, see
+the description of pcre2_set_offset_limit() in the
+section
+that describes match contexts. See also the PCRE2_FIRSTLINE
+option above.
+
+ PCRE2_UTF
+
+This option causes PCRE2 to regard both the pattern and the subject strings
+that are subsequently processed as strings of UTF characters instead of
+single-code-unit strings. It is available when PCRE2 is built to include
+Unicode support (which is the default). If Unicode support is not available,
+the use of this option provokes an error. Details of how PCRE2_UTF changes the
+behaviour of PCRE2 are given in the
+pcre2unicode
+page. In particular, note that it changes the way PCRE2_CASELESS works.
+
+
+Extra compile options
+
+
+The option bits that can be set in a compile context by calling the
+pcre2_set_compile_extra_options() function are as follows:
+
+ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK
+
+Since release 10.38 PCRE2 has forbidden the use of \K within lookaround
+assertions, following Perl's lead. This option is provided to re-enable the
+previous behaviour (act in positive lookarounds, ignore in negative ones) in
+case anybody is relying on it.
+
+ PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES
+
+This option applies when compiling a pattern in UTF-8 or UTF-32 mode. It is
+forbidden in UTF-16 mode, and ignored in non-UTF modes. Unicode "surrogate"
+code points in the range 0xd800 to 0xdfff are used in pairs in UTF-16 to encode
+code points with values in the range 0x10000 to 0x10ffff. The surrogates cannot
+therefore be represented in UTF-16. They can be represented in UTF-8 and
+UTF-32, but are defined as invalid code points, and cause errors if encountered
+in a UTF-8 or UTF-32 string that is being checked for validity by PCRE2.
+
+
+These values also cause errors if encountered in escape sequences such as
+\x{d912} within a pattern. However, it seems that some applications, when
+using PCRE2 to check for unwanted characters in UTF-8 strings, explicitly test
+for the surrogates using escape sequences. The PCRE2_NO_UTF_CHECK option does
+not disable the error that occurs, because it applies only to the testing of
+input strings for UTF validity.
+
+
+If the extra option PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is set, surrogate code
+point values in UTF-8 and UTF-32 patterns no longer provoke errors and are
+incorporated in the compiled pattern. However, they can only match subject
+characters if the matching function is called with PCRE2_NO_UTF_CHECK set.
+
+ PCRE2_EXTRA_ALT_BSUX
+
+The original option PCRE2_ALT_BSUX causes PCRE2 to process \U, \u, and \x in
+the way that ECMAscript (aka JavaScript) does. Additional functionality was
+defined by ECMAscript 6; setting PCRE2_EXTRA_ALT_BSUX has the effect of
+PCRE2_ALT_BSUX, but in addition it recognizes \u{hhh..} as a hexadecimal
+character code, where hhh.. is any number of hexadecimal digits.
+
+ PCRE2_EXTRA_ASCII_BSD
+
+This option forces \d to match only ASCII digits, even when PCRE2_UCP is set.
+It can be changed within a pattern by means of the (?aD) option setting.
+
+ PCRE2_EXTRA_ASCII_BSS
+
+This option forces \s to match only ASCII space characters, even when
+PCRE2_UCP is set. It can be changed within a pattern by means of the (?aS)
+option setting.
+
+ PCRE2_EXTRA_ASCII_BSW
+
+This option forces \w to match only ASCII word characters, even when PCRE2_UCP
+is set. It can be changed within a pattern by means of the (?aW) option
+setting.
+
+ PCRE2_EXTRA_ASCII_DIGIT
+
+This option forces the POSIX character classes [:digit:] and [:xdigit:] to
+match only ASCII digits, even when PCRE2_UCP is set. It can be changed within
+a pattern by means of the (?aT) option setting.
+
+ PCRE2_EXTRA_ASCII_POSIX
+
+This option forces all the POSIX character classes, including [:digit:] and
+[:xdigit:], to match only ASCII characters, even when PCRE2_UCP is set. It can
+be changed within a pattern by means of the (?aP) option setting, but note that
+this also sets PCRE2_EXTRA_ASCII_DIGIT in order to ensure that (?-aP) unsets
+all ASCII restrictions for POSIX classes.
+
+ PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL
+
+This is a dangerous option. Use with care. By default, an unrecognized escape
+such as \j or a malformed one such as \x{2z} causes a compile-time error when
+detected by pcre2_compile(). Perl is somewhat inconsistent in handling
+such items: for example, \j is treated as a literal "j", and non-hexadecimal
+digits in \x{} are just ignored, though warnings are given in both cases if
+Perl's warning switch is enabled. However, a malformed octal number after \o{
+always causes an error in Perl.
+
+
+If the PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL extra option is passed to
+pcre2_compile(), all unrecognized or malformed escape sequences are
+treated as single-character escapes. For example, \j is a literal "j" and
+\x{2z} is treated as the literal string "x{2z}". Setting this option means
+that typos in patterns may go undetected and have unexpected results. Also note
+that a sequence such as [\N{] is interpreted as a malformed attempt at
+[\N{...}] and so is treated as [N{] whereas [\N] gives an error because an
+unqualified \N is a valid escape sequence but is not supported in a character
+class. To reiterate: this is a dangerous option. Use with great care.
+
+ PCRE2_EXTRA_CASELESS_RESTRICT
+
+When either PCRE2_UCP or PCRE2_UTF is set, caseless matching follows Unicode
+rules, which allow for more than two cases per character. There are two
+case-equivalent character sets that contain both ASCII and non-ASCII
+characters. The ASCII letter S is case-equivalent to U+017f (long S) and the
+ASCII letter K is case-equivalent to U+212a (Kelvin sign). This option disables
+recognition of case-equivalences that cross the ASCII/non-ASCII boundary. In a
+caseless match, both characters must either be ASCII or non-ASCII. The option
+can be changed within a pattern by the (*CASELESS_RESTRICT) or (?r) option
+settings.
+
+ PCRE2_EXTRA_ESCAPED_CR_IS_LF
+
+There are some legacy applications where the escape sequence \r in a pattern
+is expected to match a newline. If this option is set, \r in a pattern is
+converted to \n so that it matches a LF (linefeed) instead of a CR (carriage
+return) character. The option does not affect a literal CR in the pattern, nor
+does it affect CR specified as an explicit code point such as \x{0D}.
+
+ PCRE2_EXTRA_MATCH_LINE
+
+This option is provided for use by the -x option of pcre2grep. It
+causes the pattern only to match complete lines. This is achieved by
+automatically inserting the code for "^(?:" at the start of the compiled
+pattern and ")$" at the end. Thus, when PCRE2_MULTILINE is set, the matched
+line may be in the middle of the subject string. This option can be used with
+PCRE2_LITERAL.
+
+ PCRE2_EXTRA_MATCH_WORD
+
+This option is provided for use by the -w option of pcre2grep. It
+causes the pattern only to match strings that have a word boundary at the start
+and the end. This is achieved by automatically inserting the code for "\b(?:"
+at the start of the compiled pattern and ")\b" at the end. The option may be
+used with PCRE2_LITERAL. However, it is ignored if PCRE2_EXTRA_MATCH_LINE is
+also set.
+
+ PCRE2_EXTRA_NO_BS0
+
+If this option is set (note that its final character is the digit 0) it locks
+out the use of the sequence \0 unless at least one more octal digit follows.
+
+ PCRE2_EXTRA_PYTHON_OCTAL
+
+If this option is set, PCRE2 follows Python's rules for interpreting octal
+escape sequences. The rules for handling sequences such as \14, which could
+be an octal number or a back reference are different. Details are given in the
+pcre2pattern
+documentation.
+
+ PCRE2_EXTRA_NEVER_CALLOUT
+
+If this option is set, PCRE2 treats callouts in the pattern as a syntax error,
+returning PCRE2_ERROR_CALLOUT_CALLER_DISABLED. This is useful if the application
+knows that a callout will not be provided to pcre2_match(), so that
+callouts in the pattern are not silently ignored.
+
+ PCRE2_EXTRA_TURKISH_CASING
+
+This option alters case-equivalence of the 'i' letters to follow the
+alphabet used by Turkish and Azeri languages. The option can be changed within
+a pattern by the (*TURKISH_CASING) start-of-pattern setting. Either the UTF or
+UCP options must be set. In the 8-bit library, UTF must be set. This option
+cannot be combined with PCRE2_EXTRA_CASELESS_RESTRICT.
+
+
+
+int pcre2_jit_compile(pcre2_code *code, uint32_t options);
+
+
+int pcre2_jit_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext);
+
+
+void pcre2_jit_free_unused_memory(pcre2_general_context *gcontext);
+
+
+pcre2_jit_stack *pcre2_jit_stack_create(size_t startsize,
+ size_t maxsize, pcre2_general_context *gcontext);
+
+
+void pcre2_jit_stack_assign(pcre2_match_context *mcontext,
+ pcre2_jit_callback callback_function, void *callback_data);
+
+
+void pcre2_jit_stack_free(pcre2_jit_stack *jit_stack);
+
+
+These functions provide support for JIT compilation, which, if the just-in-time
+compiler is available, further processes a compiled pattern into machine code
+that executes much faster than the pcre2_match() interpretive matching
+function. Full details are given in the
+pcre2jit
+documentation.
+
+
+JIT compilation is a heavyweight optimization. It can take some time for
+patterns to be analyzed, and for one-off matches and simple patterns the
+benefit of faster execution might be offset by a much slower compilation time.
+Most (but not all) patterns can be optimized by the JIT compiler.
+
+
+
+const uint8_t *pcre2_maketables(pcre2_general_context *gcontext);
+
+
+void pcre2_maketables_free(pcre2_general_context *gcontext,
+ const uint8_t *tables);
+
+
+PCRE2 handles caseless matching, and determines whether characters are letters,
+digits, or whatever, by reference to a set of tables, indexed by character code
+point. However, this applies only to characters whose code points are less than
+256. By default, higher-valued code points never match escapes such as \w or
+\d.
+
+
+When PCRE2 is built with Unicode support (the default), certain Unicode
+character properties can be tested with \p and \P, or, alternatively, the
+PCRE2_UCP option can be set when a pattern is compiled; this causes \w and
+friends to use Unicode property support instead of the built-in tables.
+PCRE2_UCP also causes upper/lower casing operations on characters with code
+points greater than 127 to use Unicode properties. These effects apply even
+when PCRE2_UTF is not set. There are, however, some PCRE2_EXTRA options (see
+above) that can be used to modify or suppress them.
+
+
+The use of locales with Unicode is discouraged. If you are handling characters
+with code points greater than 127, you should either use Unicode support, or
+use locales, but not try to mix the two.
+
+
+PCRE2 contains a built-in set of character tables that are used by default.
+These are sufficient for many applications. Normally, the internal tables
+recognize only ASCII characters. However, when PCRE2 is built, it is possible
+to cause the internal tables to be rebuilt in the default "C" locale of the
+local system, which may cause them to be different.
+
+
+The built-in tables can be overridden by tables supplied by the application
+that calls PCRE2. These may be created in a different locale from the default.
+As more and more applications change to using Unicode, the need for this locale
+support is expected to die away.
+
+
+External tables are built by calling the pcre2_maketables() function, in
+the relevant locale. The only argument to this function is a general context,
+which can be used to pass a custom memory allocator. If the argument is NULL,
+the system malloc() is used. The result can be passed to
+pcre2_compile() as often as necessary, by creating a compile context and
+calling pcre2_set_character_tables() to set the tables pointer therein.
+
+
+For example, to build and use tables that are appropriate for the French locale
+(where accented characters with values greater than 127 are treated as
+letters), the following code could be used:
+
+ setlocale(LC_CTYPE, "fr_FR");
+ tables = pcre2_maketables(NULL);
+ ccontext = pcre2_compile_context_create(NULL);
+ pcre2_set_character_tables(ccontext, tables);
+ re = pcre2_compile(..., ccontext);
+
+The locale name "fr_FR" is used on Linux and other Unix-like systems; if you
+are using Windows, the name for the French locale is "french".
+
+
+The pointer that is passed (via the compile context) to pcre2_compile()
+is saved with the compiled pattern, and the same tables are used by the
+matching functions. Thus, for any single pattern, compilation and matching both
+happen in the same locale, but different patterns can be processed in different
+locales.
+
+
+It is the caller's responsibility to ensure that the memory containing the
+tables remains available while they are still in use. When they are no longer
+needed, you can discard them using pcre2_maketables_free(), which should
+pass as its first parameter the same global context that was used to create the
+tables.
+
+
+Saving locale tables
+
+
+The tables described above are just a sequence of binary bytes, which makes
+them independent of hardware characteristics such as endianness or whether the
+processor is 32-bit or 64-bit. A copy of the result of pcre2_maketables()
+can therefore be saved in a file or elsewhere and re-used later, even in a
+different program or on another computer. The size of the tables (number of
+bytes) must be obtained by calling pcre2_config() with the
+PCRE2_CONFIG_TABLES_LENGTH option because pcre2_maketables() does not
+return this value. Note that the pcre2_dftables program, which is part of
+the PCRE2 build system, can be used stand-alone to create a file that contains
+a set of binary tables. See the
+pcre2build
+documentation for details.
+
+
+
+int pcre2_pattern_info(const pcre2 *code, uint32_t what, void *where);
+
+
+The pcre2_pattern_info() function returns general information about a
+compiled pattern. For information about callouts, see the
+next section.
+The first argument for pcre2_pattern_info() is a pointer to the compiled
+pattern. The second argument specifies which piece of information is required,
+and the third argument is a pointer to a variable to receive the data. If the
+third argument is NULL, the first argument is ignored, and the function returns
+the size in bytes of the variable that is required for the information
+requested. Otherwise, the yield of the function is zero for success, or one of
+the following negative numbers:
+
+ PCRE2_ERROR_NULL the argument code was NULL
+ PCRE2_ERROR_BADMAGIC the "magic number" was not found
+ PCRE2_ERROR_BADOPTION the value of what was invalid
+ PCRE2_ERROR_UNSET the requested field is not set
+
+The "magic number" is placed at the start of each compiled pattern as a simple
+check against passing an arbitrary memory pointer. Here is a typical call of
+pcre2_pattern_info(), to obtain the length of the compiled pattern:
+
+ int rc;
+ size_t length;
+ rc = pcre2_pattern_info(
+ re, /* result of pcre2_compile() */
+ PCRE2_INFO_SIZE, /* what is required */
+ &length); /* where to put the data */
+
+The possible values for the second argument are defined in pcre2.h, and
+are as follows:
+
+ PCRE2_INFO_ALLOPTIONS
+ PCRE2_INFO_ARGOPTIONS
+ PCRE2_INFO_EXTRAOPTIONS
+
+Return copies of the pattern's options. The third argument should point to a
+uint32_t variable. PCRE2_INFO_ARGOPTIONS returns exactly the options that
+were passed to pcre2_compile(), whereas PCRE2_INFO_ALLOPTIONS returns
+the compile options as modified by any top-level (*XXX) option settings such as
+(*UTF) at the start of the pattern itself. PCRE2_INFO_EXTRAOPTIONS returns the
+extra options that were set in the compile context by calling the
+pcre2_set_compile_extra_options() function.
+
+
+For example, if the pattern /(*UTF)abc/ is compiled with the PCRE2_EXTENDED
+option, the result for PCRE2_INFO_ALLOPTIONS is PCRE2_EXTENDED and PCRE2_UTF.
+Option settings such as (?i) that can change within a pattern do not affect the
+result of PCRE2_INFO_ALLOPTIONS, even if they appear right at the start of the
+pattern. (This was different in some earlier releases.)
+
+
+A pattern compiled without PCRE2_ANCHORED is automatically anchored by PCRE2 if
+the first significant item in every top-level branch is one of the following:
+
+ ^ unless PCRE2_MULTILINE is set
+ \A always
+ \G always
+ .* sometimes - see below
+
+When .* is the first significant item, anchoring is possible only when all the
+following are true:
+
+ .* is not in an atomic group
+ .* is not in a capture group that is the subject of a backreference
+ PCRE2_DOTALL is in force for .*
+ Neither (*PRUNE) nor (*SKIP) appears in the pattern
+ PCRE2_NO_DOTSTAR_ANCHOR is not set
+ Dotstar anchoring has not been disabled with PCRE2_DOTSTAR_ANCHOR_OFF
+
+For patterns that are auto-anchored, the PCRE2_ANCHORED bit is set in the
+options returned for PCRE2_INFO_ALLOPTIONS.
+
+ PCRE2_INFO_BACKREFMAX
+
+Return the number of the highest backreference in the pattern. The third
+argument should point to a uint32_t variable. Named capture groups
+acquire numbers as well as names, and these count towards the highest
+backreference. Backreferences such as \4 or \g{12} match the captured
+characters of the given group, but in addition, the check that a capture
+group is set in a conditional group such as (?(3)a|b) is also a backreference.
+Zero is returned if there are no backreferences.
+
+ PCRE2_INFO_BSR
+
+The output is a uint32_t integer whose value indicates what character sequences
+the \R escape sequence matches. A value of PCRE2_BSR_UNICODE means that \R
+matches any Unicode line ending sequence; a value of PCRE2_BSR_ANYCRLF means
+that \R matches only CR, LF, or CRLF.
+
+ PCRE2_INFO_CAPTURECOUNT
+
+Return the highest capture group number in the pattern. In patterns where (?|
+is not used, this is also the total number of capture groups. The third
+argument should point to a uint32_t variable.
+
+ PCRE2_INFO_DEPTHLIMIT
+
+If the pattern set a backtracking depth limit by including an item of the form
+(*LIMIT_DEPTH=nnnn) at the start, the value is returned. The third argument
+should point to a uint32_t integer. If no such value has been set, the call to
+pcre2_pattern_info() returns the error PCRE2_ERROR_UNSET. Note that this
+limit will only be used during matching if it is less than the limit set or
+defaulted by the caller of the match function.
+
+ PCRE2_INFO_FIRSTBITMAP
+
+In the absence of a single first code unit for a non-anchored pattern,
+pcre2_compile() may construct a 256-bit table that defines a fixed set of
+values for the first code unit in any match. For example, a pattern that starts
+with [abc] results in a table with three bits set. When code unit values
+greater than 255 are supported, the flag bit for 255 means "any code unit of
+value 255 or above". If such a table was constructed, a pointer to it is
+returned. Otherwise NULL is returned. The third argument should point to a
+const uint8_t * variable.
+
+ PCRE2_INFO_FIRSTCODETYPE
+
+Return information about the first code unit of any matched string, for a
+non-anchored pattern. The third argument should point to a uint32_t
+variable. If there is a fixed first value, for example, the letter "c" from a
+pattern such as (cat|cow|coyote), 1 is returned, and the value can be retrieved
+using PCRE2_INFO_FIRSTCODEUNIT. If there is no fixed first value, but it is
+known that a match can occur only at the start of the subject or following a
+newline in the subject, 2 is returned. Otherwise, and for anchored patterns, 0
+is returned.
+
+ PCRE2_INFO_FIRSTCODEUNIT
+
+Return the value of the first code unit of any matched string for a pattern
+where PCRE2_INFO_FIRSTCODETYPE returns 1; otherwise return 0. The third
+argument should point to a uint32_t variable. In the 8-bit library, the
+value is always less than 256. In the 16-bit library the value can be up to
+0xffff. In the 32-bit library in UTF-32 mode the value can be up to 0x10ffff,
+and up to 0xffffffff when not using UTF-32 mode.
+
+ PCRE2_INFO_FRAMESIZE
+
+Return the size (in bytes) of the data frames that are used to remember
+backtracking positions when the pattern is processed by pcre2_match()
+without the use of JIT. The third argument should point to a size_t
+variable. The frame size depends on the number of capturing parentheses in the
+pattern. Each additional capture group adds two PCRE2_SIZE variables.
+
+ PCRE2_INFO_HASBACKSLASHC
+
+Return 1 if the pattern contains any instances of \C, otherwise 0. The third
+argument should point to a uint32_t variable.
+
+ PCRE2_INFO_HASCRORLF
+
+Return 1 if the pattern contains any explicit matches for CR or LF characters,
+otherwise 0. The third argument should point to a uint32_t variable. An
+explicit match is either a literal CR or LF character, or \r or \n or one of
+the equivalent hexadecimal or octal escape sequences.
+
+ PCRE2_INFO_HEAPLIMIT
+
+If the pattern set a heap memory limit by including an item of the form
+(*LIMIT_HEAP=nnnn) at the start, the value is returned. The third argument
+should point to a uint32_t integer. If no such value has been set, the call to
+pcre2_pattern_info() returns the error PCRE2_ERROR_UNSET. Note that this
+limit will only be used during matching if it is less than the limit set or
+defaulted by the caller of the match function.
+
+ PCRE2_INFO_JCHANGED
+
+Return 1 if the (?J) or (?-J) option setting is used in the pattern, otherwise
+0. The third argument should point to a uint32_t variable. (?J) and
+(?-J) set and unset the local PCRE2_DUPNAMES option, respectively.
+
+ PCRE2_INFO_JITSIZE
+
+If the compiled pattern was successfully processed by
+pcre2_jit_compile(), return the size of the JIT compiled code, otherwise
+return zero. The third argument should point to a size_t variable.
+
+ PCRE2_INFO_LASTCODETYPE
+
+Returns 1 if there is a rightmost literal code unit that must exist in any
+matched string, other than at its start. The third argument should point to a
+uint32_t variable. If there is no such value, 0 is returned. When 1 is
+returned, the code unit value itself can be retrieved using
+PCRE2_INFO_LASTCODEUNIT. For anchored patterns, a last literal value is
+recorded only if it follows something of variable length. For example, for the
+pattern /^a\d+z\d+/ the returned value is 1 (with "z" returned from
+PCRE2_INFO_LASTCODEUNIT), but for /^a\dz\d/ the returned value is 0.
+
+ PCRE2_INFO_LASTCODEUNIT
+
+Return the value of the rightmost literal code unit that must exist in any
+matched string, other than at its start, for a pattern where
+PCRE2_INFO_LASTCODETYPE returns 1. Otherwise, return 0. The third argument
+should point to a uint32_t variable.
+
+ PCRE2_INFO_MATCHEMPTY
+
+Return 1 if the pattern might match an empty string, otherwise 0. The third
+argument should point to a uint32_t variable. When a pattern contains
+recursive subroutine calls it is not always possible to determine whether or
+not it can match an empty string. PCRE2 takes a cautious approach and returns 1
+in such cases.
+
+ PCRE2_INFO_MATCHLIMIT
+
+If the pattern set a match limit by including an item of the form
+(*LIMIT_MATCH=nnnn) at the start, the value is returned. The third argument
+should point to a uint32_t integer. If no such value has been set, the call to
+pcre2_pattern_info() returns the error PCRE2_ERROR_UNSET. Note that this
+limit will only be used during matching if it is less than the limit set or
+defaulted by the caller of the match function.
+
+ PCRE2_INFO_MAXLOOKBEHIND
+
+A lookbehind assertion moves back a certain number of characters (not code
+units) when it starts to process each of its branches. This request returns the
+largest of these backward moves. The third argument should point to a uint32_t
+integer. The simple assertions \b and \B require a one-character lookbehind
+and cause PCRE2_INFO_MAXLOOKBEHIND to return 1 in the absence of anything
+longer. \A also registers a one-character lookbehind, though it does not
+actually inspect the previous character.
+
+
+Note that this information is useful for multi-segment matching only
+if the pattern contains no nested lookbehinds. For example, the pattern
+(?<=a(?<=ba)c) returns a maximum lookbehind of 2, but when it is processed, the
+first lookbehind moves back by two characters, matches one character, then the
+nested lookbehind also moves back by two characters. This puts the matching
+point three characters earlier than it was at the start.
+PCRE2_INFO_MAXLOOKBEHIND is really only useful as a debugging tool. See the
+pcre2partial
+documentation for a discussion of multi-segment matching.
+
+ PCRE2_INFO_MINLENGTH
+
+If a minimum length for matching subject strings was computed, its value is
+returned. Otherwise the returned value is 0. This value is not computed when
+PCRE2_NO_START_OPTIMIZE is set. The value is a number of characters, which in
+UTF mode may be different from the number of code units. The third argument
+should point to a uint32_t variable. The value is a lower bound to the
+length of any matching string. There may not be any strings of that length that
+do actually match, but every string that does match is at least that long.
+
+ PCRE2_INFO_NAMECOUNT
+ PCRE2_INFO_NAMEENTRYSIZE
+ PCRE2_INFO_NAMETABLE
+
+PCRE2 supports the use of named as well as numbered capturing parentheses. The
+names are just an additional way of identifying the parentheses, which still
+acquire numbers. Several convenience functions such as
+pcre2_substring_get_byname() are provided for extracting captured
+substrings by name. It is also possible to extract the data directly, by first
+converting the name to a number in order to access the correct pointers in the
+output vector (described with pcre2_match() below). To do the conversion,
+you need to use the name-to-number map, which is described by these three
+values.
+
+
+The map consists of a number of fixed-size entries. PCRE2_INFO_NAMECOUNT gives
+the number of entries, and PCRE2_INFO_NAMEENTRYSIZE gives the size of each
+entry in code units; both of these return a uint32_t value. The entry
+size depends on the length of the longest name.
+
+
+PCRE2_INFO_NAMETABLE returns a pointer to the first entry of the table. This is
+a PCRE2_SPTR pointer to a block of code units. In the 8-bit library, the first
+two bytes of each entry are the number of the capturing parenthesis, most
+significant byte first. In the 16-bit library, the pointer points to 16-bit
+code units, the first of which contains the parenthesis number. In the 32-bit
+library, the pointer points to 32-bit code units, the first of which contains
+the parenthesis number. The rest of the entry is the corresponding name, zero
+terminated.
+
+
+The names are in alphabetical order. If (?| is used to create multiple capture
+groups with the same number, as described in the
+section on duplicate group numbers
+in the
+pcre2pattern
+page, the groups may be given the same name, but there is only one entry in the
+table. Different names for groups of the same number are not permitted.
+
+
+Duplicate names for capture groups with different numbers are permitted, but
+only if PCRE2_DUPNAMES is set. They appear in the table in the order in which
+they were found in the pattern. In the absence of (?| this is the order of
+increasing number; when (?| is used this is not necessarily the case because
+later capture groups may have lower numbers.
+
+
+As a simple example of the name/number table, consider the following pattern
+after compilation by the 8-bit library (assume PCRE2_EXTENDED is set, so white
+space - including newlines - is ignored):
+
+ (?<date> (?<year>(\d\d)?\d\d) - (?<month>\d\d) - (?<day>\d\d) )
+
+There are four named capture groups, so the table has four entries, and each
+entry in the table is eight bytes long. The table is as follows, with
+non-printing bytes shows in hexadecimal, and undefined bytes shown as ??:
+
+ 00 01 d a t e 00 ??
+ 00 05 d a y 00 ?? ??
+ 00 04 m o n t h 00
+ 00 02 y e a r 00 ??
+
+When writing code to extract data from named capture groups using the
+name-to-number map, remember that the length of the entries is likely to be
+different for each compiled pattern.
+
+ PCRE2_INFO_NEWLINE
+
+The output is one of the following uint32_t values:
+
+ PCRE2_NEWLINE_CR Carriage return (CR)
+ PCRE2_NEWLINE_LF Linefeed (LF)
+ PCRE2_NEWLINE_CRLF Carriage return, linefeed (CRLF)
+ PCRE2_NEWLINE_ANY Any Unicode line ending
+ PCRE2_NEWLINE_ANYCRLF Any of CR, LF, or CRLF
+ PCRE2_NEWLINE_NUL The NUL character (binary zero)
+
+This identifies the character sequence that will be recognized as meaning
+"newline" while matching.
+
+ PCRE2_INFO_SIZE
+
+Return the size of the compiled pattern in bytes (for all three libraries). The
+third argument should point to a size_t variable. This value includes the
+size of the general data block that precedes the code units of the compiled
+pattern itself. The value that is used when pcre2_compile() is getting
+memory in which to place the compiled pattern may be slightly larger than the
+value returned by this option, because there are cases where the code that
+calculates the size has to over-estimate. Processing a pattern with the JIT
+compiler does not alter the value returned by this option.
+
+
+
+int pcre2_callout_enumerate(const pcre2_code *code,
+ int (*callback)(pcre2_callout_enumerate_block *, void *),
+ void *user_data);
+
+
+A script language that supports the use of string arguments in callouts might
+like to scan all the callouts in a pattern before running the match. This can
+be done by calling pcre2_callout_enumerate(). The first argument is a
+pointer to a compiled pattern, the second points to a callback function, and
+the third is arbitrary user data. The callback function is called for every
+callout in the pattern in the order in which they appear. Its first argument is
+a pointer to a callout enumeration block, and its second argument is the
+user_data value that was passed to pcre2_callout_enumerate(). The
+contents of the callout enumeration block are described in the
+pcre2callout
+documentation, which also gives further details about callouts.
+
+
+
+It is possible to save compiled patterns on disc or elsewhere, and reload them
+later, subject to a number of restrictions. The host on which the patterns are
+reloaded must be running the same version of PCRE2, with the same code unit
+width, and must also have the same endianness, pointer width, and PCRE2_SIZE
+type. Before compiled patterns can be saved, they must be converted to a
+"serialized" form, which in the case of PCRE2 is really just a bytecode dump.
+The functions whose names begin with pcre2_serialize_ are used for
+converting to and from the serialized form. They are described in the
+pcre2serialize
+documentation. Note that PCRE2 serialization does not convert compiled patterns
+to an abstract format like Java or .NET serialization.
+
+
+
+pcre2_match_data *pcre2_match_data_create(uint32_t ovecsize,
+ pcre2_general_context *gcontext);
+
+
+pcre2_match_data *pcre2_match_data_create_from_pattern(
+ const pcre2_code *code, pcre2_general_context *gcontext);
+
+
+void pcre2_match_data_free(pcre2_match_data *match_data);
+
+
+Information about a successful or unsuccessful match is placed in a match
+data block, which is an opaque structure that is accessed by function calls. In
+particular, the match data block contains a vector of offsets into the subject
+string that define the matched parts of the subject. This is known as the
+ovector.
+
+
+Before calling pcre2_match(), pcre2_dfa_match(), or
+pcre2_jit_match() you must create a match data block by calling one of
+the creation functions above. For pcre2_match_data_create(), the first
+argument is the number of pairs of offsets in the ovector.
+
+
+When using pcre2_match(), one pair of offsets is required to identify the
+string that matched the whole pattern, with an additional pair for each
+captured substring. For example, a value of 4 creates enough space to record
+the matched portion of the subject plus three captured substrings.
+
+
+When using pcre2_dfa_match() there may be multiple matched substrings of
+different lengths at the same point in the subject. The ovector should be made
+large enough to hold as many as are expected.
+
+
+A minimum of at least 1 pair is imposed by pcre2_match_data_create(), so
+it is always possible to return the overall matched string in the case of
+pcre2_match() or the longest match in the case of
+pcre2_dfa_match(). The maximum number of pairs is 65535; if the first
+argument of pcre2_match_data_create() is greater than this, 65535 is
+used.
+
+
+The second argument of pcre2_match_data_create() is a pointer to a
+general context, which can specify custom memory management for obtaining the
+memory for the match data block. If you are not using custom memory management,
+pass NULL, which causes malloc() to be used.
+
+
+For pcre2_match_data_create_from_pattern(), the first argument is a
+pointer to a compiled pattern. The ovector is created to be exactly the right
+size to hold all the substrings a pattern might capture when matched using
+pcre2_match(). You should not use this call when matching with
+pcre2_dfa_match(). The second argument is again a pointer to a general
+context, but in this case if NULL is passed, the memory is obtained using the
+same allocator that was used for the compiled pattern (custom or default).
+
+
+A match data block can be used many times, with the same or different compiled
+patterns. You can extract information from a match data block after a match
+operation has finished, using functions that are described in the sections on
+matched strings
+and
+other match data
+below.
+
+
+When a call of pcre2_match() fails, valid data is available in the match
+block only when the error is PCRE2_ERROR_NOMATCH, PCRE2_ERROR_PARTIAL, or one
+of the error codes for an invalid UTF string. Exactly what is available depends
+on the error, and is detailed below.
+
+
+When one of the matching functions is called, pointers to the compiled pattern
+and the subject string are set in the match data block so that they can be
+referenced by the extraction functions after a successful match. After running
+a match, you must not free a compiled pattern or a subject string until after
+all operations on the match data block (for that match) have taken place,
+unless, in the case of the subject string, you have used the
+PCRE2_COPY_MATCHED_SUBJECT option, which is described in the section entitled
+"Option bits for pcre2_match()"
+below.
+
+
+When a match data block itself is no longer needed, it should be freed by
+calling pcre2_match_data_free(). If this function is called with a NULL
+argument, it returns immediately, without doing anything.
+
+
+
+PCRE2_SIZE pcre2_get_match_data_size(pcre2_match_data *match_data);
+
+
+PCRE2_SIZE pcre2_get_match_data_heapframes_size(
+ pcre2_match_data *match_data);
+
+
+The size of a match data block depends on the size of the ovector that it
+contains. The function pcre2_get_match_data_size() returns the size, in
+bytes, of the block that is its argument.
+
+
+When pcre2_match() runs interpretively (that is, without using JIT), it
+makes use of a vector of data frames for remembering backtracking positions.
+The size of each individual frame depends on the number of capturing
+parentheses in the pattern and can be obtained by calling
+pcre2_pattern_info() with the PCRE2_INFO_FRAMESIZE option (see the
+section entitled "Information about a compiled pattern"
+above).
+
+
+Heap memory is used for the frames vector; if the initial memory block turns
+out to be too small during matching, it is automatically expanded. When
+pcre2_match() returns, the memory is not freed, but remains attached to
+the match data block, for use by any subsequent matches that use the same
+block. It is automatically freed when the match data block itself is freed.
+
+
+You can find the current size of the frames vector that a match data block owns
+by calling pcre2_get_match_data_heapframes_size(). For a newly created
+match data block the size will be zero. Some types of match may require a lot
+of frames and thus a large vector; applications that run in environments where
+memory is constrained can check this and free the match data block if the heap
+frames vector has become too big.
+
+
+
+int pcre2_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext);
+
+
+The function pcre2_match() is called to match a subject string against a
+compiled pattern, which is passed in the code argument. You can call
+pcre2_match() with the same code argument as many times as you
+like, in order to find multiple matches in the subject string or to match
+different subject strings with the same pattern.
+
+
+This function is the main matching facility of the library, and it operates in
+a Perl-like manner. For specialist use there is also an alternative matching
+function, which is described
+below
+in the section about the pcre2_dfa_match() function.
+
+
+Here is an example of a simple call to pcre2_match():
+
+ pcre2_match_data *md = pcre2_match_data_create(4, NULL);
+ int rc = pcre2_match(
+ re, /* result of pcre2_compile() */
+ "some string", /* the subject string */
+ 11, /* the length of the subject string */
+ 0, /* start at offset 0 in the subject */
+ 0, /* default options */
+ md, /* the match data block */
+ NULL); /* a match context; NULL means use defaults */
+
+If the subject string is zero-terminated, the length can be given as
+PCRE2_ZERO_TERMINATED. A match context must be provided if certain less common
+matching parameters are to be changed. For details, see the section on
+the match context
+above.
+
+
+The string to be matched by pcre2_match()
+
+
+The subject string is passed to pcre2_match() as a pointer in
+subject, a length in length, and a starting offset in
+startoffset. The length and offset are in code units, not characters.
+That is, they are in bytes for the 8-bit library, 16-bit code units for the
+16-bit library, and 32-bit code units for the 32-bit library, whether or not
+UTF processing is enabled. As a special case, if subject is NULL and
+length is zero, the subject is assumed to be an empty string. If
+length is non-zero, an error occurs if subject is NULL.
+
+
+If startoffset is greater than the length of the subject,
+pcre2_match() returns PCRE2_ERROR_BADOFFSET. When the starting offset is
+zero, the search for a match starts at the beginning of the subject, and this
+is by far the most common case. In UTF-8 or UTF-16 mode, the starting offset
+must point to the start of a character, or to the end of the subject (in UTF-32
+mode, one code unit equals one character, so all offsets are valid). Like the
+pattern string, the subject may contain binary zeros.
+
+
+A non-zero starting offset is useful when searching for another match in the
+same subject by calling pcre2_match() again after a previous success.
+Setting startoffset differs from passing over a shortened string and
+setting PCRE2_NOTBOL in the case of a pattern that begins with any kind of
+lookbehind. For example, consider the pattern
+
+ \Biss\B
+
+which finds occurrences of "iss" in the middle of words. (\B matches only if
+the current position in the subject is not a word boundary.) When applied to
+the string "Mississippi" the first call to pcre2_match() finds the first
+occurrence. If pcre2_match() is called again with just the remainder of
+the subject, namely "issippi", it does not match, because \B is always false
+at the start of the subject, which is deemed to be a word boundary. However, if
+pcre2_match() is passed the entire string again, but with
+startoffset set to 4, it finds the second occurrence of "iss" because it
+is able to look behind the starting point to discover that it is preceded by a
+letter.
+
+
+Finding all the matches in a subject is tricky when the pattern can match an
+empty string. PCRE2 includes a helper API to assist with this; see the
+section entitled "Iterating over all matches"
+below
+for details.
+
+
+If a non-zero starting offset is passed when the pattern is anchored, a single
+attempt to match at the given offset is made. This can only succeed if the
+pattern does not require the match to be at the start of the subject. In other
+words, the anchoring must be the result of setting the PCRE2_ANCHORED option or
+the use of .* with PCRE2_DOTALL, not by starting the pattern with ^ or \A.
+
+
+Option bits for pcre2_match()
+
+
+The unused bits of the options argument for pcre2_match() must be
+zero. The only bits that may be set are PCRE2_ANCHORED,
+PCRE2_COPY_MATCHED_SUBJECT, PCRE2_DISABLE_RECURSELOOP_CHECK, PCRE2_ENDANCHORED,
+PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART,
+PCRE2_NO_JIT, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and PCRE2_PARTIAL_SOFT.
+Their action is described below.
+
+
+Setting PCRE2_ANCHORED or PCRE2_ENDANCHORED at match time is not supported by
+the just-in-time (JIT) compiler. If it is set, JIT matching is disabled and the
+interpretive code in pcre2_match() is run.
+PCRE2_DISABLE_RECURSELOOP_CHECK is ignored by JIT, but apart from PCRE2_NO_JIT
+(obviously), the remaining options are supported for JIT matching.
+
+ PCRE2_ANCHORED
+
+The PCRE2_ANCHORED option limits pcre2_match() to matching at the first
+matching position. If a pattern was compiled with PCRE2_ANCHORED, or turned out
+to be anchored by virtue of its contents, it cannot be made unanchored at
+matching time. Note that setting the option at match time disables JIT
+matching.
+
+ PCRE2_COPY_MATCHED_SUBJECT
+
+By default, a pointer to the subject is remembered in the match data block so
+that, after a successful match, it can be referenced by the substring
+extraction functions. This means that the subject's memory must not be freed
+until all such operations are complete. For some applications where the
+lifetime of the subject string is not guaranteed, it may be necessary to make a
+copy of the subject string, but it is wasteful to do this unless the match is
+successful. After a successful match, if PCRE2_COPY_MATCHED_SUBJECT is set, the
+subject is copied and the new pointer is remembered in the match data block
+instead of the original subject pointer. The memory allocator that was used for
+the match block itself is used. The copy is automatically freed when
+pcre2_match_data_free() is called to free the match data block. It is also
+automatically freed if the match data block is re-used for another match
+operation.
+
+ PCRE2_DISABLE_RECURSELOOP_CHECK
+
+This option is relevant only to pcre2_match() for interpretive matching.
+It is ignored when JIT is used, and is forbidden for pcre2_dfa_match().
+
+
+The use of recursion in patterns can lead to infinite loops. In the
+interpretive matcher these would be eventually caught by the match or heap
+limits, but this could take a long time and/or use a lot of memory if the
+limits are large. There is therefore a check at the start of each recursion.
+If the same group is still active from a previous call, and the current subject
+pointer is the same as it was at the start of that group, and the furthest
+inspected character of the subject has not changed, an error is generated.
+
+
+There are rare cases of matches that would complete, but nevertheless trigger
+this error. This option disables the check. It is provided mainly for testing
+when comparing JIT and interpretive behaviour.
+
+ PCRE2_ENDANCHORED
+
+If the PCRE2_ENDANCHORED option is set, any string that pcre2_match()
+matches must be right at the end of the subject string. Note that setting the
+option at match time disables JIT matching.
+
+ PCRE2_NOTBOL
+
+This option specifies that first character of the subject string is not the
+beginning of a line, so the circumflex metacharacter should not match before
+it. Setting this without having set PCRE2_MULTILINE at compile time causes
+circumflex never to match. This option affects only the behaviour of the
+circumflex metacharacter. It does not affect \A.
+
+ PCRE2_NOTEOL
+
+This option specifies that the end of the subject string is not the end of a
+line, so the dollar metacharacter should not match it nor (except in multiline
+mode) a newline immediately before it. Setting this without having set
+PCRE2_MULTILINE at compile time causes dollar never to match. This option
+affects only the behaviour of the dollar metacharacter. It does not affect \Z
+or \z.
+
+ PCRE2_NOTEMPTY
+
+An empty string is not considered to be a valid match if this option is set. If
+there are alternatives in the pattern, they are tried. If all the alternatives
+match the empty string, the entire match fails. For example, if the pattern
+
+ a?b?
+
+is applied to a string not beginning with "a" or "b", it matches an empty
+string at the start of the subject. With PCRE2_NOTEMPTY set, this match is not
+valid, so pcre2_match() searches further into the string for occurrences
+of "a" or "b".
+
+ PCRE2_NOTEMPTY_ATSTART
+
+This is like PCRE2_NOTEMPTY, except that it locks out an empty string match
+only at the first matching position, that is, at the start of the subject plus
+the starting offset. An empty string match later in the subject is permitted.
+If the pattern is anchored, such a match can occur only if the pattern contains
+\K.
+
+ PCRE2_NO_JIT
+
+By default, if a pattern has been successfully processed by
+pcre2_jit_compile(), JIT is automatically used when pcre2_match()
+is called with options that JIT supports. Setting PCRE2_NO_JIT disables the use
+of JIT; it forces matching to be done by the interpreter.
+
+ PCRE2_NO_UTF_CHECK
+
+When PCRE2_UTF is set at compile time, the validity of the subject as a UTF
+string is checked unless PCRE2_NO_UTF_CHECK is passed to pcre2_match() or
+PCRE2_MATCH_INVALID_UTF was passed to pcre2_compile(). The latter special
+case is discussed in detail in the
+pcre2unicode
+documentation.
+
+
+In the default case, if a non-zero starting offset is given, the check is
+applied only to that part of the subject that could be inspected during
+matching, and there is a check that the starting offset points to the first
+code unit of a character or to the end of the subject. If there are no
+lookbehind assertions in the pattern, the check starts at the starting offset.
+Otherwise, it starts at the length of the longest lookbehind before the
+starting offset, or at the start of the subject if there are not that many
+characters before the starting offset. Note that the sequences \b and \B are
+one-character lookbehinds.
+
+
+The check is carried out before any other processing takes place, and a
+negative error code is returned if the check fails. There are several UTF error
+codes for each code unit width, corresponding to different problems with the
+code unit sequence. There are discussions about the validity of
+UTF-8 strings,
+UTF-16 strings,
+and
+UTF-32 strings
+in the
+pcre2unicode
+documentation.
+
+
+If you know that your subject is valid, and you want to skip this check for
+performance reasons, you can set the PCRE2_NO_UTF_CHECK option when calling
+pcre2_match(). You might want to do this for the second and subsequent
+calls to pcre2_match() if you are making repeated calls to find multiple
+matches in the same subject string.
+
+
+Warning: Unless PCRE2_MATCH_INVALID_UTF was set at compile time, when
+PCRE2_NO_UTF_CHECK is set at match time the effect of passing an invalid
+string as a subject, or an invalid value of startoffset, is undefined.
+Your program may crash or loop indefinitely or give wrong results.
+
+ PCRE2_PARTIAL_HARD
+ PCRE2_PARTIAL_SOFT
+
+These options turn on the partial matching feature. A partial match occurs if
+the end of the subject string is reached successfully, but there are not enough
+subject characters to complete the match. In addition, either at least one
+character must have been inspected or the pattern must contain a lookbehind, or
+the pattern must be one that could match an empty string.
+
+
+If this situation arises when PCRE2_PARTIAL_SOFT (but not PCRE2_PARTIAL_HARD)
+is set, matching continues by testing any remaining alternatives. Only if no
+complete match can be found is PCRE2_ERROR_PARTIAL returned instead of
+PCRE2_ERROR_NOMATCH. In other words, PCRE2_PARTIAL_SOFT specifies that the
+caller is prepared to handle a partial match, but only if no complete match can
+be found.
+
+
+If PCRE2_PARTIAL_HARD is set, it overrides PCRE2_PARTIAL_SOFT. In this case, if
+a partial match is found, pcre2_match() immediately returns
+PCRE2_ERROR_PARTIAL, without considering any other alternatives. In other
+words, when PCRE2_PARTIAL_HARD is set, a partial match is considered to be more
+important than an alternative complete match.
+
+
+There is a more detailed discussion of partial and multi-segment matching, with
+examples, in the
+pcre2partial
+documentation.
+
+
+
+When PCRE2 is built, a default newline convention is set; this is usually the
+standard convention for the operating system. The default can be overridden in
+a
+compile context
+by calling pcre2_set_newline(). It can also be overridden by starting a
+pattern string with, for example, (*CRLF), as described in the
+section on newline conventions
+in the
+pcre2pattern
+page. During matching, the newline choice affects the behaviour of the dot,
+circumflex, and dollar metacharacters. It may also alter the way the match
+starting position is advanced after a match failure for an unanchored pattern.
+
+
+When PCRE2_NEWLINE_CRLF, PCRE2_NEWLINE_ANYCRLF, or PCRE2_NEWLINE_ANY is set as
+the newline convention, and a match attempt for an unanchored pattern fails
+when the current starting position is at a CRLF sequence, and the pattern
+contains no explicit matches for CR or LF characters, the match position is
+advanced by two characters instead of one, in other words, to after the CRLF.
+
+
+The above rule is a compromise that makes the most common cases work as
+expected. For example, if the pattern is .+A (and the PCRE2_DOTALL option is
+not set), it does not match the string "\r\nA" because, after failing at the
+start, it skips both the CR and the LF before retrying. However, the pattern
+[\r\n]A does match that string, because it contains an explicit CR or LF
+reference, and so advances only by one character after the first failure.
+
+
+An explicit match for CR of LF is either a literal appearance of one of those
+characters in the pattern, or one of the \r or \n or equivalent octal or
+hexadecimal escape sequences. Implicit matches such as [^X] do not count, nor
+does \s, even though it includes CR and LF in the characters that it matches.
+
+
+Notwithstanding the above, anomalous effects may still occur when CRLF is a
+valid newline sequence and explicit \r or \n escapes appear in the pattern.
+
+
+
+uint32_t pcre2_get_ovector_count(pcre2_match_data *match_data);
+
+
+PCRE2_SIZE *pcre2_get_ovector_pointer(pcre2_match_data *match_data);
+
+
+In general, a pattern matches a certain portion of the subject, and in
+addition, further substrings from the subject may be picked out by
+parenthesized parts of the pattern. Following the usage in Jeffrey Friedl's
+book, this is called "capturing" in what follows, and the phrase "capture
+group" (Perl terminology) is used for a fragment of a pattern that picks out a
+substring. PCRE2 supports several other kinds of parenthesized group that do
+not cause substrings to be captured. The pcre2_pattern_info() function
+can be used to find out how many capture groups there are in a compiled
+pattern.
+
+
+You can use auxiliary functions for accessing captured substrings
+by number
+or
+by name,
+as described in sections below.
+
+
+Alternatively, you can make direct use of the vector of PCRE2_SIZE values,
+called the ovector, which contains the offsets of captured strings. It is
+part of the
+match data block.
+The function pcre2_get_ovector_pointer() returns the address of the
+ovector, and pcre2_get_ovector_count() returns the number of pairs of
+values it contains.
+
+
+Within the ovector, the first in each pair of values is set to the offset of
+the first code unit of a substring, and the second is set to the offset of the
+first code unit after the end of a substring. These values are always code unit
+offsets, not character offsets. That is, they are byte offsets in the 8-bit
+library, 16-bit offsets in the 16-bit library, and 32-bit offsets in the 32-bit
+library.
+
+
+After a partial match (error return PCRE2_ERROR_PARTIAL), only the first pair
+of offsets (that is, ovector[0] and ovector[1]) are set. They
+identify the part of the subject that was partially matched. See the
+pcre2partial
+documentation for details of partial matching.
+
+
+After a fully successful match, the first pair of offsets identifies the
+portion of the subject string that was matched by the entire pattern. The next
+pair is used for the first captured substring, and so on. The value returned by
+pcre2_match() is one more than the highest numbered pair that has been
+set. For example, if two substrings have been captured, the returned value is
+3. If there are no captured substrings, the return value from a successful
+match is 1, indicating that just the first pair of offsets has been set.
+
+
+If a pattern uses the \K escape sequence within a positive lookahead assertion,
+the reported start of a successful match can be greater than the end of the
+match. For example, if the pattern (?=ab\K) is matched against "ab", the start
+and end offset values for the match are 2 and 0.
+
+
+If a capture group is matched repeatedly within a single match operation, it is
+the last portion of the subject that it matched that is returned.
+
+
+If the ovector is too small to hold all the captured substring offsets, as much
+as possible is filled in, and the function returns a value of zero. If captured
+substrings are not of interest, pcre2_match() may be called with a match
+data block whose ovector is of minimum length (that is, one pair).
+
+
+It is possible for capture group number n+1 to match some part of the
+subject when group n has not been used at all. For example, if the string
+"abc" is matched against the pattern (a|(z))(bc) the return from the function
+is 4, and groups 1 and 3 are matched, but 2 is not. When this happens, both
+values in the offset pairs corresponding to unused groups are set to
+PCRE2_UNSET.
+
+
+Offset values that correspond to unused groups at the end of the expression are
+also set to PCRE2_UNSET. For example, if the string "abc" is matched against
+the pattern (abc)(x(yz)?)? groups 2 and 3 are not matched. The return from the
+function is 2, because the highest used capture group number is 1. The offsets
+for the second and third capture groups (assuming the vector is large enough,
+of course) are set to PCRE2_UNSET.
+
+
+Elements in the ovector that do not correspond to capturing parentheses in the
+pattern are never changed. That is, if a pattern contains n capturing
+parentheses, no more than ovector[0] to ovector[2n+1] are set by
+pcre2_match(). The other elements retain whatever values they previously
+had. After a failed match attempt, the contents of the ovector are unchanged.
+
+
+
+PCRE2_SPTR pcre2_get_mark(pcre2_match_data *match_data);
+
+
+PCRE2_SIZE pcre2_get_startchar(pcre2_match_data *match_data);
+
+
+As well as the offsets in the ovector, other information about a match is
+retained in the match data block and can be retrieved by the above functions in
+appropriate circumstances. If they are called at other times, the result is
+undefined.
+
+
+After a successful match, a partial match (PCRE2_ERROR_PARTIAL), or a failure
+to match (PCRE2_ERROR_NOMATCH), a mark name may be available. The function
+pcre2_get_mark() can be called to access this name, which can be
+specified in the pattern by any of the backtracking control verbs, not just
+(*MARK). The same function applies to all the verbs. It returns a pointer to
+the zero-terminated name, which is within the compiled pattern. If no name is
+available, NULL is returned. The length of the name (excluding the terminating
+zero) is stored in the code unit that precedes the name. You should use this
+length instead of relying on the terminating zero if the name might contain a
+binary zero.
+
+
+After a successful match, the name that is returned is the last mark name
+encountered on the matching path through the pattern. Instances of backtracking
+verbs without names do not count. Thus, for example, if the matching path
+contains (*MARK:A)(*PRUNE), the name "A" is returned. After a "no match" or a
+partial match, the last encountered name is returned. For example, consider
+this pattern:
+
+ ^(*MARK:A)((*MARK:B)a|b)c
+
+When it matches "bc", the returned name is A. The B mark is "seen" in the first
+branch of the group, but it is not on the matching path. On the other hand,
+when this pattern fails to match "bx", the returned name is B.
+
+
+Warning: By default, certain start-of-match optimizations are used to
+give a fast "no match" result in some situations. For example, if the anchoring
+is removed from the pattern above, there is an initial check for the presence
+of "c" in the subject before running the matching engine. This check fails for
+"bx", causing a match failure without seeing any marks. You can disable the
+start-of-match optimizations by setting the PCRE2_NO_START_OPTIMIZE option for
+pcre2_compile() or by starting the pattern with (*NO_START_OPT).
+
+
+After a successful match, a partial match, or one of the invalid UTF errors
+(for example, PCRE2_ERROR_UTF8_ERR5), pcre2_get_startchar() can be
+called. After a successful or partial match it returns the code unit offset of
+the character at which the match started. For a non-partial match, this can be
+different to the value of ovector[0] if the pattern contains the \K
+escape sequence. After a partial match, however, this value is always the same
+as ovector[0] because \K does not affect the result of a partial match.
+
+
+After a UTF check failure, pcre2_get_startchar() can be used to obtain
+the code unit offset of the invalid UTF character. Details are given in the
+pcre2unicode
+page.
+
+
+
+If pcre2_match() fails, it returns a negative number. This can be
+converted to a text string by calling the pcre2_get_error_message()
+function (see "Obtaining a textual error message"
+below).
+Negative error codes are also returned by other functions, and are documented
+with them. The codes are given names in the header file. If UTF checking is in
+force and an invalid UTF subject string is detected, one of a number of
+UTF-specific negative error codes is returned. Details are given in the
+pcre2unicode
+page. The following are the other errors that may be returned by
+pcre2_match():
+
+ PCRE2_ERROR_NOMATCH
+
+The subject string did not match the pattern.
+
+ PCRE2_ERROR_PARTIAL
+
+The subject string did not match, but it did match partially. See the
+pcre2partial
+documentation for details of partial matching.
+
+ PCRE2_ERROR_BADMAGIC
+
+PCRE2 stores a 4-byte "magic number" at the start of the compiled code, to
+catch the case when it is passed a junk pointer. This is the error that is
+returned when the magic number is not present.
+
+ PCRE2_ERROR_BADMODE
+
+This error is given when a compiled pattern is passed to a function in a
+library of a different code unit width, for example, a pattern compiled by
+the 8-bit library is passed to a 16-bit or 32-bit library function.
+
+ PCRE2_ERROR_BADOFFSET
+
+The value of startoffset was greater than the length of the subject.
+
+ PCRE2_ERROR_BADOPTION
+
+An unrecognized bit was set in the options argument.
+
+ PCRE2_ERROR_BADUTFOFFSET
+
+The UTF code unit sequence that was passed as a subject was checked and found
+to be valid (the PCRE2_NO_UTF_CHECK option was not set), but the value of
+startoffset did not point to the beginning of a UTF character or the end
+of the subject.
+
+ PCRE2_ERROR_CALLOUT
+
+This error is never generated by pcre2_match() itself. It is provided for
+use by callout functions that want to cause pcre2_match() or
+pcre2_callout_enumerate() to return a distinctive error code. See the
+pcre2callout
+documentation for details.
+
+ PCRE2_ERROR_DEPTHLIMIT
+
+The nested backtracking depth limit was reached.
+
+ PCRE2_ERROR_HEAPLIMIT
+
+The heap limit was reached.
+
+ PCRE2_ERROR_INTERNAL
+
+An unexpected internal error has occurred. This error could be caused by a bug
+in PCRE2 or by overwriting of the compiled pattern.
+
+ PCRE2_ERROR_JIT_STACKLIMIT
+
+This error is returned when a pattern that was successfully studied using JIT
+is being matched, but the memory available for the just-in-time processing
+stack is not large enough. See the
+pcre2jit
+documentation for more details.
+
+ PCRE2_ERROR_MATCHLIMIT
+
+The backtracking match limit was reached.
+
+ PCRE2_ERROR_NOMEMORY
+
+Heap memory is used to remember backtracking points. This error is given when
+the memory allocation function (default or custom) fails. Note that a different
+error, PCRE2_ERROR_HEAPLIMIT, is given if the amount of memory needed exceeds
+the heap limit. PCRE2_ERROR_NOMEMORY is also returned if
+PCRE2_COPY_MATCHED_SUBJECT is set and memory allocation fails.
+
+ PCRE2_ERROR_NULL
+
+Either the code, subject, or match_data argument was passed
+as NULL.
+
+ PCRE2_ERROR_RECURSELOOP
+
+This error is returned when pcre2_match() detects a recursion loop within
+the pattern. Specifically, it means that either the whole pattern or a
+capture group has been called recursively for the second time at the same
+position in the subject string. Some simple patterns that might do this are
+detected and faulted at compile time, but more complicated cases, in particular
+mutual recursions between two different groups, cannot be detected until
+matching is attempted.
+
+
+
+int pcre2_get_error_message(int errorcode, PCRE2_UCHAR *buffer,
+ PCRE2_SIZE bufflen);
+
+
+A text message for an error code from any PCRE2 function (compile, match, or
+auxiliary) can be obtained by calling pcre2_get_error_message(). The code
+is passed as the first argument, with the remaining two arguments specifying a
+code unit buffer and its length in code units, into which the text message is
+placed. The message is returned in code units of the appropriate width for the
+library that is being used.
+
+
+The returned message is terminated with a trailing zero, and the function
+returns the number of code units used, excluding the trailing zero. If the
+error number is unknown, the negative error code PCRE2_ERROR_BADDATA is
+returned. If the buffer is too small, the message is truncated (but still with
+a trailing zero), and the negative error code PCRE2_ERROR_NOMEMORY is returned.
+None of the messages is very long; a buffer size of 120 code units is ample.
+
+
+
+int pcre2_next_match(pcre2_match_data *match_data,
+ PCRE2_SIZE *pstart_offset, uint32_t *poptions);
+
+
+A common task for applications is to implement "global" matching behaviour,
+for example, replacing all matches in the subject; splitting the subject on all
+matches; or simply counting the number of matches. The pcre2_next_match()
+function helps with this task by providing the appropriate parameters for the
+next match attempt (available since PCRE2 10.47).
+
+
+First, a match attempt should be made using one of the matching functions
+(pcre2_match(), pcre2_dfa_match(), or pcre2_jit_match()).
+Then, pcre2_next_match() can be called, providing the same
+match_data parameter.
+
+
+It returns 0 ("false") if there is no need to make a further match attempt, or
+1 ("true") if another match should be attempted. Returning 1 does not imply that
+there is another match, only that another match should be attempted (which may
+return PCRE2_ERROR_NOMATCH).
+
+
+The *pstart_offset and *poptions are set if the function returns 1.
+The *pstart_offset should be passed to the next match attempt directly,
+and the *poptions should be passed to the next match attempt by combining
+with the application's match options using OR.
+
+
+There is some code that demonstrates how to do this in the
+pcre2demo
+sample program. The general pattern is:
+
+
+
+ uint32_t app_options = ...;
+ uint32_t global_options = 0;
+ PCRE2_SIZE start_offset = 0;
+ while (1)
+ {
+ int rc = pcre2_match(re, subject, subject_len, start_offset,
+ app_options | global_options, match_data,
+ match_context);
+
+ if (rc == PCRE2_ERROR_NOMATCH) break; /* no match, and no more attempts */
+ if (rc < 0) { ... exit }
+
+ ...handle the match
+
+ if (!pcre2_next_match(match_data, &start_offset, &global_options))
+ break; /* no more attempts */
+ }
+
+
+
+The guarantees provided by pcre2_next_match() are that the start_offset
+will advance, so the loop will definitely terminate. The conditions which
+ensure this are that either: (a) pcre2_next_match() returns 0 (false); or
+(b) the returned *pstart_offset is strictly greater than the previous
+start_offset; or (c) if the previous match was a successful match of the empty
+string then the returned *pstart_offset is equal to the previous
+ovector[1], and *poptions will be set to PCRE2_NOTEMPTY_ATSTART to prevent
+another empty match from being returned.
+
+
+A loop implemented as shown above will always terminate, unless there is a bug
+in PCRE2. As a measure of "defensive programming", applications are encouraged
+to add an assertion or check to break their loop if it does not make progress
+(and report the issue as a bug).
+
+
+If an application does not use the flag PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK, then
+each match is "well-behaved" and satisfies:
+
+ start_offset <= ovector[0] <= ovector[1].
+
+In this case, the matches found by pcre2_match() with pcre2_next_match() will be
+sorted, non-overlapping (possibly touching), and with no duplicates.
+
+
+Otherwise, if PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK is used, then the guarantees are
+considerably weaker. We do not guarantee that the matches will always advance:
+only that the start_offset will. The matches found by pcre2_match() with
+pcre2_next_match() will be a finite sequence (as pcre2_next_match() ensures that
+start_offset advances, so the search will terminate). The matches can however be
+overlapping, can contain duplicates, and (in truly pathological examples) may
+not even be sorted by ovector[0]. Additionally, each match itself can end before
+it starts (ovector[1] < ovector[0]). We recommend that applications do not set
+PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK.
+
+
+
+int pcre2_substring_length_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_SIZE *length);
+
+
+int pcre2_substring_copy_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_UCHAR *buffer,
+ PCRE2_SIZE *bufflen);
+
+
+int pcre2_substring_get_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_UCHAR **bufferptr,
+ PCRE2_SIZE *bufflen);
+
+
+void pcre2_substring_free(PCRE2_UCHAR *buffer);
+
+
+Captured substrings can be accessed directly by using the ovector as described
+above.
+For convenience, auxiliary functions are provided for extracting captured
+substrings as new, separate, zero-terminated strings. A substring that contains
+a binary zero is correctly extracted and has a further zero added on the end,
+but the result is not, of course, a C string.
+
+
+The functions in this section identify substrings by number. The number zero
+refers to the entire matched substring, with higher numbers referring to
+substrings captured by parenthesized groups. After a partial match, only
+substring zero is available. An attempt to extract any other substring gives
+the error PCRE2_ERROR_PARTIAL. The next section describes similar functions for
+extracting captured substrings by name.
+
+
+If a pattern uses the \K escape sequence within a positive lookahead assertion,
+the reported start of a successful match can be greater than the end of the
+match. For example, if the pattern (?=ab\K) is matched against "ab", the start
+and end offset values for the match are 2 and 0. In this situation, calling
+these functions with a zero substring number extracts a zero-length empty
+string.
+
+
+You can find the length in code units of a captured substring without
+extracting it by calling pcre2_substring_length_bynumber(). The first
+argument is a pointer to the match data block, the second is the group number,
+and the third is a pointer to a variable into which the length is placed. If
+you just want to know whether or not the substring has been captured, you can
+pass the third argument as NULL.
+
+
+The pcre2_substring_copy_bynumber() function copies a captured substring
+into a supplied buffer, whereas pcre2_substring_get_bynumber() copies it
+into new memory, obtained using the same memory allocation function that was
+used for the match data block. The first two arguments of these functions are a
+pointer to the match data block and a capture group number.
+
+
+The final arguments of pcre2_substring_copy_bynumber() are a pointer to
+the buffer and a pointer to a variable that contains its length in code units.
+This is updated to contain the actual number of code units used for the
+extracted substring, excluding the terminating zero.
+
+
+For pcre2_substring_get_bynumber() the third and fourth arguments point
+to variables that are updated with a pointer to the new memory and the number
+of code units that comprise the substring, again excluding the terminating
+zero. When the substring is no longer needed, the memory should be freed by
+calling pcre2_substring_free().
+
+
+The return value from all these functions is zero for success, or a negative
+error code. If the pattern match failed, the match failure code is returned.
+If a substring number greater than zero is used after a partial match,
+PCRE2_ERROR_PARTIAL is returned. Other possible error codes are:
+
+ PCRE2_ERROR_NOMEMORY
+
+The buffer was too small for pcre2_substring_copy_bynumber(), or the
+attempt to get memory failed for pcre2_substring_get_bynumber().
+
+ PCRE2_ERROR_NOSUBSTRING
+
+There is no substring with that number in the pattern, that is, the number is
+greater than the number of capturing parentheses.
+
+ PCRE2_ERROR_UNAVAILABLE
+
+The substring number, though not greater than the number of captures in the
+pattern, is greater than the number of slots in the ovector, so the substring
+could not be captured.
+
+ PCRE2_ERROR_UNSET
+
+The substring did not participate in the match. For example, if the pattern is
+(abc)|(def) and the subject is "def", and the ovector contains at least two
+capturing slots, substring number 1 is unset.
+
+
+
+int pcre2_substring_list_get(pcre2_match_data *match_data,
+ PCRE2_UCHAR ***listptr, PCRE2_SIZE **lengthsptr);
+
+
+void pcre2_substring_list_free(PCRE2_UCHAR **list);
+
+
+The pcre2_substring_list_get() function extracts all available substrings
+and builds a list of pointers to them. It also (optionally) builds a second
+list that contains their lengths (in code units), excluding a terminating zero
+that is added to each of them. All this is done in a single block of memory
+that is obtained using the same memory allocation function that was used to get
+the match data block.
+
+
+This function must be called only after a successful match. If called after a
+partial match, the error code PCRE2_ERROR_PARTIAL is returned.
+
+
+The address of the memory block is returned via listptr, which is also
+the start of the list of string pointers. The end of the list is marked by a
+NULL pointer. The address of the list of lengths is returned via
+lengthsptr. If your strings do not contain binary zeros and you do not
+therefore need the lengths, you may supply NULL as the lengthsptr
+argument to disable the creation of a list of lengths. The yield of the
+function is zero if all went well, or PCRE2_ERROR_NOMEMORY if the memory block
+could not be obtained. When the list is no longer needed, it should be freed by
+calling pcre2_substring_list_free().
+
+
+If this function encounters a substring that is unset, which can happen when
+capture group number n+1 matches some part of the subject, but group
+n has not been used at all, it returns an empty string. This can be
+distinguished from a genuine zero-length substring by inspecting the
+appropriate offset in the ovector, which contain PCRE2_UNSET for unset
+substrings, or by calling pcre2_substring_length_bynumber().
+
+
+
+int pcre2_substring_number_from_name(const pcre2_code *code,
+ PCRE2_SPTR name);
+
+
+int pcre2_substring_length_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_SIZE *length);
+
+
+int pcre2_substring_copy_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_UCHAR *buffer, PCRE2_SIZE *bufflen);
+
+
+int pcre2_substring_get_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_UCHAR **bufferptr, PCRE2_SIZE *bufflen);
+
+
+void pcre2_substring_free(PCRE2_UCHAR *buffer);
+
+
+To extract a substring by name, you first have to find associated number.
+For example, for this pattern:
+
+ (a+)b(?<xxx>\d+)...
+
+the number of the capture group called "xxx" is 2. If the name is known to be
+unique (PCRE2_DUPNAMES was not set), you can find the number from the name by
+calling pcre2_substring_number_from_name(). The first argument is the
+compiled pattern, and the second is the name. The yield of the function is the
+group number, PCRE2_ERROR_NOSUBSTRING if there is no group with that name, or
+PCRE2_ERROR_NOUNIQUESUBSTRING if there is more than one group with that name.
+Given the number, you can extract the substring directly from the ovector, or
+use one of the "bynumber" functions described above.
+
+
+For convenience, there are also "byname" functions that correspond to the
+"bynumber" functions, the only difference being that the second argument is a
+name instead of a number. If PCRE2_DUPNAMES is set and there are duplicate
+names, these functions scan all the groups with the given name, and return the
+captured substring from the first named group that is set.
+
+
+If there are no groups with the given name, PCRE2_ERROR_NOSUBSTRING is
+returned. If all groups with the name have numbers that are greater than the
+number of slots in the ovector, PCRE2_ERROR_UNAVAILABLE is returned. If there
+is at least one group with a slot in the ovector, but no group is found to be
+set, PCRE2_ERROR_UNSET is returned.
+
+
+Warning: If the pattern uses the (?| feature to set up multiple
+capture groups with the same number, as described in the
+section on duplicate group numbers
+in the
+pcre2pattern
+page, you cannot use names to distinguish the different capture groups, because
+names are not included in the compiled code. The matching process uses only
+numbers. For this reason, the use of different names for groups with the
+same number causes an error at compile time.
+
+
+
+int pcre2_substitute(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext, PCRE2_SPTR replacement,
+ PCRE2_SIZE rlength, PCRE2_UCHAR *outputbuffer,
+ PCRE2_SIZE *outlengthptr);
+
+
+This function optionally calls pcre2_match() and then makes a copy of the
+subject string in outputbuffer, replacing parts that were matched with
+the replacement string, whose length is supplied in rlength, which
+can be given as PCRE2_ZERO_TERMINATED for a zero-terminated string. As a
+special case, if replacement is NULL and rlength is zero, the
+replacement is assumed to be an empty string. If rlength is non-zero, an
+error occurs if replacement is NULL.
+
+
+There is an option (see PCRE2_SUBSTITUTE_REPLACEMENT_ONLY below) to return just
+the replacement string(s). The default action is to perform just one
+replacement if the pattern matches, but there is an option that requests
+multiple replacements (see PCRE2_SUBSTITUTE_GLOBAL below).
+
+
+If successful, pcre2_substitute() returns the number of substitutions
+that were carried out. This may be zero if no match was found, and is never
+greater than one unless PCRE2_SUBSTITUTE_GLOBAL is set. A negative value is
+returned if an error is detected.
+
+
+Matches in which a \K item in a lookahead in the pattern causes the match to
+end before it starts are not supported, and give rise to an error return. For
+global replacements, matches in which \K in a lookbehind causes the match to
+start earlier than the point that was reached in the previous iteration are
+also not supported. (These cases are only possible if the pattern was compiled
+with the backwards-compatibility option PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK.)
+
+
+The first seven arguments of pcre2_substitute() are the same as for
+pcre2_match(), except that the partial matching options are not
+permitted, and match_data may be passed as NULL, in which case a match
+data block is obtained and freed within this function, using memory management
+functions from the match context, if provided, or else those that were used to
+allocate memory for the compiled code.
+
+
+If match_data is not NULL and PCRE2_SUBSTITUTE_MATCHED is not set, the
+provided block is used for all calls to pcre2_match(), and its contents
+afterwards are the result of the final call made internally by
+pcre2_substitute() to the matching function. For global changes, this will
+always be a no-match error. The contents of the ovector within the match data
+block may or may not have been changed.
+
+
+As well as the usual options for pcre2_match(), a number of additional
+options can be set in the options argument of pcre2_substitute().
+One such option is PCRE2_SUBSTITUTE_MATCHED. When this is set, an external
+match_data block must be provided, and it must have already been used for
+an external call to pcre2_match() (or pcre2_jit_match()) with the
+same pattern, subject pointer, effective subject length, start offset, and match
+option arguments (substitute-specific options can be added to the options
+argument). If any of these parameters is changed, pcre2_substitute()
+returns an error. The data in the match_data block (return code, offset
+vector) is used for the first substitution instead of calling
+pcre2_match() from within pcre2_substitute(). This allows an
+application to check for a match before choosing to substitute, without having
+to repeat the match.
+
+
+If the contents of the subject buffer are mutated in between pcre2_match()
+and a call to pcre2_substitute() with PCRE2_SUBSTITUTE_MATCHED, the
+behaviour is unsafe; in particular, in this case, PCRE2 is unable to ensure that
+the offsets in the ovector point to the start of characters (with UTF-encoded
+input).
+
+
+The contents of the externally supplied match data block are not changed when
+PCRE2_SUBSTITUTE_MATCHED is set, and so the match block is permitted for use in
+another call using PCRE2_SUBSTITUTE_MATCHED. If PCRE2_SUBSTITUTE_GLOBAL is also
+set, pcre2_match() is called after the first substitution to check for
+furthe matches, but this is done using an internally obtained match data block,
+thus always leaving the external block unchanged.
+
+
+The code argument is not used for matching before the first substitution
+when PCRE2_SUBSTITUTE_MATCHED is set, but it must be provided, even when
+PCRE2_SUBSTITUTE_GLOBAL is not set, because it contains information such as the
+UTF setting and the number of capturing parentheses in the pattern.
+
+
+When using PCRE2_SUBSTITUTE_MATCHED, you should not modify the subject string
+in between the prior call to pcre2_match() and pcre2_substitute(),
+as the substitution assumes that the passed-in ovector is compatible with the
+subject string. Although PCRE2 does verify that the subject is a pointer to the
+same buffer, it cannot in general verify whether the contents of the buffer have
+changed. For example, if the subject buffer is mutated from one valid UTF-8
+string to another valid string, of the same length in code units, the ovector
+offsets are no longer guaranteed to point to the start of a character. Beware
+that with PCRE2_SUBSTITUTE_MATCHED in UTF mode, the subject string is not
+re-scanned for UTF validity when pcre2_substitute() first uses it.
+
+
+The default action of pcre2_substitute() is to return a copy of the
+subject string with matched substrings replaced. However, if
+PCRE2_SUBSTITUTE_REPLACEMENT_ONLY is set, only the replacement substrings are
+returned. In the global case, multiple replacements are concatenated in the
+output buffer. Substitution callouts (see
+below)
+can be used to separate them if necessary.
+
+
+Partial matching is supported, with limitations: if matching succeeds but with a
+partial match, then pcre2_substitute returns PCRE2_ERROR_PARTIAL. When
+partial-matching (either of PCRE2_PARTIAL_HARD or PCRE2_PARTIAL_SOFT is passed),
+then PCRE2_SUBSTITUTE_REPLACEMENT_ONLY must also be set, or else
+PCRE2_ERROR_BADOPTION is returned. Similarly, certain replacement items
+($' and $_) cause PCRE2_ERROR_PARTIALSUBS to be returned when partial-matching,
+even if a complete match is found.
+
+
+The outlengthptr argument of pcre2_substitute() must point to a
+variable that contains the length, in code units, of the output buffer. If the
+function is successful, the value is updated to contain the length in code
+units of the new string, excluding the trailing zero that is automatically
+added.
+
+
+If the function is not successful, the value set via outlengthptr depends
+on the type of error. For syntax errors in the replacement string, the value is
+the offset in the replacement string where the error was detected. For other
+errors, the value is PCRE2_UNSET by default. This includes the case of the
+output buffer being too small, unless PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set.
+
+
+PCRE2_SUBSTITUTE_OVERFLOW_LENGTH changes what happens when the output buffer is
+too small. The default action is to return PCRE2_ERROR_NOMEMORY immediately. If
+this option is set, however, pcre2_substitute() continues to go through
+the motions of matching and substituting (without, of course, writing anything)
+in order to compute the size of buffer that is needed, which will include the
+extra space for the terminating NUL. This value is passed back via the
+outlengthptr variable, with the result of the function still being
+PCRE2_ERROR_NOMEMORY.
+
+
+Passing a buffer size of zero is a permitted way of finding out how much memory
+is needed for given substitution. However, this does mean that the entire
+operation is carried out twice. Depending on the application, it may be more
+efficient to allocate a large buffer and free the excess afterwards, instead of
+using PCRE2_SUBSTITUTE_OVERFLOW_LENGTH.
+
+
+The replacement string, which is interpreted as a UTF string in UTF mode, is
+checked for UTF validity unless PCRE2_NO_UTF_CHECK is set. An invalid UTF
+replacement string causes an immediate return with the relevant UTF error code.
+
+
+If PCRE2_SUBSTITUTE_LITERAL is set, the replacement string is not interpreted
+in any way. By default, however, a dollar character is an escape character that
+can specify the insertion of characters from capture groups and names from
+(*MARK) or other control verbs in the pattern. Dollar is the only escape
+character (backslash is treated as literal). The following forms are
+recognized:
+
+ $$ insert a dollar character
+ $n or ${n} insert the contents of group n
+ $0 or $& insert the entire matched substring
+ $` insert the substring that precedes the match
+ $' insert the substring that follows the match
+ $_ insert the entire input string
+ $+ insert the highest-numbered capture group which matched
+ $*MARK or ${*MARK} insert a control verb name
+
+Either a group number or a group name can be given for n, for example $2
+or $NAME. Curly brackets are required only if the following character would be
+interpreted as part of the number or name. The number may be zero to include
+the entire matched string. For example, if the pattern a(b)c is matched with
+"=abc=" and the replacement string "+$1$0$1+", the result is "=+babcb+=".
+
+
+The JavaScript form $<name>, where the angle brackets are part of the syntax,
+is also recognized for group names, but not for group numbers or *MARK.
+
+
+$*MARK inserts the name from the last encountered backtracking control verb on
+the matching path that has a name. (*MARK) must always include a name, but the
+other verbs need not. For example, in the case of (*MARK:A)(*PRUNE) the name
+inserted is "A", but for (*MARK:A)(*PRUNE:B) the relevant name is "B". This
+facility can be used to perform simple simultaneous substitutions, as this
+pcre2test example shows:
+
+ /(*MARK:pear)apple|(*MARK:orange)lemon/g,replace=${*MARK}
+ apple lemon
+ 2: pear orange
+
+PCRE2_SUBSTITUTE_GLOBAL causes the function to iterate over the subject string,
+replacing every matching substring. If this option is not set, only the first
+matching substring is replaced. The search for matches takes place in the
+original subject string (that is, previous replacements do not affect it).
+Iteration is implemented by advancing the startoffset value for each
+search, which is always passed the entire subject string. If an offset limit is
+set in the match context, searching stops when that limit is reached.
+
+
+Because global substitutions apply the pattern repeatedly to the subject string,
+and always iterate over non-overlapping matches, the substitutions done by
+pcre2_substitute() do not match and substitute text inside the replacement
+strings themselves (no recursive/iterative substitution). However, applications
+can easily implement other alternative replacement strategies, such as
+iteratively replacing, then matching and replacing on the result. The
+replacement loop inside pcre2_substitute() is simple and can be emulated
+in client code by allocating a buffer, searching for matches in a loop, and
+calling pcre2_substitute() with PCRE2_SUBSTITUTE_REPLACEMENT_ONLY an
+PCRE2_SUBSTITUTE_MATCHED, and without PCRE2_SUBSTITUTE_GLOBAL.
+
+
+You can restrict the effect of a global substitution to a portion of the
+subject string by setting either or both of startoffset and an offset
+limit. Here is a pcre2test example:
+
+ /B/g,replace=!,use_offset_limit
+ ABC ABC ABC ABC\=offset=3,offset_limit=12
+ 2: ABC A!C A!C ABC
+
+When continuing with global substitutions after matching a substring with zero
+length, an attempt to find a non-empty match at the same offset is performed.
+If this is not successful, the offset is advanced by one character except when
+CRLF is a valid newline sequence and the next two characters are CR, LF. In
+this case, the offset is advanced by two characters.
+
+
+PCRE2_SUBSTITUTE_UNKNOWN_UNSET causes references to capture groups that do
+not appear in the pattern to be treated as unset groups. This option should be
+used with care, because it means that a typo in a group name or number no
+longer causes the PCRE2_ERROR_NOSUBSTRING error.
+
+
+PCRE2_SUBSTITUTE_UNSET_EMPTY causes unset capture groups (including unknown
+groups when PCRE2_SUBSTITUTE_UNKNOWN_UNSET is set) to be treated as empty
+strings when inserted as described above. If this option is not set, an attempt
+to insert an unset group causes the PCRE2_ERROR_UNSET error. This option does
+not influence the extended substitution syntax described below.
+
+
+PCRE2_SUBSTITUTE_EXTENDED causes extra processing to be applied to the
+replacement string. Without this option, only the dollar character is special,
+and only the group insertion forms listed above are valid. When
+PCRE2_SUBSTITUTE_EXTENDED is set, several things change:
+
+
+Firstly, backslash in a replacement string is interpreted as an escape
+character. The usual forms such as \x{ddd} can be used to specify particular
+character codes, and backslash followed by any non-alphanumeric character
+quotes that character. Extended quoting can be coded using \Q...\E, exactly
+as in pattern strings. The escapes \b and \v are interpreted as the
+characters backspace and vertical tab, respectively.
+
+
+The interpretation of backslash followed by one or more digits is the same as
+in a pattern, which in Perl has some ambiguities. Details are given in the
+pcre2pattern
+page.
+
+
+The Python form \g<n>, where the angle brackets are part of the syntax and
+n is either a group name or number, is recognized as an alternative way
+of inserting the contents of a group, for example \g<3>.
+
+
+There are also four escape sequences for forcing the case of inserted letters.
+Case forcing applies to all inserted characters, including those from capture
+groups and letters within \Q...\E quoted sequences. The insertion mechanism
+has three states: no case forcing, force upper case, and force lower case. The
+escape sequences change the current state: \U and \L change to upper or lower
+case forcing, respectively, and \E (when not terminating a \Q quoted
+sequence) reverts to no case forcing. The sequences \u and \l force the next
+character (if it is a letter) to upper or lower case, respectively, and then
+the state automatically reverts to no case forcing.
+
+
+However, if \u is immediately followed by \L or \l is immediately followed
+by \U, the next character's case is forced by the first escape sequence, and
+subsequent characters by the second. This provides a "title casing" facility
+that can be applied to group captures. For example, if group 1 has captured
+"heLLo", the replacement string "\u\L$1" becomes "Hello".
+
+
+If either PCRE2_UTF or PCRE2_UCP was set when the pattern was compiled, Unicode
+properties are used for case forcing characters whose code points are greater
+than 127. However, only simple case folding, as determined by the Unicode file
+CaseFolding.txt is supported. PCRE2 does not support language-specific
+special casing rules such as using different lower case Greek sigmas in the
+middle and ends of words (as defined in the Unicode file
+SpecialCasing.txt).
+
+
+Note that case forcing sequences such as \U...\E do not nest. For example,
+the result of processing "\Uaa\LBB\Ecc\E" is "AAbbcc"; the final \E has no
+effect. Note also that the PCRE2_ALT_BSUX and PCRE2_EXTRA_ALT_BSUX options do
+not apply to replacement strings.
+
+
+The final effect of setting PCRE2_SUBSTITUTE_EXTENDED is to add more
+flexibility to capture group substitution. The syntax is similar to that used
+by Bash:
+
+ ${n:-string}
+ ${n:+string1:string2}
+
+As in the simple case, n may be a group number or a name. The first form
+specifies a default value. If group n is set, its value is inserted; if
+not, the string is expanded and the result inserted. The second form specifies
+strings that are expanded and inserted when group n is set or unset,
+respectively. The first form is just a convenient shorthand for
+
+ ${n:+${n}:string}
+
+Backslash can be used to escape colons and closing curly brackets in the
+replacement strings. A change of the case forcing state within a replacement
+string remains in force afterwards, as shown in this pcre2test example:
+
+ /(some)?(body)/substitute_extended,replace=${1:+\U:\L}HeLLo
+ body
+ 1: hello
+ somebody
+ 1: HELLO
+
+The PCRE2_SUBSTITUTE_UNSET_EMPTY option does not affect these extended
+substitutions. However, PCRE2_SUBSTITUTE_UNKNOWN_UNSET does cause unknown
+groups in the extended syntax forms to be treated as unset.
+
+
+If PCRE2_SUBSTITUTE_LITERAL is set, PCRE2_SUBSTITUTE_UNKNOWN_UNSET,
+PCRE2_SUBSTITUTE_UNSET_EMPTY, and PCRE2_SUBSTITUTE_EXTENDED are irrelevant and
+are ignored.
+
+
+Substitution errors
+
+
+In the event of an error, pcre2_substitute() returns a negative error
+code. Except for PCRE2_ERROR_NOMATCH (which is never returned), errors from
+pcre2_match() are passed straight back.
+
+
+PCRE2_ERROR_NOSUBSTRING is returned for a non-existent substring insertion,
+unless PCRE2_SUBSTITUTE_UNKNOWN_UNSET is set.
+
+
+PCRE2_ERROR_UNSET is returned for an unset substring insertion (including an
+unknown substring when PCRE2_SUBSTITUTE_UNKNOWN_UNSET is set) when the simple
+(non-extended) syntax is used and PCRE2_SUBSTITUTE_UNSET_EMPTY is not set.
+
+
+PCRE2_ERROR_NOMEMORY is returned if the output buffer is not big enough. If the
+PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option is set, the size of buffer that is
+needed is returned via outlengthptr. Note that this does not happen by
+default.
+
+
+PCRE2_ERROR_NULL is returned if PCRE2_SUBSTITUTE_MATCHED is set but the
+match_data argument is NULL or if the subject or replacement
+arguments are NULL. For backward compatibility reasons an exception is made for
+the replacement argument if the rlength argument is also 0.
+
+
+PCRE2_ERROR_BADREPLACEMENT is used for miscellaneous syntax errors in the
+replacement string, with more particular errors being PCRE2_ERROR_BADREPESCAPE
+(invalid escape sequence), PCRE2_ERROR_REPMISSINGBRACE (closing curly bracket
+not found), PCRE2_ERROR_BADSUBSTITUTION (syntax error in extended group
+substitution), and PCRE2_ERROR_BADSUBSPATTERN (the pattern match ended before
+it started or the match started earlier than the current position in the
+subject, which can happen if \K is used in a lookaround assertion).
+
+
+As for all PCRE2 errors, a text message that describes the error can be
+obtained by calling the pcre2_get_error_message() function (see
+"Obtaining a textual error message"
+above).
+
+
+Substitution callouts
+
+
+int pcre2_set_substitute_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_substitute_callout_block *, void *),
+ void *callout_data);
+
+
+The pcre2_set_substitute_callout() function can be used to specify a
+callout function for pcre2_substitute(). This information is passed in
+a match context. The callout function is called after each substitution has
+been processed, but it can cause the replacement not to happen.
+
+
+The callout function is not called for simulated substitutions that happen as a
+result of the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option. In this mode, when
+substitution processing exceeds the buffer space provided by the caller,
+processing continues by counting code units. The simulation is unable to
+populate the callout block, and so the simulation is pessimistic about the
+required buffer size. Whichever is larger of accepted or rejected substitution
+is reported as the required size. Therefore, the returned buffer length may be
+an overestimate (without a substitution callout, it is normally an exact
+measurement).
+
+
+The first argument of the callout function is a pointer to a substitute callout
+block structure, which contains the following fields, not necessarily in this
+order:
+
+ uint32_t version;
+ uint32_t subscount;
+ PCRE2_SPTR input;
+ PCRE2_SPTR output;
+ PCRE2_SIZE *ovector;
+ uint32_t oveccount;
+ PCRE2_SIZE output_offsets[2];
+
+The version field contains the version number of the block format. The
+current version is 0. The version number will increase in future if more fields
+are added, but the intention is never to remove any of the existing fields.
+
+
+The subscount field is the number of the current match. It is 1 for the
+first callout, 2 for the second, and so on. The input and output
+pointers are copies of the values passed to pcre2_substitute().
+
+
+The ovector field points to the ovector, which contains the result of the
+most recent match. The oveccount field contains the number of pairs that
+are set in the ovector, and is always greater than zero.
+
+
+The output_offsets vector contains the offsets of the replacement in the
+output string. This has already been processed for dollar and (if requested)
+backslash substitutions as described above.
+
+
+The second argument of the callout function is the value passed as
+callout_data when the function was registered. The value returned by the
+callout function is interpreted as follows:
+
+
+If the value is zero, the replacement is accepted, and, if
+PCRE2_SUBSTITUTE_GLOBAL is set, processing continues with a search for the next
+match. If the value is not zero, the current replacement is not accepted. If
+the value is greater than zero, processing continues when
+PCRE2_SUBSTITUTE_GLOBAL is set. Otherwise (the value is less than zero or
+PCRE2_SUBSTITUTE_GLOBAL is not set), the rest of the input is copied to the
+output and the call to pcre2_substitute() exits, returning the number of
+matches so far.
+
+
+Substitution case callouts
+
+
+int pcre2_set_substitute_case_callout(pcre2_match_context *mcontext,
+ PCRE2_SIZE (*callout_function)(PCRE2_SPTR, PCRE2_SIZE,
+ PCRE2_UCHAR *, PCRE2_SIZE,
+ int, void *),
+ void *callout_data);
+
+
+The pcre2_set_substitute_case_callout() function can be used to specify
+a callout function for pcre2_substitute() to use when performing case
+transformations. This does not affect any case insensitivity behaviour when
+performing a match, but only the user-visible transformations performed when
+processing a substitution such as:
+
+ pcre2_substitute(..., "\\U$1", ...)
+
+
+
+The default case transformations applied by PCRE2 are reasonably complete, and,
+in UTF or UCP mode, perform the simple locale-invariant case transformations as
+specified by Unicode. This is suitable for the internal (invisible)
+case-equivalence procedures used during pattern matching, but an application
+may wish to use more sophisticated locale-aware processing for the user-visible
+substitution transformations.
+
+
+One example implementation of the callout_function using the ICU
+library would be:
+
+
+
+ PCRE2_SIZE
+ icu_case_callout(
+ PCRE2_SPTR input, PCRE2_SIZE input_len,
+ PCRE2_UCHAR *output, PCRE2_SIZE output_cap,
+ int to_case, void *data_ptr)
+ {
+ UErrorCode err = U_ZERO_ERROR;
+ int32_t r = to_case == PCRE2_SUBSTITUTE_CASE_LOWER
+ ? u_strToLower(output, output_cap, input, input_len, NULL, &err)
+ : to_case == PCRE2_SUBSTITUTE_CASE_UPPER
+ ? u_strToUpper(output, output_cap, input, input_len, NULL, &err)
+ : u_strToTitle(output, output_cap, input, input_len, &first_char_only,
+ NULL, &err);
+ if (U_FAILURE(err)) return (~(PCRE2_SIZE)0);
+ return r;
+ }
+
+
+
+The first and second arguments of the case callout function are the Unicode
+string to transform.
+
+
+The third and fourth arguments are the output buffer and its capacity.
+
+
+The fifth is one of the constants PCRE2_SUBSTITUTE_CASE_LOWER,
+PCRE2_SUBSTITUTE_CASE_UPPER, or PCRE2_SUBSTITUTE_CASE_TITLE_FIRST.
+PCRE2_SUBSTITUTE_CASE_LOWER and PCRE2_SUBSTITUTE_CASE_UPPER are passed to the
+callout to indicate that the case of the entire callout input should be
+case-transformed. PCRE2_SUBSTITUTE_CASE_TITLE_FIRST is passed to indicate that
+only the first character or glyph should be transformed to Unicode titlecase
+and the rest to Unicode lowercase (note that titlecasing sometimes uses Unicode
+properties to titlecase each word in a string; but PCRE2 is requesting that only
+the single leading character is to be titlecased).
+
+
+The sixth argument is the callout_data supplied to
+pcre2_set_substitute_case_callout().
+
+
+The resulting string in the destination buffer may be larger or smaller than the
+input, if the casing rules merge or split characters. The return value is the
+length required for the output string. If a buffer of sufficient size was
+provided to the callout, then the result must be written to the buffer and the
+number of code units returned. If the result does not fit in the provided
+buffer, then the required capacity must be returned and PCRE2 will not make use
+of the output buffer. PCRE2 provides input and output buffers which overlap, so
+the callout must support this by suitable internal buffering.
+
+
+Alternatively, if the callout wishes to indicate an error, then it may return
+(~(PCRE2_SIZE)0). In this case pcre2_substitute() will immediately fail with
+error PCRE2_ERROR_REPLACECASE.
+
+
+When a case callout is combined with the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+option, there are situations when pcre2_substitute() will return an
+underestimate of the required buffer size. If you call pcre2_substitute() once
+with PCRE2_SUBSTITUTE_OVERFLOW_LENGTH, and the input buffer is too small for
+the replacement string to be constructed, then instead of calling the case
+callout, pcre2_substitute() will make an estimate of the required buffer size.
+The second call should also pass PCRE2_SUBSTITUTE_OVERFLOW_LENGTH, because that
+second call is not guaranteed to succeed either, if the case callout requires
+more buffer space than expected. The caller must make repeated attempts in a
+loop.
+
+
+
+int pcre2_substring_nametable_scan(const pcre2_code *code,
+ PCRE2_SPTR name, PCRE2_SPTR *first, PCRE2_SPTR *last);
+
+
+When a pattern is compiled with the PCRE2_DUPNAMES option, names for capture
+groups are not required to be unique. Duplicate names are always allowed for
+groups with the same number, created by using the (?| feature. Indeed, if such
+groups are named, they are required to use the same names.
+
+
+Normally, patterns that use duplicate names are such that in any one match,
+only one of each set of identically-named groups participates. An example is
+shown in the
+pcre2pattern
+documentation.
+
+
+When duplicates are present, pcre2_substring_copy_byname() and
+pcre2_substring_get_byname() return the first substring corresponding to
+the given name that is set. Only if none are set is PCRE2_ERROR_UNSET is
+returned. The pcre2_substring_number_from_name() function returns the
+error PCRE2_ERROR_NOUNIQUESUBSTRING when there are duplicate names.
+
+
+If you want to get full details of all captured substrings for a given name,
+you must use the pcre2_substring_nametable_scan() function. The first
+argument is the compiled pattern, and the second is the name. If the third and
+fourth arguments are NULL, the function returns a group number for a unique
+name, or PCRE2_ERROR_NOUNIQUESUBSTRING otherwise.
+
+
+When the third and fourth arguments are not NULL, they must be pointers to
+variables that are updated by the function. After it has run, they point to the
+first and last entries in the name-to-number table for the given name, and the
+function returns the length of each entry in code units. In both cases,
+PCRE2_ERROR_NOSUBSTRING is returned if there are no entries for the given name.
+
+
+The format of the name table is described
+above
+in the section entitled Information about a pattern. Given all the
+relevant entries for the name, you can extract each of their numbers, and hence
+the captured data.
+
+
+
+The traditional matching function uses a similar algorithm to Perl, which stops
+when it finds the first match at a given point in the subject. If you want to
+find all possible matches, or the longest possible match at a given position,
+consider using the alternative matching function (see below) instead. If you
+cannot use the alternative function, you can kludge it up by making use of the
+callout facility, which is described in the
+pcre2callout
+documentation.
+
+
+What you have to do is to insert a callout right at the end of the pattern.
+When your callout function is called, extract and save the current matched
+substring. Then return 1, which forces pcre2_match() to backtrack and try
+other alternatives. Ultimately, when it runs out of matches,
+pcre2_match() will yield PCRE2_ERROR_NOMATCH.
+
+
+
+int pcre2_dfa_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext,
+ int *workspace, PCRE2_SIZE wscount);
+
+
+The function pcre2_dfa_match() is called to match a subject string
+against a compiled pattern, using a matching algorithm that scans the subject
+string just once (not counting lookaround assertions), and does not backtrack
+(except when processing lookaround assertions). This has different
+characteristics to the normal algorithm, and is not compatible with Perl. Some
+of the features of PCRE2 patterns are not supported. Nevertheless, there are
+times when this kind of matching can be useful. For a discussion of the two
+matching algorithms, and a list of features that pcre2_dfa_match() does
+not support, see the
+pcre2matching
+documentation.
+
+
+The arguments for the pcre2_dfa_match() function are the same as for
+pcre2_match(), plus two extras. The ovector within the match data block
+is used in a different way, and this is described below. The other common
+arguments are used in the same way as for pcre2_match(), so their
+description is not repeated here.
+
+
+The two additional arguments provide workspace for the function. The workspace
+vector should contain at least 20 elements. It is used for keeping track of
+multiple paths through the pattern tree. More workspace is needed for patterns
+and subjects where there are a lot of potential matches.
+
+
+Here is an example of a simple call to pcre2_dfa_match():
+
+ int wspace[20];
+ pcre2_match_data *md = pcre2_match_data_create(4, NULL);
+ int rc = pcre2_dfa_match(
+ re, /* result of pcre2_compile() */
+ "some string", /* the subject string */
+ 11, /* the length of the subject string */
+ 0, /* start at offset 0 in the subject */
+ 0, /* default options */
+ md, /* the match data block */
+ NULL, /* a match context; NULL means use defaults */
+ wspace, /* working space vector */
+ 20); /* number of elements (NOT size in bytes) */
+
+
+
+Option bits for pcre2_dfa_match()
+
+
+The unused bits of the options argument for pcre2_dfa_match() must
+be zero. The only bits that may be set are PCRE2_ANCHORED,
+PCRE2_COPY_MATCHED_SUBJECT, PCRE2_ENDANCHORED, PCRE2_NOTBOL, PCRE2_NOTEOL,
+PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD,
+PCRE2_PARTIAL_SOFT, PCRE2_DFA_SHORTEST, and PCRE2_DFA_RESTART. All but the last
+four of these are exactly the same as for pcre2_match(), so their
+description is not repeated here.
+
+ PCRE2_PARTIAL_HARD
+ PCRE2_PARTIAL_SOFT
+
+These have the same general effect as they do for pcre2_match(), but the
+details are slightly different. When PCRE2_PARTIAL_HARD is set for
+pcre2_dfa_match(), it returns PCRE2_ERROR_PARTIAL if the end of the
+subject is reached and there is still at least one matching possibility that
+requires additional characters. This happens even if some complete matches have
+already been found. When PCRE2_PARTIAL_SOFT is set, the return code
+PCRE2_ERROR_NOMATCH is converted into PCRE2_ERROR_PARTIAL if the end of the
+subject is reached, there have been no complete matches, but there is still at
+least one matching possibility. The portion of the string that was inspected
+when the longest partial match was found is set as the first matching string in
+both cases. There is a more detailed discussion of partial and multi-segment
+matching, with examples, in the
+pcre2partial
+documentation.
+
+ PCRE2_DFA_SHORTEST
+
+Setting the PCRE2_DFA_SHORTEST option causes the matching algorithm to stop as
+soon as it has found one match. Because of the way the alternative algorithm
+works, this is necessarily the shortest possible match at the first possible
+matching point in the subject string.
+
+ PCRE2_DFA_RESTART
+
+When pcre2_dfa_match() returns a partial match, it is possible to call it
+again, with additional subject characters, and have it continue with the same
+match. The PCRE2_DFA_RESTART option requests this action; when it is set, the
+workspace and wscount options must reference the same vector as
+before because data about the match so far is left in them after a partial
+match. There is more discussion of this facility in the
+pcre2partial
+documentation.
+
+
+Successful returns from pcre2_dfa_match()
+
+
+When pcre2_dfa_match() succeeds, it may have matched more than one
+substring in the subject. Note, however, that all the matches from one run of
+the function start at the same point in the subject. The shorter matches are
+all initial substrings of the longer matches. For example, if the pattern
+
+ <.*>
+
+is matched against the string
+
+ This is <something> <something else> <something further> no more
+
+the three matched strings are
+
+ <something> <something else> <something further>
+ <something> <something else>
+ <something>
+
+On success, the yield of the function is a number greater than zero, which is
+the number of matched substrings. The offsets of the substrings are returned in
+the ovector, and can be extracted by number in the same way as for
+pcre2_match(), but the numbers bear no relation to any capture groups
+that may exist in the pattern, because DFA matching does not support capturing.
+
+
+Calls to the convenience functions that extract substrings by name
+return the error PCRE2_ERROR_DFA_UFUNC (unsupported function) if used after a
+DFA match. The convenience functions that extract substrings by number never
+return PCRE2_ERROR_NOSUBSTRING.
+
+
+The matched strings are stored in the ovector in reverse order of length; that
+is, the longest matching string is first. If there were too many matches to fit
+into the ovector, the yield of the function is zero, and the vector is filled
+with the longest matches.
+
+
+NOTE: PCRE2's "auto-possessification" optimization usually applies to character
+repeats at the end of a pattern (as well as internally). For example, the
+pattern "a\d+" is compiled as if it were "a\d++". For DFA matching, this
+means that only one possible match is found. If you really do want multiple
+matches in such cases, either use an ungreedy repeat such as "a\d+?" or set
+the PCRE2_NO_AUTO_POSSESS option when compiling.
+
+
+Error returns from pcre2_dfa_match()
+
+
+The pcre2_dfa_match() function returns a negative number when it fails.
+Many of the errors are the same as for pcre2_match(), as described
+above.
+There are in addition the following errors that are specific to
+pcre2_dfa_match():
+
+ PCRE2_ERROR_DFA_UITEM
+
+This return is given if pcre2_dfa_match() encounters an item in the
+pattern that it does not support, for instance, the use of \C in a UTF mode or
+a backreference.
+
+ PCRE2_ERROR_DFA_UCOND
+
+This return is given if pcre2_dfa_match() encounters a condition item
+that uses a backreference for the condition, or a test for recursion in a
+specific capture group. These are not supported.
+
+ PCRE2_ERROR_DFA_UINVALID_UTF
+
+This return is given if pcre2_dfa_match() is called for a pattern that
+was compiled with PCRE2_MATCH_INVALID_UTF. This is not supported for DFA
+matching.
+
+ PCRE2_ERROR_DFA_WSSIZE
+
+This return is given if pcre2_dfa_match() runs out of space in the
+workspace vector.
+
+ PCRE2_ERROR_DFA_RECURSE
+
+When a recursion or subroutine call is processed, the matching function calls
+itself recursively, using private memory for the ovector and workspace.
+This error is given if the internal ovector is not large enough. This should be
+extremely rare, as a vector of size 1000 is used.
+
+ PCRE2_ERROR_DFA_BADRESTART
+
+When pcre2_dfa_match() is called with the PCRE2_DFA_RESTART option,
+some plausibility checks are made on the contents of the workspace, which
+should contain data about the previous partial match. If any of these checks
+fail, this error is given.
+
+
+
+pcre2build(3), pcre2callout(3), pcre2demo(3),
+pcre2matching(3), pcre2partial(3), pcre2posix(3),
+pcre2sample(3), pcre2unicode(3).
+
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+
+Last updated: 08 December 2025
+
+Copyright © 1997-2024 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2build.html b/doc/html/pcre2build.html
new file mode 100644
index 0000000..603e9ab
--- /dev/null
+++ b/doc/html/pcre2build.html
@@ -0,0 +1,671 @@
+
+
+pcre2build specification
+
+
+pcre2build man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+PCRE2 is distributed with a configure script that can be used to build
+the library in Unix-like environments using the Autotools applications. Also in
+the distribution are files to support building using CMake instead of
+configure. The text file
+README
+contains general information about building with Autotools (some of which is
+repeated below), and also has some comments about building on various operating
+systems. The files in the vms directory support building under OpenVMS.
+There is a lot more information about building PCRE2 without using
+Autotools (including information about using CMake and building "by
+hand") in the text file called
+NON-AUTOTOOLS-BUILD.
+You should consult this file as well as the
+README
+file if you are building in a non-Unix-like environment.
+
+
+
+The rest of this document describes the optional features of PCRE2 that can be
+selected when the library is compiled. It assumes use of the configure
+script, where the optional features are selected or deselected by providing
+options to configure before running the make command. However, the
+same options can be selected in both Unix-like and non-Unix-like environments
+if you are using CMake instead of configure to build PCRE2.
+
+
+If you are not using Autotools or CMake, option selection can be done by
+editing the config.h file, or by passing parameter settings to the
+compiler, as described in
+NON-AUTOTOOLS-BUILD.
+
+
+The complete list of options for configure (which includes the standard
+ones such as the selection of the installation directory) can be obtained by
+running
+
+ ./configure --help
+
+The following sections include descriptions of "on/off" options whose names
+begin with --enable or --disable. Because of the way that configure
+works, --enable and --disable always come in pairs, so the complementary option
+always exists as well, but as it specifies the default, it is not described.
+Options that specify values have names that start with --with. At the end of a
+configure run, a summary of the configuration is output.
+
+
+
+By default, a library called libpcre2-8 is built, containing functions
+that take string arguments contained in arrays of bytes, interpreted either as
+single-byte characters, or UTF-8 strings. You can also build two other
+libraries, called libpcre2-16 and libpcre2-32, which process
+strings that are contained in arrays of 16-bit and 32-bit code units,
+respectively. These can be interpreted either as single-unit characters or
+UTF-16/UTF-32 strings. To build these additional libraries, add one or both of
+the following to the configure command:
+
+ --enable-pcre2-16
+ --enable-pcre2-32
+
+If you do not want the 8-bit library, add
+
+ --disable-pcre2-8
+
+as well. At least one of the three libraries must be built. Note that the POSIX
+wrapper is for the 8-bit library only, and that pcre2grep is an 8-bit
+program. Neither of these are built if you select only the 16-bit or 32-bit
+libraries.
+
+
+
+The Autotools PCRE2 building process uses libtool to build both shared
+and static libraries by default. You can suppress an unwanted library by adding
+one of
+
+ --disable-shared
+ --disable-static
+
+to the configure command. Setting --disable-shared ensures that PCRE2
+libraries are built as static libraries. The binaries that are then created as
+part of the build process (for example, pcre2test and pcre2grep)
+are linked statically with one or more PCRE2 libraries, but may also be
+dynamically linked with other libraries such as libc. If you want these
+binaries to be fully statically linked, you can set LDFLAGS like this:
+
+
+LDFLAGS=--static ./configure --disable-shared
+
+
+Note the two hyphens in --static. Of course, this works only if static versions
+of all the relevant libraries are available for linking.
+
+
+
+By default, PCRE2 is built with support for Unicode and UTF character strings.
+To build it without Unicode support, add
+
+ --disable-unicode
+
+to the configure command. This setting applies to all three libraries. It
+is not possible to build one library with Unicode support and another without
+in the same configuration.
+
+
+Of itself, Unicode support does not make PCRE2 treat strings as UTF-8, UTF-16
+or UTF-32. To do that, applications that use the library can set the PCRE2_UTF
+option when they call pcre2_compile() to compile a pattern.
+Alternatively, patterns may be started with (*UTF) unless the application has
+locked this out by setting PCRE2_NEVER_UTF.
+
+
+UTF support allows the libraries to process character code points up to
+0x10ffff in the strings that they handle. Unicode support also gives access to
+the Unicode properties of characters, using pattern escapes such as \P, \p,
+and \X. Only the general category properties such as Lu and Nd,
+script names, and some bi-directional and binary properties are supported.
+Details are given in the
+pcre2pattern
+documentation.
+
+
+Pattern escapes such as \d and \w do not by default make use of Unicode
+properties. The application can request that they do by setting the PCRE2_UCP
+option. Unless the application has set PCRE2_NEVER_UCP, a pattern may also
+request this by starting with (*UCP).
+
+
+
+The \C escape sequence, which matches a single code unit, even in a UTF mode,
+can cause unpredictable behaviour because it may leave the current matching
+point in the middle of a multi-code-unit character. The application can lock
+it out by setting the PCRE2_NEVER_BACKSLASH_C option when calling
+pcre2_compile(). There is also a build-time option
+
+ --enable-never-backslash-C
+
+(note the upper case C) which locks out the use of \C entirely.
+
+
+
+Just-in-time (JIT) compiler support is included in the build by specifying
+
+ --enable-jit
+
+This support is available only for certain hardware architectures. If this
+option is set for an unsupported architecture, a building error occurs.
+If in doubt, use
+
+ --enable-jit=auto
+
+which enables JIT only if the current hardware is supported. You can check
+if JIT is enabled in the configuration summary that is output at the end of a
+configure run. If you are enabling JIT under SELinux you may also want to
+add
+
+ --enable-jit-sealloc
+
+which enables the use of an execmem allocator in JIT that is compatible with
+SELinux. This has no effect if JIT is not enabled. See the
+pcre2jit
+documentation for a discussion of JIT usage. When JIT support is enabled,
+pcre2grep automatically makes use of it, unless you add
+
+ --disable-pcre2grep-jit
+
+to the configure command.
+
+
+
+By default, PCRE2 interprets the linefeed (LF) character as indicating the end
+of a line. This is the normal newline character on Unix-like systems. You can
+compile PCRE2 to use carriage return (CR) instead, by adding
+
+ --enable-newline-is-cr
+
+to the configure command. There is also an --enable-newline-is-lf option,
+which explicitly specifies linefeed as the newline character.
+
+
+Alternatively, you can specify that line endings are to be indicated by the
+two-character sequence CRLF (CR immediately followed by LF). If you want this,
+add
+
+ --enable-newline-is-crlf
+
+to the configure command. There is a fourth option, specified by
+
+ --enable-newline-is-anycrlf
+
+which causes PCRE2 to recognize any of the three sequences CR, LF, or CRLF as
+indicating a line ending. A fifth option, specified by
+
+ --enable-newline-is-any
+
+causes PCRE2 to recognize any Unicode newline sequence. The Unicode newline
+sequences are the three just mentioned, plus the single characters VT (vertical
+tab, U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line
+separator, U+2028), and PS (paragraph separator, U+2029). The final option is
+
+ --enable-newline-is-nul
+
+which causes NUL (binary zero) to be set as the default line-ending character.
+
+
+Whatever default line ending convention is selected when PCRE2 is built can be
+overridden by applications that use the library. At build time it is
+recommended to use the standard for your operating system.
+
+
+
+By default, the sequence \R in a pattern matches any Unicode newline sequence,
+independently of what has been selected as the line ending sequence. If you
+specify
+
+ --enable-bsr-anycrlf
+
+the default is changed so that \R matches only CR, LF, or CRLF. Whatever is
+selected when PCRE2 is built can be overridden by applications that use the
+library.
+
+
+
+Within a compiled pattern, offset values are used to point from one part to
+another (for example, from an opening parenthesis to an alternation
+metacharacter). By default, in the 8-bit and 16-bit libraries, two-byte values
+are used for these offsets, leading to a maximum size for a compiled pattern of
+around 64 thousand code units. This is sufficient to handle all but the most
+gigantic patterns. Nevertheless, some people do want to process truly enormous
+patterns, so it is possible to compile PCRE2 to use three-byte or four-byte
+offsets by adding a setting such as
+
+ --with-link-size=3
+
+to the configure command. The value given must be 2, 3, or 4. For the
+16-bit library, a value of 3 is rounded up to 4. In these libraries, using
+longer offsets slows down the operation of PCRE2 because it has to load
+additional data when handling them. For the 32-bit library the value is always
+4 and cannot be overridden; the value of --with-link-size is ignored.
+
+
+
+The pcre2_match() function increments a counter each time it goes round
+its main loop. Putting a limit on this counter controls the amount of computing
+resource used by a single call to pcre2_match(). The limit can be changed
+at run time, as described in the
+pcre2api
+documentation. The default is 10 million, but this can be changed by adding a
+setting such as
+
+ --with-match-limit=500000
+
+to the configure command. This setting also applies to the
+pcre2_dfa_match() matching function, and to JIT matching (though the
+counting is done differently).
+
+
+The pcre2_match() function uses heap memory to record backtracking
+points. The more nested backtracking points there are (that is, the deeper the
+search tree), the more memory is needed. There is an upper limit, specified in
+kibibytes (units of 1024 bytes). This limit can be changed at run time, as
+described in the
+pcre2api
+documentation. The default limit (in effect unlimited) is 20 million. You can
+change this by a setting such as
+
+ --with-heap-limit=500
+
+which limits the amount of heap to 500 KiB. This limit applies only to
+interpretive matching in pcre2_match() and pcre2_dfa_match(), which
+may also use the heap for internal workspace when processing complicated
+patterns. This limit does not apply when JIT (which has its own memory
+arrangements) is used.
+
+
+You can also explicitly limit the depth of nested backtracking in the
+pcre2_match() interpreter. This limit defaults to the value that is set
+for --with-match-limit. You can set a lower default limit by adding, for
+example,
+
+ --with-match-limit-depth=10000
+
+to the configure command. This value can be overridden at run time. This
+depth limit indirectly limits the amount of heap memory that is used, but
+because the size of each backtracking "frame" depends on the number of
+capturing parentheses in a pattern, the amount of heap that is used before the
+limit is reached varies from pattern to pattern. This limit was more useful in
+versions before 10.30, where function recursion was used for backtracking.
+
+
+As well as applying to pcre2_match(), the depth limit also controls
+the depth of recursive function calls in pcre2_dfa_match(). These are
+used for lookaround assertions, atomic groups, and recursion within patterns.
+The limit does not apply to JIT matching.
+
+
+
+Lookbehind assertions in which one or more branches can match a variable number
+of characters are supported only if there is a maximum matching length for each
+top-level branch. There is a limit to this maximum that defaults to 255
+characters. You can alter this default by a setting such as
+
+ --with-max-varlookbehind=100
+
+The limit can be changed at runtime by calling
+pcre2_set_max_varlookbehind(). Lookbehind assertions in which every
+branch matches a fixed number of characters (not necessarily all the same) are
+not constrained by this limit.
+
+
+
+PCRE2 uses fixed tables for processing characters whose code points are less
+than 256. By default, PCRE2 is built with a set of tables that are distributed
+in the file src/pcre2_chartables.c.dist. These tables are for ASCII codes
+only. If you add
+
+ --enable-rebuild-chartables
+
+to the configure command, the distributed tables are no longer used.
+Instead, a program called pcre2_dftables is compiled and run. This
+outputs the source for new set of tables, created in the default locale of your
+C run-time system. This method of replacing the tables does not work if you are
+cross compiling, because pcre2_dftables needs to be run on the local
+host and therefore not compiled with the cross compiler.
+
+
+If you need to create alternative tables when cross compiling, you will have to
+do so "by hand". There may also be other reasons for creating tables manually.
+To cause pcre2_dftables to be built on the local host, run a normal
+compiling command, and then run the program with the output file as its
+argument, for example:
+
+ cc src/pcre2_dftables.c -o pcre2_dftables
+ ./pcre2_dftables src/pcre2_chartables.c
+
+This builds the tables in the default locale of the local host. If you want to
+specify a locale, you must use the -L option:
+
+ LC_ALL=fr_FR ./pcre2_dftables -L src/pcre2_chartables.c
+
+You can also specify -b (with or without -L). This causes the tables to be
+written in binary instead of as source code. A set of binary tables can be
+loaded into memory by an application and passed to pcre2_compile() in the
+same way as tables created by calling pcre2_maketables(). The tables are
+just a string of bytes, independent of hardware characteristics such as
+endianness. This means they can be bundled with an application that runs in
+different environments, to ensure consistent behaviour.
+
+
+
+PCRE2 assumes by default that it will run in an environment where the character
+code is ASCII or Unicode, which is a superset of ASCII. This is the case for
+most computer operating systems. PCRE2 can, however, be compiled to run in an
+8-bit EBCDIC environment by adding
+
+ --enable-ebcdic --disable-unicode
+
+to the configure command. You should only use it if you know that you are
+in an EBCDIC environment (for example, an IBM mainframe operating system).
+
+
+This setting implies --enable-rebuild-chartables, in order to ensure that you
+have the correct default character tables for your system's codepage. There is
+an exception when you set --enable-ebcdic-ignoring-compiler (see below), which
+allows using a default set of EBCDIC 1047 character tables rather than forcing
+use of --enable-rebuild-chartables.
+
+
+It is not supported to enable both EBCDIC input and either ASCII or UTF-8/16/32
+in the same build of the library. When PCRE2 is built with EBCDIC support, it
+always operates in EBCDIC, and consequently --enable-unicode and --enable-ebcdic
+are mutually exclusive.
+
+
+The EBCDIC character that corresponds to an ASCII LF is assumed to have the
+value 0x15 by default. However, in some EBCDIC environments, 0x25 is used. In
+such an environment you should use
+
+ --enable-ebcdic-nl25
+
+(which implies --enable-ebcdic). The EBCDIC character for CR has the same value
+as in ASCII, namely, 0x0d. Whichever of 0x15 and 0x25 is not chosen as LF
+is made to correspond to the Unicode NEL character (which, in Unicode, is 0x85).
+
+
+The options that select newline behaviour, such as --enable-newline-is-cr,
+and equivalent run-time options, refer to these character values in an EBCDIC
+environment.
+
+
+On systems requiring an EBCDIC build of PCRE2, the compiler should be set to use
+the correct codepage, so that C character literals such as 'z' use the correct
+numeric value for whichever EBCDIC codpage is in use. (PCRE2 cannot support
+multiple EBCDIC codepages dynamically.) However, if this not possible, then you
+can use
+
+ --enable-ebcdic-ignoring-compiler
+
+in order to disregard the compiler's codepage, and instead force PCRE2 to use
+numeric constants corresponding to the EBCDIC 1047 codepage instead. This can be
+used to build (or test) EBCDIC support on an ASCII/UTF-8 system such as Linux.
+
+
+
+By default pcre2grep supports the use of callouts with string arguments
+within the patterns it is matching. There are two kinds: one that generates
+output using local code, and another that calls an external program or script.
+If --disable-pcre2grep-callout-fork is added to the configure command,
+only the first kind of callout is supported; if --disable-pcre2grep-callout is
+used, all callouts are completely ignored. For more details of pcre2grep
+callouts, see the
+pcre2grep
+documentation.
+
+
+
+By default, pcre2grep reads all files as plain text. You can build it so
+that it recognizes files whose names end in .gz or .bz2, and reads
+them with libz or libbz2, respectively, by adding one or both of
+
+ --enable-pcre2grep-libz
+ --enable-pcre2grep-libbz2
+
+to the configure command. These options naturally require that the
+relevant libraries are installed on your system. Configuration will fail if
+they are not.
+
+
+
+pcre2grep uses an internal buffer to hold a "window" on the file it is
+scanning, in order to be able to output "before" and "after" lines when it
+finds a match. The default starting size of the buffer is 20KiB. The buffer
+itself is three times this size, but because of the way it is used for holding
+"before" lines, the longest line that is guaranteed to be processable is the
+notional buffer size. If a longer line is encountered, pcre2grep
+automatically expands the buffer, up to a specified maximum size, whose default
+is 1MiB or the starting size, whichever is the larger. You can change the
+default parameter values by adding, for example,
+
+ --with-pcre2grep-bufsize=51200
+ --with-pcre2grep-max-bufsize=2097152
+
+to the configure command. The caller of pcre2grep can override
+these values by using --buffer-size and --max-buffer-size on the command line.
+
+
+
+If you add one of
+
+ --enable-pcre2test-libreadline
+ --enable-pcre2test-libedit
+
+to the configure command, pcre2test is linked with the
+libreadline orlibedit library, respectively, and when its input is
+from a terminal, it reads it using the readline() function. This provides
+line-editing and history facilities. Note that libreadline is
+GPL-licensed, so if you distribute a binary of pcre2test linked in this
+way, there may be licensing issues. These can be avoided by linking instead
+with libedit, which has a BSD licence.
+
+
+Setting --enable-pcre2test-libreadline causes the -lreadline option to be
+added to the pcre2test build. In many operating environments with a
+system-installed readline library this is sufficient. However, in some
+environments (e.g. if an unmodified distribution version of readline is in
+use), some extra configuration may be necessary. The INSTALL file for
+libreadline says this:
+
+ "Readline uses the termcap functions, but does not link with
+ the termcap or curses library itself, allowing applications
+ which link with readline the to choose an appropriate library."
+
+If your environment has not been set up so that an appropriate library is
+automatically included, you may need to add something like
+
+ LIBS="-lncurses"
+
+immediately before the configure command.
+
+
+
+If you add
+
+ --enable-debug
+
+to the configure command, additional debugging code is included in the
+build. This feature is intended for use by the PCRE2 maintainers.
+
+
+
+If you add
+
+ --enable-valgrind
+
+to the configure command, PCRE2 will use valgrind annotations to mark
+certain memory regions as unaddressable. This allows it to detect invalid
+memory accesses, and is mostly useful for debugging PCRE2 itself.
+
+
+
+If your C compiler is gcc, you can build a version of PCRE2 that can generate a
+code coverage report for its test suite. To enable this, you must install
+lcov version 1.6 or above. Then specify
+
+ --enable-coverage
+
+to the configure command and build PCRE2 in the usual way.
+
+
+Note that using ccache (a caching C compiler) is incompatible with code
+coverage reporting. If you have configured ccache to run automatically
+on your system, you must set the environment variable
+
+ CCACHE_DISABLE=1
+
+before running make to build PCRE2, so that ccache is not used.
+
+
+When --enable-coverage is used, the following addition targets are added to the
+Makefile:
+
+ make coverage
+
+This creates a fresh coverage report for the PCRE2 test suite. It is equivalent
+to running "make coverage-reset", "make coverage-baseline", "make check", and
+then "make coverage-report".
+
+ make coverage-reset
+
+This zeroes the coverage counters, but does nothing else.
+
+ make coverage-baseline
+
+This captures baseline coverage information.
+
+ make coverage-report
+
+This creates the coverage report.
+
+ make coverage-clean-report
+
+This removes the generated coverage report without cleaning the coverage data
+itself.
+
+ make coverage-clean-data
+
+This removes the captured coverage data without removing the coverage files
+created at compile time (*.gcno).
+
+ make coverage-clean
+
+This cleans all coverage data including the generated coverage report. For more
+information about code coverage, see the gcov and lcov
+documentation.
+
+
+
+The C99 standard defines formatting modifiers z and t for size_t and
+ptrdiff_t values, respectively. By default, PCRE2 uses these modifiers in
+environments other than old versions of Microsoft Visual Studio when
+__STDC_VERSION__ is defined and has a value greater than or equal to 199901L
+(indicating support for C99).
+However, there is at least one environment that claims to be C99 but does not
+support these modifiers. If
+
+ --disable-percent-zt
+
+is specified, no use is made of the z or t modifiers. Instead of %td or %zu,
+a suitable format is used depending in the size of long for the platform.
+
+
+
+There is a special option for use by people who want to run fuzzing tests on
+PCRE2:
+
+ --enable-fuzz-support
+
+At present this applies only to the 8-bit library. If set, it causes an extra
+library called libpcre2-fuzzsupport.a to be built, but not installed. This
+contains a single function called LLVMFuzzerTestOneInput() whose arguments are
+a pointer to a string and the length of the string. When called, this function
+tries to compile the string as a pattern, and if that succeeds, to match it.
+This is done both with no options and with some random options bits that are
+generated from the string.
+
+
+Setting --enable-fuzz-support also causes a binary called pcre2fuzzcheck
+to be created. This is normally run under valgrind or used when PCRE2 is
+compiled with address sanitizing enabled. It calls the fuzzing function and
+outputs information about what it is doing. The input strings are specified by
+arguments: if an argument starts with "=" the rest of it is a literal input
+string. Otherwise, it is assumed to be a file name, and the contents of the
+file are the test string.
+
+
+
+In versions of PCRE2 prior to 10.30, there were two ways of handling
+backtracking in the pcre2_match() function. The default was to use the
+system stack, but if
+
+ --disable-stack-for-recursion
+
+was set, memory on the heap was used. From release 10.30 onwards this has
+changed (the stack is no longer used) and this option now does nothing except
+give a warning.
+
+
+
+pcre2api(3), pcre2-config(3).
+
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+
+Last updated: 17 October 2025
+
+Copyright © 1997-2024 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2callout.html b/doc/html/pcre2callout.html
new file mode 100644
index 0000000..62885a5
--- /dev/null
+++ b/doc/html/pcre2callout.html
@@ -0,0 +1,480 @@
+
+
+pcre2callout specification
+
+
+pcre2callout man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+#include <pcre2.h>
+
+
+int (*pcre2_callout)(pcre2_callout_block *, void *);
+
+
+int pcre2_callout_enumerate(const pcre2_code *code,
+ int (*callback)(pcre2_callout_enumerate_block *, void *),
+ void *user_data);
+
+
+
+PCRE2 provides a feature called "callout", which is a means of temporarily
+passing control to the caller of PCRE2 in the middle of pattern matching. The
+caller of PCRE2 provides an external function by putting its entry point in
+a match context (see pcre2_set_callout() in the
+pcre2api
+documentation).
+
+
+When using the pcre2_substitute() function, an additional callout feature
+is available. This does a callout after each change to the subject string and
+is described in the
+pcre2api
+documentation; the rest of this document is concerned with callouts during
+pattern matching.
+
+
+Within a regular expression, (?C<arg>) indicates a point at which the external
+function is to be called. Different callout points can be identified by putting
+a number less than 256 after the letter C. The default value is zero.
+Alternatively, the argument may be a delimited string. The starting delimiter
+must be one of ` ' " ^ % # $ { and the ending delimiter is the same as the
+start, except for {, where the ending delimiter is }. If the ending delimiter
+is needed within the string, it must be doubled. For example, this pattern has
+two callout points:
+
+ (?C1)abc(?C"some ""arbitrary"" text")def
+
+If the PCRE2_AUTO_CALLOUT option bit is set when a pattern is compiled, PCRE2
+automatically inserts callouts, all with number 255, before each item in the
+pattern except for immediately before or after an explicit callout. For
+example, if PCRE2_AUTO_CALLOUT is used with the pattern
+
+ A(?C3)B
+
+it is processed as if it were
+
+ (?C255)A(?C3)B(?C255)
+
+Here is a more complicated example:
+
+ A(\d{2}|--)
+
+With PCRE2_AUTO_CALLOUT, this pattern is processed as if it were
+
+ (?C255)A(?C255)((?C255)\d{2}(?C255)|(?C255)-(?C255)-(?C255))(?C255)
+
+Notice that there is a callout before and after each parenthesis and
+alternation bar. If the pattern contains a conditional group whose condition is
+an assertion, an automatic callout is inserted immediately before the
+condition. Such a callout may also be inserted explicitly, for example:
+
+ (?(?C9)(?=a)ab|de) (?(?C%text%)(?!=d)ab|de)
+
+This applies only to assertion conditions (because they are themselves
+independent groups).
+
+
+Callouts can be useful for tracking the progress of pattern matching. The
+pcre2test
+program has a pattern qualifier (/auto_callout) that sets automatic callouts.
+When any callouts are present, the output from pcre2test indicates how
+the pattern is being matched. This is useful information when you are trying to
+optimize the performance of a particular pattern.
+
+
+
+You should be aware that, because of optimizations in the way PCRE2 compiles
+and matches patterns, callouts sometimes do not happen exactly as you might
+expect.
+
+
+Auto-possessification
+
+
+At compile time, PCRE2 "auto-possessifies" repeated items when it knows that
+what follows cannot be part of the repeat. For example, a+[bc] is compiled as
+if it were a++[bc]. The pcre2test output when this pattern is compiled
+with PCRE2_ANCHORED and PCRE2_AUTO_CALLOUT and then applied to the string
+"aaaa" is:
+
+ --->aaaa
+ +0 ^ a+
+ +2 ^ ^ [bc]
+ No match
+
+This indicates that when matching [bc] fails, there is no backtracking into a+
+(because it is being treated as a++) and therefore the callouts that would be
+taken for the backtracks do not occur. You can disable the auto-possessify
+feature by passing PCRE2_NO_AUTO_POSSESS to pcre2_compile(), or starting
+the pattern with (*NO_AUTO_POSSESS). In this case, the output changes to this:
+
+ --->aaaa
+ +0 ^ a+
+ +2 ^ ^ [bc]
+ +2 ^ ^ [bc]
+ +2 ^ ^ [bc]
+ +2 ^^ [bc]
+ No match
+
+This time, when matching [bc] fails, the matcher backtracks into a+ and tries
+again, repeatedly, until a+ itself fails.
+
+
+Automatic .* anchoring
+
+
+By default, an optimization is applied when .* is the first significant item in
+a pattern. If PCRE2_DOTALL is set, so that the dot can match any character, the
+pattern is automatically anchored. If PCRE2_DOTALL is not set, a match can
+start only after an internal newline or at the beginning of the subject, and
+pcre2_compile() remembers this. If a pattern has more than one top-level
+branch, automatic anchoring occurs if all branches are anchorable.
+
+
+This optimization is disabled, however, if .* is in an atomic group or if there
+is a backreference to the capture group in which it appears. It is also
+disabled if the pattern contains (*PRUNE) or (*SKIP). However, the presence of
+callouts does not affect it.
+
+
+For example, if the pattern .*\d is compiled with PCRE2_AUTO_CALLOUT and
+applied to the string "aa", the pcre2test output is:
+
+ --->aa
+ +0 ^ .*
+ +2 ^ ^ \d
+ +2 ^^ \d
+ +2 ^ \d
+ No match
+
+This shows that all match attempts start at the beginning of the subject. In
+other words, the pattern is anchored. You can disable this optimization by
+passing PCRE2_NO_DOTSTAR_ANCHOR to pcre2_compile(), or starting the
+pattern with (*NO_DOTSTAR_ANCHOR). In this case, the output changes to:
+
+ --->aa
+ +0 ^ .*
+ +2 ^ ^ \d
+ +2 ^^ \d
+ +2 ^ \d
+ +0 ^ .*
+ +2 ^^ \d
+ +2 ^ \d
+ No match
+
+This shows more match attempts, starting at the second subject character.
+Another optimization, described in the next section, means that there is no
+subsequent attempt to match with an empty subject.
+
+
+Other optimizations
+
+
+Other optimizations that provide fast "no match" results also affect callouts.
+For example, if the pattern is
+
+ ab(?C4)cd
+
+PCRE2 knows that any matching string must contain the letter "d". If the
+subject string is "abyz", the lack of "d" means that matching doesn't ever
+start, and the callout is never reached. However, with "abyd", though the
+result is still no match, the callout is obeyed.
+
+
+For most patterns PCRE2 also knows the minimum length of a matching string, and
+will immediately give a "no match" return without actually running a match if
+the subject is not long enough, or, for unanchored patterns, if it has been
+scanned far enough.
+
+
+You can disable these optimizations by passing the PCRE2_NO_START_OPTIMIZE
+option to pcre2_compile(), or by starting the pattern with
+(*NO_START_OPT). This slows down the matching process, but does ensure that
+callouts such as the example above are obeyed.
+
+
+
+During matching, when PCRE2 reaches a callout point, if an external function is
+provided in the match context, it is called. This applies to both normal,
+DFA, and JIT matching. The first argument to the callout function is a pointer
+to a pcre2_callout block. The second argument is the void * callout data
+that was supplied when the callout was set up by calling
+pcre2_set_callout() (see the
+pcre2api
+documentation). The callout block structure contains the following fields, not
+necessarily in this order:
+
+ uint32_t version;
+ uint32_t callout_number;
+ uint32_t capture_top;
+ uint32_t capture_last;
+ uint32_t callout_flags;
+ PCRE2_SIZE *offset_vector;
+ PCRE2_SPTR mark;
+ PCRE2_SPTR subject;
+ PCRE2_SIZE subject_length;
+ PCRE2_SIZE start_match;
+ PCRE2_SIZE current_position;
+ PCRE2_SIZE pattern_position;
+ PCRE2_SIZE next_item_length;
+ PCRE2_SIZE callout_string_offset;
+ PCRE2_SIZE callout_string_length;
+ PCRE2_SPTR callout_string;
+
+The version field contains the version number of the block format. The
+current version is 2; the three callout string fields were added for version 1,
+and the callout_flags field for version 2. If you are writing an
+application that might use an earlier release of PCRE2, you should check the
+version number before accessing any of these fields. The version number will
+increase in future if more fields are added, but the intention is never to
+remove any of the existing fields.
+
+
+Fields for numerical callouts
+
+
+For a numerical callout, callout_string is NULL, and callout_number
+contains the number of the callout, in the range 0-255. This is the number
+that follows (?C for callouts that part of the pattern; it is 255 for
+automatically generated callouts.
+
+
+Fields for string callouts
+
+
+For callouts with string arguments, callout_number is always zero, and
+callout_string points to the string that is contained within the compiled
+pattern. Its length is given by callout_string_length. Duplicated ending
+delimiters that were present in the original pattern string have been turned
+into single characters, but there is no other processing of the callout string
+argument. An additional code unit containing binary zero is present after the
+string, but is not included in the length. The delimiter that was used to start
+the string is also stored within the pattern, immediately before the string
+itself. You can access this delimiter as callout_string[-1] if you need
+it.
+
+
+The callout_string_offset field is the code unit offset to the start of
+the callout argument string within the original pattern string. This is
+provided for the benefit of applications such as script languages that might
+need to report errors in the callout string within the pattern.
+
+
+Fields for all callouts
+
+
+The remaining fields in the callout block are the same for both kinds of
+callout.
+
+
+The offset_vector field is a pointer to a vector of capturing offsets
+(the "ovector"). You may read the elements in this vector, but you must not
+change any of them.
+
+
+For calls to pcre2_match(), the offset_vector field is not (since
+release 10.30) a pointer to the actual ovector that was passed to the matching
+function in the match data block. Instead it points to an internal ovector of a
+size large enough to hold all possible captured substrings in the pattern. Note
+that whenever a recursion or subroutine call within a pattern completes, the
+capturing state is reset to what it was before.
+
+
+The capture_last field contains the number of the most recently captured
+substring, and the capture_top field contains one more than the number of
+the highest numbered captured substring so far. If no substrings have yet been
+captured, the value of capture_last is 0 and the value of
+capture_top is 1. The values of these fields do not always differ by one;
+for example, when the callout in the pattern ((a)(b))(?C2) is taken,
+capture_last is 1 but capture_top is 4.
+
+
+The contents of ovector[2] to ovector[<capture_top>*2-1] can be inspected in
+order to extract substrings that have been matched so far, in the same way as
+extracting substrings after a match has completed. The values in ovector[0] and
+ovector[1] are always PCRE2_UNSET because the match is by definition not
+complete. Substrings that have not been captured but whose numbers are less
+than capture_top also have both of their ovector slots set to
+PCRE2_UNSET.
+
+
+For DFA matching, the offset_vector field points to the ovector that was
+passed to the matching function in the match data block for callouts at the top
+level, but to an internal ovector during the processing of pattern recursions,
+lookarounds, and atomic groups. However, these ovectors hold no useful
+information because pcre2_dfa_match() does not support substring
+capturing. The value of capture_top is always 1 and the value of
+capture_last is always 0 for DFA matching.
+
+
+The subject and subject_length fields contain copies of the values
+that were passed to the matching function.
+
+
+The start_match field normally contains the offset within the subject at
+which the current match attempt started. However, if the escape sequence \K
+has been encountered, this value is changed to reflect the modified starting
+point. If the pattern is not anchored, the callout function may be called
+several times from the same point in the pattern for different starting points
+in the subject.
+
+
+The current_position field contains the offset within the subject of the
+current match pointer.
+
+
+The pattern_position field contains the offset in the pattern string to
+the next item to be matched.
+
+
+The next_item_length field contains the length of the next item to be
+processed in the pattern string. When the callout is at the end of the pattern,
+the length is zero. When the callout precedes an opening parenthesis, the
+length includes meta characters that follow the parenthesis. For example, in a
+callout before an assertion such as (?=ab) the length is 3. For an alternation
+bar or a closing parenthesis, the length is one, unless a closing parenthesis
+is followed by a quantifier, in which case its length is included. (This
+changed in release 10.23. In earlier releases, before an opening parenthesis
+the length was that of the entire group, and before an alternation bar or a
+closing parenthesis the length was zero.)
+
+
+The pattern_position and next_item_length fields are intended to
+help in distinguishing between different automatic callouts, which all have the
+same callout number. However, they are set for all callouts, and are used by
+pcre2test to show the next item to be matched when displaying callout
+information.
+
+
+In callouts from pcre2_match() the mark field contains a pointer to
+the zero-terminated name of the most recently passed (*MARK), (*PRUNE), or
+(*THEN) item in the match, or NULL if no such items have been passed. Instances
+of (*PRUNE) or (*THEN) without a name do not obliterate a previous (*MARK). In
+callouts from the DFA matching function this field always contains NULL.
+
+
+The callout_flags field is always zero in callouts from
+pcre2_dfa_match() or when JIT is being used. When pcre2_match()
+without JIT is used, the following bits may be set:
+
+ PCRE2_CALLOUT_STARTMATCH
+
+This is set for the first callout after the start of matching for each new
+starting position in the subject.
+
+ PCRE2_CALLOUT_BACKTRACK
+
+This is set if there has been a matching backtrack since the previous callout,
+or since the start of matching if this is the first callout from a
+pcre2_match() run.
+
+
+Both bits are set when a backtrack has caused a "bumpalong" to a new starting
+position in the subject. Output from pcre2test does not indicate the
+presence of these bits unless the callout_extra modifier is set.
+
+
+The information in the callout_flags field is provided so that
+applications can track and tell their users how matching with backtracking is
+done. This can be useful when trying to optimize patterns, or just to
+understand how PCRE2 works. There is no support in pcre2_dfa_match()
+because there is no backtracking in DFA matching, and there is no support in
+JIT because JIT is all about maximimizing matching performance. In both these
+cases the callout_flags field is always zero.
+
+
+
+The external callout function returns an integer to PCRE2. If the value is
+zero, matching proceeds as normal. If the value is greater than zero, matching
+fails at the current point, but the testing of other matching possibilities
+goes ahead, just as if a lookahead assertion had failed. If the value is less
+than zero, the match is abandoned, and the matching function returns the
+negative value.
+
+
+Negative values should normally be chosen from the set of PCRE2_ERROR_xxx
+values. In particular, PCRE2_ERROR_NOMATCH forces a standard "no match"
+failure. The error number PCRE2_ERROR_CALLOUT is reserved for use by callout
+functions; it will never be used by PCRE2 itself.
+
+
+
+int pcre2_callout_enumerate(const pcre2_code *code,
+ int (*callback)(pcre2_callout_enumerate_block *, void *),
+ void *user_data);
+
+
+A script language that supports the use of string arguments in callouts might
+like to scan all the callouts in a pattern before running the match. This can
+be done by calling pcre2_callout_enumerate(). The first argument is a
+pointer to a compiled pattern, the second points to a callback function, and
+the third is arbitrary user data. The callback function is called for every
+callout in the pattern in the order in which they appear. Its first argument is
+a pointer to a callout enumeration block, and its second argument is the
+user_data value that was passed to pcre2_callout_enumerate(). The
+data block contains the following fields:
+
+ version Block version number
+ pattern_position Offset to next item in pattern
+ next_item_length Length of next item in pattern
+ callout_number Number for numbered callouts
+ callout_string_offset Offset to string within pattern
+ callout_string_length Length of callout string
+ callout_string Points to callout string or is NULL
+
+The version number is currently 0. It will increase if new fields are ever
+added to the block. The remaining fields are the same as their namesakes in the
+pcre2_callout block that is used for callouts during matching, as
+described
+above.
+
+
+Note that the value of pattern_position is unique for each callout.
+However, if a callout occurs inside a group that is quantified with a non-zero
+minimum or a fixed maximum, the group is replicated inside the compiled
+pattern. For example, a pattern such as /(a){2}/ is compiled as if it were
+/(a)(a)/. This means that the callout will be enumerated more than once, but
+with the same value for pattern_position in each case.
+
+
+The callback function should normally return zero. If it returns a non-zero
+value, scanning the pattern stops, and that value is returned from
+pcre2_callout_enumerate().
+
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+
+Last updated: 26 February 2025
+
+Copyright © 1997-2024 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2compat.html b/doc/html/pcre2compat.html
new file mode 100644
index 0000000..3700abf
--- /dev/null
+++ b/doc/html/pcre2compat.html
@@ -0,0 +1,303 @@
+
+
+pcre2compat specification
+
+
+pcre2compat man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+DIFFERENCES BETWEEN PCRE2 AND PERL
+
+
+This document describes some of the known differences in the ways that PCRE2
+and Perl handle regular expressions. The differences described here are with
+respect to Perl version 5.38.0, but as both Perl and PCRE2 are continually
+changing, the information may at times be out of date.
+
+
+1. When PCRE2_DOTALL (equivalent to Perl's /s qualifier) is not set, the
+behaviour of the '.' metacharacter differs from Perl. In PCRE2, '.' matches the
+next character unless it is the start of a newline sequence. This means that,
+if the newline setting is CR, CRLF, or NUL, '.' will match the code point LF
+(0x0A) in ASCII/Unicode environments, and NL (either 0x15 or 0x25) when using
+EBCDIC. In Perl, '.' appears never to match LF, even when 0x0A is not a newline
+indicator.
+
+
+2. PCRE2 has only a subset of Perl's Unicode support. Details of what it does
+have are given in the
+pcre2unicode
+page.
+
+
+3. Like Perl, PCRE2 allows repeat quantifiers on parenthesized assertions, but
+they do not mean what you might think. For example, (?!a){3} does not assert
+that the next three characters are not "a". It just asserts that the next
+character is not "a" three times (in principle; PCRE2 optimizes this to run the
+assertion just once). Perl allows some repeat quantifiers on other assertions,
+for example, \b* , but these do not seem to have any use. PCRE2 does not allow
+any kind of quantifier on non-lookaround assertions.
+
+
+4. If a braced quantifier such as {1,2} appears where there is nothing to
+repeat (for example, at the start of a branch), PCRE2 raises an error whereas
+Perl treats the quantifier characters as literal. When a braced quantifier
+(...){min,max} has min > max, Perl treats it as an item which fails to match
+any portion of the subject (as no number of repetitions can meet the
+condition), and additionally issues a warning when in warning mode. PCRE2 has
+no warning features, so it gives an error in this case.
+
+
+5. Capture groups that occur inside negative lookaround assertions are counted,
+but their entries in the offsets vector are set only when a negative assertion
+is a condition that has a matching branch (that is, the condition is false).
+Perl may set such capture groups in other circumstances.
+
+
+6. The following Perl escape sequences are not supported: \F, \l, \L, \u,
+\U, and \N when followed by a character name. \N on its own, matching a
+non-newline character, and \N{U+dd..}, matching a Unicode code point, are
+supported. The escapes that modify the case of following letters are
+implemented by Perl's general string-handling and are not part of its pattern
+matching engine. If any of these are encountered by PCRE2, an error is
+generated by default. However, if either of the PCRE2_ALT_BSUX or
+PCRE2_EXTRA_ALT_BSUX options is set, \U and \u are interpreted as ECMAScript
+interprets them.
+
+
+7. The Perl escape sequences \p, \P, and \X are supported only if PCRE2 is
+built with Unicode support (the default). The properties that can be tested
+with \p and \P are limited to the general category properties such as Lu and
+Nd, the derived properties Any and Lc (synonym L&), script names such as Greek
+or Han, Bidi_Class, Bidi_Control, and a few binary properties. Both PCRE2 and
+Perl support the Cs (surrogate) property, but in PCRE2 its use is limited. See
+the
+pcre2pattern
+documentation for details. The long synonyms for property names that Perl
+supports (such as \p{Letter}) are not supported by PCRE2, nor is it permitted
+to prefix any of these properties with "Is".
+
+
+8. PCRE2 supports the \Q...\E escape for quoting substrings. Characters
+in between are treated as literals. However, this is slightly different from
+Perl in that $ and @ are also handled as literals inside the quotes. In Perl,
+they cause variable interpolation (PCRE2 does not have variables). Also, Perl
+does "double-quotish backslash interpolation" on any backslashes between \Q
+and \E which, its documentation says, "may lead to confusing results". PCRE2
+treats a backslash between \Q and \E just like any other character. Note the
+following examples:
+
+ Pattern PCRE2 matches Perl matches
+
+ \Qabc$xyz\E abc$xyz abc followed by the contents of $xyz
+ \Qabc\$xyz\E abc\$xyz abc\$xyz
+ \Qabc\E\$\Qxyz\E abc$xyz abc$xyz
+ \QA\B\E A\B A\B
+ \Q\\E \ \\E
+
+The \Q...\E sequence is recognized both inside and outside character classes
+by both PCRE2 and Perl. Another difference from Perl is that any appearance of
+\Q or \E inside what might otherwise be a quantifier causes PCRE2 not to
+recognize the sequence as a quantifier. Perl recognizes a quantifier if
+(redundantly) either of the numbers is inside \Q...\E, but not if the
+separating comma is. When not recognized as a quantifier a sequence such as
+{\Q1\E,2} is treated as the literal string "{1,2}".
+
+
+9. Fairly obviously, PCRE2 does not support the (?{code}) and (??{code})
+constructions. However, PCRE2 does have a "callout" feature, which allows an
+external function to be called during pattern matching. See the
+pcre2callout
+documentation for details.
+
+
+10. Subroutine calls (whether recursive or not) were treated as atomic groups
+up to PCRE2 release 10.23, but from release 10.30 this changed, and
+backtracking into subroutine calls is now supported, as in Perl.
+
+
+11. In PCRE2, if any of the backtracking control verbs are used in a group that
+is called as a subroutine (whether or not recursively), their effect is
+confined to that group; it does not extend to the surrounding pattern. This is
+not always the case in Perl. In particular, if (*THEN) is present in a group
+that is called as a subroutine, its action is limited to that group, even if
+the group does not contain any | characters. Note that such groups are
+processed as anchored at the point where they are tested. PCRE2 also confines
+all control verbs within atomic assertions, again including (*THEN) in
+assertions with only one branch.
+
+
+12. If a pattern contains more than one backtracking control verb, the first
+one that is backtracked onto acts. For example, in the pattern
+A(*COMMIT)B(*PRUNE)C a failure in B triggers (*COMMIT), but a failure in C
+triggers (*PRUNE). Perl's behaviour is more complex; in many cases it is the
+same as PCRE2, but there are cases where it differs.
+
+
+13. There are some differences that are concerned with the settings of captured
+strings when part of a pattern is repeated. For example, matching "aba" against
+the pattern /^(a(b)?)+$/ in Perl leaves $2 unset, but in PCRE2 it is set to
+"b".
+
+
+14. PCRE2's handling of duplicate capture group numbers and names is not as
+general as Perl's. This is a consequence of the fact the PCRE2 works internally
+just with numbers, using an external table to translate between numbers and
+names. In particular, a pattern such as (?|(?<a>A)|(?<b>B)), where the two
+capture groups have the same number but different names, is not supported, and
+causes an error at compile time. If it were allowed, it would not be possible
+to distinguish which group matched, because both names map to capture group
+number 1. To avoid this confusing situation, an error is given at compile time.
+
+
+15. Perl used to recognize comments in some places that PCRE2 does not, for
+example, between the ( and ? at the start of a group. If the /x modifier is
+set, Perl allowed white space between ( and ? though the latest Perls give an
+error (for a while it was just deprecated). There may still be some cases where
+Perl behaves differently.
+
+
+16. Perl, when in warning mode, gives warnings for character classes such as
+[A-\d] or [a-[:digit:]]. It then treats the hyphens as literals. PCRE2 has no
+warning features, so it gives an error in these cases because they are almost
+certainly user mistakes.
+
+
+17. In PCRE2, until release 10.45, the upper/lower case character properties Lu
+and Ll were not affected when case-independent matching was specified. Perl has
+changed in this respect, and PCRE2 has now changed to match. When caseless
+matching is in force, Lu, Ll, and Lt (title case) are all treated as Lc (cased
+letter).
+
+
+18. From release 5.32.0, Perl locks out the use of \K in lookaround
+assertions. From release 10.38 PCRE2 does the same by default. However, there
+is an option for re-enabling the previous behaviour. When this option is set,
+\K is acted on when it occurs in positive assertions, but is ignored in
+negative assertions.
+
+
+19. PCRE2 provides some extensions to the Perl regular expression facilities.
+Perl 5.10 included new features that were not in earlier versions of Perl, some
+of which (such as named parentheses) were in PCRE2 for some time before. This
+list is with respect to Perl 5.38:
+
+
+(a) If PCRE2_DOLLAR_ENDONLY is set and PCRE2_MULTILINE is not set, the $
+meta-character matches only at the very end of the string.
+
+
+(b) A backslash followed by a letter with no special meaning is faulted. (Perl
+can be made to issue a warning.)
+
+
+(c) If PCRE2_UNGREEDY is set, the greediness of the repetition quantifiers is
+inverted, that is, by default they are not greedy, but if followed by a
+question mark they are.
+
+
+(d) PCRE2_ANCHORED can be used at matching time to force a pattern to be tried
+only at the first matching position in the subject string.
+
+
+(e) The PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY and PCRE2_NOTEMPTY_ATSTART
+options have no Perl equivalents.
+
+
+(f) The \R escape sequence can be restricted to match only CR, LF, or CRLF
+by the PCRE2_BSR_ANYCRLF option.
+
+
+(g) The callout facility is PCRE2-specific. Perl supports codeblocks and
+variable interpolation, but not general hooks on every match.
+
+
+(h) The partial matching facility is PCRE2-specific.
+
+
+(i) The alternative matching function (pcre2_dfa_match()) matches in a
+different way and is not Perl-compatible.
+
+
+(j) PCRE2 recognizes some special sequences such as (*CR) or (*NO_JIT) at
+the start of a pattern. These set overall options that cannot be changed within
+the pattern.
+
+
+(k) PCRE2 supports non-atomic positive lookaround assertions. This is an
+extension to the lookaround facilities. The default, Perl-compatible
+lookarounds are atomic.
+
+
+(l) There are three syntactical items in patterns that can refer to a capturing
+group by number: back references such as \g{2}, subroutine calls such as (?3),
+and condition references such as (?(4)...). PCRE2 supports relative group
+numbers such as +2 and -4 in all three cases. Perl supports both plus and minus
+for subroutine calls, but only minus for back references, and no relative
+numbering at all for conditions.
+
+
+(m) The scan substring assertion (syntax (*scs:(n)...)) is a PCRE2 extension
+that is not available in Perl.
+
+
+20. Perl has different limits than PCRE2. See the
+pcre2limits
+documentation for details. Perl went with 5.10 from recursion to iteration
+keeping the intermediate matches on the heap, which is ~10% slower but does not
+fall into any stack-overflow limit. PCRE2 made a similar change at release
+10.30, and also has many build-time and run-time customizable limits.
+
+
+21. Unlike Perl, PCRE2 doesn't have character set modifiers and specially no way
+to set characters by context just like Perl's "/d". A regular expression using
+PCRE2_UTF and PCRE2_UCP will use similar rules to Perl's "/u"; something closer
+to "/a" could be selected by adding other PCRE2_EXTRA_ASCII* options on top.
+
+
+22. Some recursive patterns that Perl diagnoses as infinite recursions can be
+handled by PCRE2, either by the interpreter or the JIT. An example is
+/(?:|(?0)abcd)(?(R)|\z)/, which matches a sequence of any number of repeated
+"abcd" substrings at the end of the subject.
+
+
+23. Both PCRE2 and Perl error when \x{ escapes are invalid, but Perl tries to
+recover and prints a warning if the problem was that an invalid hexadecimal
+digit was found. Since PCRE2 doesn't have warnings it returns an error instead.
+Additionally, Perl accepts \x{} and generates NUL unlike PCRE2.
+
+
+24. From release 10.45, PCRE2 gives an error if \x is not followed by a
+hexadecimal digit or a curly bracket. It used to interpret this as the NUL
+character. Perl still generates NUL, but warns when in warning mode in most
+cases.
+
+
+AUTHOR
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+REVISION
+
+
+Last updated: 02 June 2025
+
+Copyright © 1997-2024 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2convert.html b/doc/html/pcre2convert.html
new file mode 100644
index 0000000..8d57478
--- /dev/null
+++ b/doc/html/pcre2convert.html
@@ -0,0 +1,191 @@
+
+
+pcre2convert specification
+
+
+pcre2convert man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+This document describes a set of functions that can be used to convert
+"foreign" patterns into PCRE2 regular expressions. This facility is currently
+experimental, and may be changed in future releases. Two kinds of pattern,
+globs and POSIX patterns, are supported.
+
+
+
+pcre2_convert_context *pcre2_convert_context_create(
+ pcre2_general_context *gcontext);
+
+
+pcre2_convert_context *pcre2_convert_context_copy(
+ pcre2_convert_context *cvcontext);
+
+
+void pcre2_convert_context_free(pcre2_convert_context *cvcontext);
+
+
+int pcre2_set_glob_escape(pcre2_convert_context *cvcontext,
+ uint32_t escape_char);
+
+
+int pcre2_set_glob_separator(pcre2_convert_context *cvcontext,
+ uint32_t separator_char);
+
+
+A convert context is used to hold parameters that affect the way that pattern
+conversion works. Like all PCRE2 contexts, you need to use a context only if
+you want to override the defaults. There are the usual create, copy, and free
+functions. If custom memory management functions are set in a general context
+that is passed to pcre2_convert_context_create(), they are used for all
+memory management within the conversion functions.
+
+
+There are only two parameters in the convert context at present. Both apply
+only to glob conversions. The escape character defaults to grave accent under
+Windows, otherwise backslash. It can be set to zero, meaning no escape
+character, or to any punctuation character with a code point less than 256.
+The separator character defaults to backslash under Windows, otherwise forward
+slash. It can be set to forward slash, backslash, or dot.
+
+
+The two setting functions return zero on success, or PCRE2_ERROR_BADDATA if
+their second argument is invalid.
+
+
+
+int pcre2_pattern_convert(PCRE2_SPTR pattern, PCRE2_SIZE length,
+ uint32_t options, PCRE2_UCHAR **buffer,
+ PCRE2_SIZE *blength, pcre2_convert_context *cvcontext);
+
+
+void pcre2_converted_pattern_free(PCRE2_UCHAR *converted_pattern);
+
+
+The first two arguments of pcre2_pattern_convert() define the foreign
+pattern that is to be converted. The length may be given as
+PCRE2_ZERO_TERMINATED. The options argument defines how the pattern is to
+be processed. If the input is UTF, the PCRE2_CONVERT_UTF option should be set.
+PCRE2_CONVERT_NO_UTF_CHECK may also be set if you are sure the input is valid.
+One or more of the glob options, or one of the following POSIX options must be
+set to define the type of conversion that is required:
+
+ PCRE2_CONVERT_GLOB
+ PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR
+ PCRE2_CONVERT_GLOB_NO_STARSTAR
+ PCRE2_CONVERT_POSIX_BASIC
+ PCRE2_CONVERT_POSIX_EXTENDED
+
+Details of the conversions are given below. The buffer and blength
+arguments define how the output is handled:
+
+
+If buffer is NULL, the function just returns the length of the converted
+pattern via blength. This is one less than the length of buffer needed,
+because a terminating zero is always added to the output.
+
+
+If buffer points to a NULL pointer, an output buffer is obtained using
+the allocator in the context or malloc() if no context is supplied. A
+pointer to this buffer is placed in the variable to which buffer points.
+When no longer needed the output buffer must be freed by calling
+pcre2_converted_pattern_free(). If this function is called with a NULL
+argument, it returns immediately without doing anything.
+
+
+If buffer points to a non-NULL pointer, blength must be set to the
+actual length of the buffer provided (in code units).
+
+
+In all cases, after successful conversion, the variable pointed to by
+blength is updated to the length actually used (in code units), excluding
+the terminating zero that is always added.
+
+
+If an error occurs, the length (via blength) is set to the offset
+within the input pattern where the error was detected. Only gross syntax errors
+are caught; there are plenty of errors that will get passed on for
+pcre2_compile() to discover.
+
+
+The return from pcre2_pattern_convert() is zero on success or a non-zero
+PCRE2 error code. Note that PCRE2 error codes may be positive or negative:
+pcre2_compile() uses mostly positive codes and pcre2_match()
+negative ones; pcre2_convert() uses existing codes of both kinds. A
+textual error message can be obtained by calling
+pcre2_get_error_message().
+
+
+
+Globs are used to match file names, and consequently have the concept of a
+"path separator", which defaults to backslash under Windows and forward slash
+otherwise. If PCRE2_CONVERT_GLOB is set, the wildcards * and ? are not
+permitted to match separator characters, but the double-star (**) feature
+(which does match separators) is supported.
+
+
+PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR matches globs with wildcards allowed to
+match separator characters. PCRE2_CONVERT_GLOB_NO_STARSTAR matches globs with
+the double-star feature disabled. These options may be given together.
+
+
+
+POSIX defines two kinds of regular expression pattern: basic and extended.
+These can be processed by setting PCRE2_CONVERT_POSIX_BASIC or
+PCRE2_CONVERT_POSIX_EXTENDED, respectively.
+
+
+In POSIX patterns, backslash is not special in a character class. Unmatched
+closing parentheses are treated as literals.
+
+
+In basic patterns, ? + | {} and () must be escaped to be recognized
+as metacharacters outside a character class. If the first character in the
+pattern is * it is treated as a literal. ^ is a metacharacter only at the start
+of a branch.
+
+
+In extended patterns, a backslash not in a character class always
+makes the next character literal, whatever it is. There are no backreferences.
+
+
+Note: POSIX mandates that the longest possible match at the first matching
+position must be found. This is not what pcre2_match() does; it yields
+the first match that is found. An application can use pcre2_dfa_match()
+to find the longest match, but that does not support backreferences (but then
+neither do POSIX extended patterns).
+
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+
+Last updated: 14 November 2023
+
+Copyright © 1997-2018 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2demo.html b/doc/html/pcre2demo.html
new file mode 100644
index 0000000..37525fd
--- /dev/null
+++ b/doc/html/pcre2demo.html
@@ -0,0 +1,467 @@
+
+
+pcre2demo specification
+
+
+pcre2demo man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SOURCE CODE
+
+
+/*************************************************
+* PCRE2 DEMONSTRATION PROGRAM *
+*************************************************/
+
+/* This is a demonstration program to illustrate a straightforward way of
+using the PCRE2 regular expression library from a C program. See the
+pcre2sample documentation for a short discussion ("man pcre2sample" if you have
+the PCRE2 man pages installed). PCRE2 is a revised API for the library, and is
+incompatible with the original PCRE API.
+
+There are actually three libraries, each supporting a different code unit
+width. This demonstration program uses the 8-bit library. The default is to
+process each code unit as a separate character, but if the pattern begins with
+"(*UTF)", both it and the subject are treated as UTF-8 strings, where
+characters may occupy multiple code units.
+
+In Unix-like environments, if PCRE2 is installed in your standard system
+libraries, you should be able to compile this program using this command:
+
+cc -Wall pcre2demo.c -lpcre2-8 -o pcre2demo
+
+If PCRE2 is not installed in a standard place, it is likely to be installed
+with support for the pkg-config mechanism. If you have pkg-config, you can
+compile this program using this command:
+
+cc -Wall pcre2demo.c `pkg-config --cflags --libs libpcre2-8` -o pcre2demo
+
+If you do not have pkg-config, you may have to use something like this:
+
+cc -Wall pcre2demo.c -I/usr/local/include -L/usr/local/lib \
+ -R/usr/local/lib -lpcre2-8 -o pcre2demo
+
+Replace "/usr/local/include" and "/usr/local/lib" with wherever the include and
+library files for PCRE2 are installed on your system. Only some operating
+systems (Solaris is one) use the -R option.
+
+Building under Windows:
+
+If you want to statically link this program against a non-dll .a file, you must
+define PCRE2_STATIC before including pcre2.h, so in this environment, uncomment
+the following line. */
+
+/* #define PCRE2_STATIC */
+
+/* The PCRE2_CODE_UNIT_WIDTH macro must be defined before including pcre2.h.
+For a program that uses only one code unit width, setting it to 8, 16, or 32
+makes it possible to use generic function names such as pcre2_compile(). Note
+that just changing 8 to 16 (for example) is not sufficient to convert this
+program to process 16-bit characters. Even in a fully 16-bit environment, where
+string-handling functions such as strcmp() and printf() work with 16-bit
+characters, the code for handling the table of named substrings will still need
+to be modified. */
+
+#define PCRE2_CODE_UNIT_WIDTH 8
+
+#include <stdio.h>
+#include <string.h>
+#include <pcre2.h>
+
+
+/**************************************************************************
+* Here is the program. The API includes the concept of "contexts" for *
+* setting up unusual interface requirements for compiling and matching, *
+* such as custom memory managers and non-standard newline definitions. *
+* This program does not do any of this, so it makes no use of contexts, *
+* always passing NULL where a context could be given. *
+**************************************************************************/
+
+int main(int argc, char **argv)
+{
+pcre2_code *re;
+PCRE2_SPTR pattern; /* PCRE2_SPTR is a pointer to unsigned code units of */
+PCRE2_SPTR subject; /* the appropriate width (in this case, 8 bits). */
+PCRE2_SPTR name_table;
+
+int errornumber;
+int find_all, caseless_match;
+int i;
+int rc;
+
+uint32_t namecount;
+uint32_t name_entry_size;
+
+PCRE2_SIZE erroroffset;
+PCRE2_SIZE *ovector;
+PCRE2_SIZE ovector_last[2];
+PCRE2_SIZE subject_length;
+
+pcre2_match_data *match_data;
+
+
+/**************************************************************************
+* First, sort out the command line. Options: *
+* - "-g" to request repeated matching to find all occurrences, *
+* like Perl's /g option. We set the variable find_all to a non-zero *
+* value if the -g option is present. *
+* - "-i" to request caseless matching, like Perl's /i option. We set the *
+* variable caseless_match to PCRE2_CASELESS if the -i option is *
+* present. *
+**************************************************************************/
+
+find_all = 0;
+caseless_match = 0;
+for (i = 1; i < argc; i++)
+ {
+ if (strcmp(argv[i], "-g") == 0) find_all = 1;
+ else if (strcmp(argv[i], "-i") == 0) caseless_match = PCRE2_CASELESS;
+ else if (argv[i][0] == '-')
+ {
+ printf("Unrecognised option %s\n", argv[i]);
+ return 1;
+ }
+ else break;
+ }
+
+/* After the options, we require exactly two arguments, which are the pattern,
+and the subject string. */
+
+if (argc - i != 2)
+ {
+ printf("Exactly two arguments required: a regex and a subject string\n");
+ return 1;
+ }
+
+/* Pattern and subject are char arguments, so they can be straightforwardly
+cast to PCRE2_SPTR because we are working in 8-bit code units. The subject
+length is cast to PCRE2_SIZE for completeness, though PCRE2_SIZE is in fact
+defined to be size_t. */
+
+pattern = (PCRE2_SPTR)argv[i];
+subject = (PCRE2_SPTR)argv[i+1];
+subject_length = (PCRE2_SIZE)strlen((char *)subject);
+
+
+/*************************************************************************
+* Now we are going to compile the regular expression pattern, and handle *
+* any errors that are detected. *
+*************************************************************************/
+
+re = pcre2_compile(
+ pattern, /* the pattern */
+ PCRE2_ZERO_TERMINATED, /* indicates pattern is zero-terminated */
+ caseless_match, /* possibly enable caseless */
+ &errornumber, /* for error number */
+ &erroroffset, /* for error offset */
+ NULL); /* use default compile context */
+
+/* Compilation failed: print the error message and exit. */
+
+if (re == NULL)
+ {
+ PCRE2_UCHAR buffer[256];
+ pcre2_get_error_message(errornumber, buffer, sizeof(buffer));
+ printf("PCRE2 compilation failed at offset %d: %s\n", (int)erroroffset,
+ buffer);
+ return 1;
+ }
+
+
+/*************************************************************************
+* If the compilation succeeded, we call PCRE2 again, in order to do a *
+* pattern match against the subject string. This does just ONE match. If *
+* further matching is needed, it will be done below. Before running the *
+* match we must set up a match_data block for holding the result. Using *
+* pcre2_match_data_create_from_pattern() ensures that the block is *
+* exactly the right size for the number of capturing parentheses in the *
+* pattern. If you need to know the actual size of a match_data block as *
+* a number of bytes, you can find it like this: *
+* *
+* PCRE2_SIZE match_data_size = pcre2_get_match_data_size(match_data); *
+*************************************************************************/
+
+match_data = pcre2_match_data_create_from_pattern(re, NULL);
+
+/* Now run the match. */
+
+rc = pcre2_match(
+ re, /* the compiled pattern */
+ subject, /* the subject string */
+ subject_length, /* the length of the subject */
+ 0, /* start at offset 0 in the subject */
+ 0, /* default options */
+ match_data, /* block for storing the result */
+ NULL); /* use default match context */
+
+/* Matching failed: handle error cases */
+
+if (rc < 0)
+ {
+ switch(rc)
+ {
+ case PCRE2_ERROR_NOMATCH: printf("No match\n"); break;
+ /*
+ Handle other special cases if you like
+ */
+ default: printf("Matching error %d\n", rc); break;
+ }
+ pcre2_match_data_free(match_data); /* Release memory used for the match */
+ pcre2_code_free(re); /* data and the compiled pattern. */
+ return 1;
+ }
+
+/* Match succeeded. Get a pointer to the output vector, where string offsets
+are stored. */
+
+ovector = pcre2_get_ovector_pointer(match_data);
+printf("Match succeeded at offset %d\n", (int)ovector[0]);
+
+
+/*************************************************************************
+* We have found the first match within the subject string. If the output *
+* vector wasn't big enough, say so. Then output any substrings that were *
+* captured. *
+*************************************************************************/
+
+/* The output vector wasn't big enough. This should not happen, because we used
+pcre2_match_data_create_from_pattern() above. */
+
+if (rc == 0)
+ printf("ovector was not big enough for all the captured substrings\n");
+
+/* Since release 10.38 PCRE2 has locked out the use of \K in lookaround
+assertions. This is the recommended behaviour. However, the option
+PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK allows applications to re-enable the old
+behaviour. If that is set, it is possible to run patterns such as /(?=.\K)/ that
+use \K in an assertion to set the start of a match later than its end. In this
+demonstration program, we show how to detect this case, although it cannot arise
+because the option is never set. */
+
+if (ovector[0] > ovector[1])
+ {
+ printf("\\K was used in an assertion to set the match start after its end.\n"
+ "From end to start the match was: %.*s\n", (int)(ovector[0] - ovector[1]),
+ (char *)(subject + ovector[1]));
+ printf("Run abandoned\n");
+ pcre2_match_data_free(match_data);
+ pcre2_code_free(re);
+ return 1;
+ }
+
+/* Show substrings stored in the output vector by number. Obviously, in a real
+application you might want to do things other than print them. */
+
+for (i = 0; i < rc; i++)
+ {
+ PCRE2_SPTR substring_start = subject + ovector[2*i];
+ PCRE2_SIZE substring_length = ovector[2*i+1] - ovector[2*i];
+ printf("%2d: %.*s\n", i, (int)substring_length, (char *)substring_start);
+ }
+
+
+/**************************************************************************
+* That concludes the basic part of this demonstration program. We have *
+* compiled a pattern, and performed a single match. The code that follows *
+* shows first how to access named substrings, and then how to code for *
+* repeated matches on the same subject. *
+**************************************************************************/
+
+/* See if there are any named substrings, and if so, show them by name. First
+we have to extract the count of named parentheses from the pattern. */
+
+(void)pcre2_pattern_info(
+ re, /* the compiled pattern */
+ PCRE2_INFO_NAMECOUNT, /* get the number of named substrings */
+ &namecount); /* where to put the answer */
+
+if (namecount == 0)
+ printf("No named substrings\n");
+else
+ {
+ PCRE2_SPTR tabptr;
+ printf("Named substrings\n");
+
+ /* Before we can access the substrings, we must extract the table for
+ translating names to numbers, and the size of each entry in the table. */
+
+ (void)pcre2_pattern_info(
+ re, /* the compiled pattern */
+ PCRE2_INFO_NAMETABLE, /* address of the table */
+ &name_table); /* where to put the answer */
+
+ (void)pcre2_pattern_info(
+ re, /* the compiled pattern */
+ PCRE2_INFO_NAMEENTRYSIZE, /* size of each entry in the table */
+ &name_entry_size); /* where to put the answer */
+
+ /* Now we can scan the table and, for each entry, print the number, the name,
+ and the substring itself. In the 8-bit library the number is held in two
+ bytes, most significant first. */
+
+ tabptr = name_table;
+ for (i = 0; i < namecount; i++)
+ {
+ int n = (tabptr[0] << 8) | tabptr[1];
+ printf("(%d) %*s: %.*s\n", n, name_entry_size - 3, tabptr + 2,
+ (int)(ovector[2*n+1] - ovector[2*n]), subject + ovector[2*n]);
+ tabptr += name_entry_size;
+ }
+ }
+
+
+/*************************************************************************
+* If the "-g" option was given on the command line, we want to continue *
+* to search for additional matches in the subject string, in a similar *
+* way to the /g option in Perl. This turns out to be trickier than you *
+* might think because of the possibility of matching an empty string. *
+* *
+* To help with this task, PCRE2 provides the pcre2_next_match() helper. *
+*************************************************************************/
+
+if (!find_all) /* Check for -g */
+ {
+ pcre2_match_data_free(match_data); /* Release the memory that was used */
+ pcre2_code_free(re); /* for the match data and the pattern. */
+ return 0; /* Exit the program. */
+ }
+
+/* Loop for second and subsequent matches */
+
+ovector_last[0] = ovector[0];
+ovector_last[1] = ovector[1];
+
+for (;;)
+ {
+ PCRE2_SIZE start_offset;
+ uint32_t options;
+
+ /* After each successful match, we use pcre2_next_match() to obtain the match
+ parameters for subsequent match attempts. */
+
+ if (!pcre2_next_match(match_data, &start_offset, &options))
+ break;
+
+ /* Run the next matching operation */
+
+ rc = pcre2_match(
+ re, /* the compiled pattern */
+ subject, /* the subject string */
+ subject_length, /* the length of the subject */
+ start_offset, /* starting offset in the subject */
+ options, /* options */
+ match_data, /* block for storing the result */
+ NULL); /* use default match context */
+
+ /* If this match attempt fails, exit the loop for subsequent matches. */
+
+ if (rc == PCRE2_ERROR_NOMATCH)
+ break;
+
+ /* Other matching errors are not recoverable. */
+
+ if (rc < 0)
+ {
+ printf("Matching error %d\n", rc);
+ pcre2_match_data_free(match_data);
+ pcre2_code_free(re);
+ return 1;
+ }
+
+ /* This demonstration program depends on pcre2_next_match() to ensure that the
+ loop for second and subsequent matches does not run forever. However, it would
+ be robust practice for a production application to verify this. The following
+ block of code shows how to do this. This error case is not reachable unless
+ there is a bug in PCRE2.
+
+ Because this program does not set the PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK option,
+ the logic is simple. We verify that either ovector[1] has advanced, or that we
+ have an empty match touching the end of a previous non-empty match. See the
+ API documentation for guidance if your application uses
+ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK and searches for multiple matches. */
+
+ if (!(ovector[1] > ovector_last[1] ||
+ (ovector[1] == ovector[0] && ovector_last[1] > ovector_last[0] &&
+ ovector[1] == ovector_last[1])))
+ {
+ printf("\\K was used in an assertion to yield non-advancing matches.\n");
+ printf("Run abandoned\n");
+ pcre2_match_data_free(match_data);
+ pcre2_code_free(re);
+ return 1;
+ }
+
+ ovector_last[0] = ovector[0];
+ ovector_last[1] = ovector[1];
+
+ /* Match succeeded. */
+
+ printf("\nMatch succeeded again at offset %d\n", (int)ovector[0]);
+
+ /* The match succeeded, but the output vector wasn't big enough. This
+ should not happen. */
+
+ if (rc == 0)
+ printf("ovector was not big enough for all the captured substrings\n");
+
+ /* We guard against patterns such as /(?=.\K)/ that use \K in an assertion to
+ set the start of a match later than its end. As explained above, this case
+ should not occur because this demonstration program does not set the
+ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK option, however, we do include code showing
+ how to detect it. */
+
+ if (ovector[0] > ovector[1])
+ {
+ printf("\\K was used in an assertion to set the match start after its end.\n"
+ "From end to start the match was: %.*s\n", (int)(ovector[0] - ovector[1]),
+ (char *)(subject + ovector[1]));
+ printf("Run abandoned\n");
+ pcre2_match_data_free(match_data);
+ pcre2_code_free(re);
+ return 1;
+ }
+
+ /* As before, show substrings stored in the output vector by number, and then
+ also any named substrings. */
+
+ for (i = 0; i < rc; i++)
+ {
+ PCRE2_SPTR substring_start = subject + ovector[2*i];
+ size_t substring_length = ovector[2*i+1] - ovector[2*i];
+ printf("%2d: %.*s\n", i, (int)substring_length, (char *)substring_start);
+ }
+
+ if (namecount == 0)
+ printf("No named substrings\n");
+ else
+ {
+ PCRE2_SPTR tabptr = name_table;
+ printf("Named substrings\n");
+ for (i = 0; i < namecount; i++)
+ {
+ int n = (tabptr[0] << 8) | tabptr[1];
+ printf("(%d) %*s: %.*s\n", n, name_entry_size - 3, tabptr + 2,
+ (int)(ovector[2*n+1] - ovector[2*n]), subject + ovector[2*n]);
+ tabptr += name_entry_size;
+ }
+ }
+ } /* End of loop to find second and subsequent matches */
+
+printf("\n");
+
+pcre2_match_data_free(match_data);
+pcre2_code_free(re);
+return 0;
+}
+
+/* End of pcre2demo.c */
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2grep.html b/doc/html/pcre2grep.html
new file mode 100644
index 0000000..deb667e
--- /dev/null
+++ b/doc/html/pcre2grep.html
@@ -0,0 +1,1135 @@
+
+
+pcre2grep specification
+
+
+pcre2grep man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+pcre2grep [options] [long options] [pattern] [path1 path2 ...]
+
+
+
+pcre2grep searches files for character patterns, in the same way as other
+grep commands do, but it uses the PCRE2 regular expression library to support
+patterns that are compatible with the regular expressions of Perl 5. See
+pcre2syntax(3)
+for a quick-reference summary of pattern syntax, or
+pcre2pattern(3)
+for a full description of the syntax and semantics of the regular expressions
+that PCRE2 supports.
+
+
+Patterns, whether supplied on the command line or in a separate file, are given
+without delimiters. For example:
+
+ pcre2grep Thursday /etc/motd
+
+If you attempt to use delimiters (for example, by surrounding a pattern with
+slashes, as is common in Perl scripts), they are interpreted as part of the
+pattern. Quotes can of course be used to delimit patterns on the command line
+because they are interpreted by the shell, and indeed quotes are required if a
+pattern contains white space or shell metacharacters.
+
+
+The first argument that follows any option settings is treated as the single
+pattern to be matched when neither -e nor -f is present.
+Conversely, when one or both of these options are used to specify patterns, all
+arguments are treated as path names. At least one of -e, -f, or an
+argument pattern must be provided.
+
+
+If no files are specified, pcre2grep reads the standard input. The
+standard input can also be referenced by a name consisting of a single hyphen.
+For example:
+
+ pcre2grep some-pattern file1 - file3
+
+By default, input files are searched line by line, so pattern assertions about
+the beginning and end of a subject string (^, $, \A, \Z, and \z) match at
+the beginning and end of each line. When a line matches a pattern, it is copied
+to the standard output, and if there is more than one file, the file name is
+output at the start of each line, followed by a colon. However, there are
+options that can change how pcre2grep behaves. For example, the -M
+option makes it possible to search for strings that span line boundaries. What
+defines a line boundary is controlled by the -N (--newline) option.
+The -h and -H options control whether or not file names are shown,
+and the -Z option changes the file name terminator to a zero byte.
+
+
+The amount of memory used for buffering files that are being scanned is
+controlled by parameters that can be set by the --buffer-size and
+--max-buffer-size options. The first of these sets the size of buffer
+that is obtained at the start of processing. If an input file contains very
+long lines, a larger buffer may be needed; this is handled by automatically
+extending the buffer, up to the limit specified by --max-buffer-size. The
+default values for these parameters can be set when pcre2grep is
+built; if nothing is specified, the defaults are set to 20KiB and 1MiB
+respectively. An error occurs if a line is too long and the buffer can no
+longer be expanded.
+
+
+The block of memory that is actually used is three times the "buffer size", to
+allow for buffering "before" and "after" lines. If the buffer size is too
+small, fewer than requested "before" and "after" lines may be output.
+
+
+When matching with a multiline pattern, the size of the buffer must be at least
+half of the maximum match expected or the pattern might fail to match.
+
+
+Patterns can be no longer than 8KiB or BUFSIZ bytes, whichever is the greater.
+BUFSIZ is defined in <stdio.h>. When there is more than one pattern
+(specified by the use of -e and/or -f), each pattern is applied to
+each line in the order in which they are defined, except that all the -e
+patterns are tried before the -f patterns.
+
+
+By default, as soon as one pattern matches a line, no further patterns are
+considered. However, if --colour (or --color) is used to colour the
+matching substrings, or if --only-matching, --file-offsets,
+--line-offsets, or --output is used to output only the part of the
+line that matched (either shown literally, or as an offset), the behaviour is
+different. In this situation, all the patterns are applied to the line. If
+there is more than one match, the one that begins nearest to the start of the
+subject is processed; if there is more than one match at that position, the one
+with the longest matching substring is processed; if the matching substrings
+are equal, the first match found is processed.
+
+
+Scanning with all the patterns resumes immediately following the match, so that
+later matches on the same line can be found. Note, however, that an overlapping
+match that starts in the middle of another match will not be processed.
+
+
+The above behaviour was changed at release 10.41 to be more compatible with GNU
+grep. In earlier releases, pcre2grep did not recognize matches from
+later patterns that were earlier in the subject.
+
+
+Patterns that can match an empty string are accepted, but empty string
+matches are never recognized. An example is the pattern "(super)?(man)?", in
+which all components are optional. This pattern finds all occurrences of both
+"super" and "man"; the output differs from matching with "super|man" when only
+the matching substrings are being shown.
+
+
+If the LC_ALL or LC_CTYPE environment variable is set,
+pcre2grep uses the value to set a locale when calling the PCRE2 library.
+The --locale option can be used to override this.
+
+
+
+Compile-time options for pcre2grep can set it up to use libz or
+libbz2 for reading compressed files whose names end in .gz or
+.bz2, respectively. You can find out whether your pcre2grep binary
+has support for one or both of these file types by running it with the
+--help option. If the appropriate support is not present, all files are
+treated as plain text. The standard input is always so treated. If a file with
+a .gz or .bz2 extension is not in fact compressed, it is read as a
+plain text file. When input is from a compressed .gz or .bz2 file, the
+--line-buffered option is ignored.
+
+
+
+By default, a file that contains a binary zero byte within the first 1024 bytes
+is identified as a binary file, and is processed specially. However, if the
+newline type is specified as NUL, that is, the line terminator is a binary
+zero, the test for a binary file is not applied. See the --binary-files
+option for a means of changing the way binary files are handled.
+
+
+
+Patterns passed from the command line are strings that are terminated by a
+binary zero, so cannot contain internal zeros. However, patterns that are read
+from a file via the -f option may contain binary zeros.
+
+
+
+The order in which some of the options appear can affect the output. For
+example, both the -H and -l options affect the printing of file
+names. Whichever comes later in the command line will be the one that takes
+effect. Similarly, except where noted below, if an option is given twice, the
+later setting is used. Numerical values for options may be followed by K or M,
+to signify multiplication by 1024 or 1024*1024 respectively.
+
+
+--
+This terminates the list of options. It is useful if the next item on the
+command line starts with a hyphen but is not an option. This allows for the
+processing of patterns and file names that start with hyphens.
+
+
+-A number, --after-context=number
+Output up to number lines of context after each matching line. Fewer
+lines are output if the next match or the end of the file is reached, or if the
+processing buffer size has been set too small. If file names and/or line
+numbers are being output, a hyphen separator is used instead of a colon for the
+context lines (the -Z option can be used to change the file name
+terminator to a zero byte). A line containing "--" is output between each group
+of lines, unless they are in fact contiguous in the input file. The value of
+number is expected to be relatively small. When -c is used,
+-A is ignored.
+
+
+-a, --text
+Treat binary files as text. This is equivalent to
+--binary-files=text.
+
+
+--allow-lookaround-bsk
+PCRE2 now forbids the use of \K in lookarounds by default, in line with Perl.
+This option causes pcre2grep to set the PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK
+option, which enables this somewhat dangerous usage.
+
+
+-B number, --before-context=number
+Output up to number lines of context before each matching line. Fewer
+lines are output if the previous match or the start of the file is within
+number lines, or if the processing buffer size has been set too small. If
+file names and/or line numbers are being output, a hyphen separator is used
+instead of a colon for the context lines (the -Z option can be used to
+change the file name terminator to a zero byte). A line containing "--" is
+output between each group of lines, unless they are in fact contiguous in the
+input file. The value of number is expected to be relatively small. When
+-c is used, -B is ignored.
+
+
+--binary-files=word
+Specify how binary files are to be processed. If the word is "binary" (the
+default), pattern matching is performed on binary files, but the only output is
+"Binary file <name> matches" when a match succeeds. If the word is "text",
+which is equivalent to the -a or --text option, binary files are
+processed in the same way as any other file. In this case, when a match
+succeeds, the output may be binary garbage, which can have nasty effects if
+sent to a terminal. If the word is "without-match", which is equivalent to the
+-I option, binary files are not processed at all; they are assumed not to
+be of interest and are skipped without causing any output or affecting the
+return code.
+
+
+--buffer-size=number
+Set the parameter that controls how much memory is obtained at the start of
+processing for buffering files that are being scanned. See also
+--max-buffer-size below.
+
+
+-C number, --context=number
+Output number lines of context both before and after each matching line.
+This is equivalent to setting both -A and -B to the same value.
+
+
+-c, --count
+Do not output lines from the files that are being scanned; instead output the
+number of lines that would have been shown, either because they matched, or, if
+-v is set, because they failed to match. By default, this count is
+exactly the same as the number of lines that would have been output, but if the
+-M (multiline) option is used (without -v), there may be more
+suppressed lines than the count (that is, the number of matches).
+
+
+If no lines are selected, the number zero is output. If several files are
+being scanned, a count is output for each of them and the -t option can
+be used to cause a total to be output at the end. However, if the
+--files-with-matches option is also used, only those files whose counts
+are greater than zero are listed. When -c is used, the -A,
+-B, and -C options are ignored.
+
+
+--colour, --color
+If this option is given without any data, it is equivalent to "--colour=auto".
+If data is required, it must be given in the same shell item, separated by an
+equals sign.
+
+
+--colour=value, --color=value
+This option specifies under what circumstances the parts of a line that matched
+a pattern should be coloured in the output. It is ignored if
+--file-offsets, --line-offsets, or --output is set. By
+default, output is not coloured. The value for the --colour option (which
+is optional, see above) may be "never", "always", or "auto". In the latter
+case, colouring happens only if the standard output is connected to a terminal.
+More resources are used when colouring is enabled, because pcre2grep has
+to search for all possible matches in a line, not just one, in order to colour
+them all.
+
+
+The colour that is used can be specified by setting one of the environment
+variables PCRE2GREP_COLOUR, PCRE2GREP_COLOR, PCREGREP_COLOUR, or
+PCREGREP_COLOR, which are checked in that order. If none of these are set,
+pcre2grep looks for GREP_COLORS or GREP_COLOR (in that order). The value
+of the variable should be a string of two numbers, separated by a semicolon,
+except in the case of GREP_COLORS, which must start with "ms=" or "mt="
+followed by two semicolon-separated colours, terminated by the end of the
+string or by a colon. If GREP_COLORS does not start with "ms=" or "mt=" it is
+ignored, and GREP_COLOR is checked.
+
+
+If the string obtained from one of the above variables contains any characters
+other than semicolon or digits, the setting is ignored and the default colour
+is used. The string is copied directly into the control string for setting
+colour on a terminal, so it is your responsibility to ensure that the values
+make sense. If no relevant environment variable is set, the default is "1;31",
+which gives red.
+
+
+-D action, --devices=action
+If an input path is not a regular file or a directory, "action" specifies how
+it is to be processed. Valid values are "read" (the default) or "skip"
+(silently skip the path).
+
+
+-d action, --directories=action
+If an input path is a directory, "action" specifies how it is to be processed.
+Valid values are "read" (the default in non-Windows environments, for
+compatibility with GNU grep), "recurse" (equivalent to the -r option), or
+"skip" (silently skip the path, the default in Windows environments). In the
+"read" case, directories are read as if they were ordinary files. In some
+operating systems the effect of reading a directory like this is an immediate
+end-of-file; in others it may provoke an error.
+
+
+--depth-limit=number
+See --match-limit below.
+
+
+-E, --case-restrict
+When case distinctions are being ignored in Unicode mode, two ASCII letters (K
+and S) will by default match Unicode characters U+212A (Kelvin sign) and U+017F
+(long S) respectively, as well as their lower case ASCII counterparts. When
+this option is set, case equivalences are restricted such that no ASCII
+character matches a non-ASCII character, and vice versa.
+
+
+-e pattern, --regex=pattern, --regexp=pattern
+Specify a pattern to be matched. This option can be used multiple times in
+order to specify several patterns. It can also be used as a way of specifying a
+single pattern that starts with a hyphen. When -e is used, no argument
+pattern is taken from the command line; all arguments are treated as file
+names. There is no limit to the number of patterns. They are applied to each
+line in the order in which they are defined.
+
+
+If -f is used with -e, the command line patterns are matched first,
+followed by the patterns from the file(s), independent of the order in which
+these options are specified.
+
+
+--exclude=pattern
+Files (but not directories) whose names match the pattern are skipped without
+being processed. This applies to all files, whether listed on the command line,
+obtained from --file-list, or by scanning a directory. The pattern is a
+PCRE2 regular expression, and is matched against the final component of the
+file name, not the entire path. The -F, -w, and -x options do
+not apply to this pattern. The option may be given any number of times in order
+to specify multiple patterns. If a file name matches both an --include
+and an --exclude pattern, it is excluded. There is no short form for this
+option.
+
+
+--exclude-from=filename
+Treat each non-empty line of the file as the data for an --exclude
+option. What constitutes a newline when reading the file is the operating
+system's default. The --newline option has no effect on this option. This
+option may be given more than once in order to specify a number of files to
+read.
+
+
+--exclude-dir=pattern
+Directories whose names match the pattern are skipped without being processed,
+whatever the setting of the --recursive option. This applies to all
+directories, whether listed on the command line, obtained from
+--file-list, or by scanning a parent directory. The pattern is a PCRE2
+regular expression, and is matched against the final component of the directory
+name, not the entire path. The -F, -w, and -x options do not
+apply to this pattern. The option may be given any number of times in order to
+specify more than one pattern. If a directory matches both --include-dir
+and --exclude-dir, it is excluded. There is no short form for this
+option.
+
+
+-F, --fixed-strings
+Interpret each data-matching pattern as a list of fixed strings, separated by
+newlines, instead of as a regular expression. What constitutes a newline for
+this purpose is controlled by the --newline option. The -w (match
+as a word) and -x (match whole line) options can be used with -F.
+They apply to each of the fixed strings. A line is selected if any of the fixed
+strings are found in it (subject to -w or -x, if present). This
+option applies only to the patterns that are matched against the contents of
+files; it does not apply to patterns specified by any of the --include or
+--exclude options.
+
+
+-f filename, --file=filename
+Read patterns from the file, one per line. As is the case with patterns on the
+command line, no delimiters should be used. What constitutes a newline when
+reading the file is the operating system's default interpretation of \n. The
+--newline option has no effect on this option. Trailing white space is
+removed from each line, and blank lines are ignored unless the
+--posix-pattern-file option is also provided. An empty file contains no
+patterns and therefore matches nothing. Patterns read from a file in this way
+may contain binary zeros, which are treated as ordinary character literals.
+
+
+If this option is given more than once, all the specified files are read. A
+data line is output if any of the patterns match it. A file name can be given
+as "-" to refer to the standard input. When -f is used, patterns
+specified on the command line using -e may also be present; they are
+matched before the file's patterns. However, no pattern is taken from the
+command line; all arguments are treated as the names of paths to be searched.
+
+
+--file-list=filename
+Read a list of files and/or directories that are to be scanned from the given
+file, one per line. What constitutes a newline when reading the file is the
+operating system's default. Trailing white space is removed from each line, and
+blank lines are ignored. These paths are processed before any that are listed
+on the command line. The file name can be given as "-" to refer to the standard
+input. If --file and --file-list are both specified as "-",
+patterns are read first. This is useful only when the standard input is a
+terminal, from which further lines (the list of files) can be read after an
+end-of-file indication. If this option is given more than once, all the
+specified files are read.
+
+
+--file-offsets
+Instead of showing lines or parts of lines that match, show each match as an
+offset from the start of the file and a length, separated by a comma. In this
+mode, --colour has no effect, and no context is shown. That is, the
+-A, -B, and -C options are ignored. If there is more than one
+match in a line, each of them is shown separately. This option is mutually
+exclusive with --output, --line-offsets, and --only-matching.
+
+
+--group-separator=text
+Output this text string instead of two hyphens between groups of lines when
+-A, -B, or -C is in use. See also --no-group-separator.
+
+
+-H, --with-filename
+Force the inclusion of the file name at the start of output lines when
+searching a single file. The file name is not normally shown in this case.
+By default, for matching lines, the file name is followed by a colon; for
+context lines, a hyphen separator is used. The -Z option can be used to
+change the terminator to a zero byte. If a line number is also being output,
+it follows the file name. When the -M option causes a pattern to match
+more than one line, only the first is preceded by the file name. This option
+overrides any previous -h, -l, or -L options.
+
+
+-h, --no-filename
+Suppress the output file names when searching multiple files. File names are
+normally shown when multiple files are searched. By default, for matching
+lines, the file name is followed by a colon; for context lines, a hyphen
+separator is used. The -Z option can be used to change the terminator to
+a zero byte. If a line number is also being output, it follows the file name.
+This option overrides any previous -H, -L, or -l options.
+
+
+--heap-limit=number
+See --match-limit below.
+
+
+--help
+Output a help message, giving brief details of the command options and file
+type support, and then exit. Anything else on the command line is
+ignored.
+
+
+-I
+Ignore binary files. This is equivalent to
+--binary-files=without-match.
+
+
+-i, --ignore-case
+Ignore upper/lower case distinctions when pattern matching. This applies when
+matching path names for inclusion or exclusion as well as when matching lines
+in files.
+
+
+--include=pattern
+If any --include patterns are specified, the only files that are
+processed are those whose names match one of the patterns and do not match an
+--exclude pattern. This option does not affect directories, but it
+applies to all files, whether listed on the command line, obtained from
+--file-list, or by scanning a directory. The pattern is a PCRE2 regular
+expression, and is matched against the final component of the file name, not
+the entire path. The -F, -w, and -x options do not apply to
+this pattern. The option may be given any number of times. If a file name
+matches both an --include and an --exclude pattern, it is excluded.
+There is no short form for this option.
+
+
+--include-from=filename
+Treat each non-empty line of the file as the data for an --include
+option. What constitutes a newline for this purpose is the operating system's
+default. The --newline option has no effect on this option. This option
+may be given any number of times; all the files are read.
+
+
+--include-dir=pattern
+If any --include-dir patterns are specified, the only directories that
+are processed are those whose names match one of the patterns and do not match
+an --exclude-dir pattern. This applies to all directories, whether listed
+on the command line, obtained from --file-list, or by scanning a parent
+directory. The pattern is a PCRE2 regular expression, and is matched against
+the final component of the directory name, not the entire path. The -F,
+-w, and -x options do not apply to this pattern. The option may be
+given any number of times. If a directory matches both --include-dir and
+--exclude-dir, it is excluded. There is no short form for this option.
+
+
+-L, --files-without-match
+Instead of outputting lines from the files, just output the names of the files
+that do not contain any lines that would have been output. Each file name is
+output once, on a separate line by default, but if the -Z option is set,
+they are separated by zero bytes instead of newlines. This option overrides any
+previous -H, -h, or -l options.
+
+
+-l, --files-with-matches
+Instead of outputting lines from the files, just output the names of the files
+containing lines that would have been output. Each file name is output once, on
+a separate line, but if the -Z option is set, they are separated by zero
+bytes instead of newlines. Searching normally stops as soon as a matching line
+is found in a file. However, if the -c (count) option is also used,
+matching continues in order to obtain the correct count, and those files that
+have at least one match are listed along with their counts. Using this option
+with -c is a way of suppressing the listing of files with no matches that
+occurs with -c on its own. This option overrides any previous -H,
+-h, or -L options.
+
+
+--label=name
+This option supplies a name to be used for the standard input when file names
+are being output. If not supplied, "(standard input)" is used. There is no
+short form for this option.
+
+
+--line-buffered
+When this option is given, non-compressed input is read and processed line by
+line, and the output is flushed after each write. By default, input is read in
+large chunks, unless pcre2grep can determine that it is reading from a
+terminal, which is currently possible only in Unix-like environments or
+Windows. Output to terminal is normally automatically flushed by the operating
+system. This option can be useful when the input or output is attached to a
+pipe and you do not want pcre2grep to buffer up large amounts of data.
+However, its use will affect performance, and the -M (multiline) option
+ceases to work. When input is from a compressed .gz or .bz2 file,
+--line-buffered is ignored.
+
+
+--line-offsets
+Instead of showing lines or parts of lines that match, show each match as a
+line number, the offset from the start of the line, and a length. The line
+number is terminated by a colon (as usual; see the -n option), and the
+offset and length are separated by a comma. In this mode, --colour has no
+effect, and no context is shown. That is, the -A, -B, and -C
+options are ignored. If there is more than one match in a line, each of them is
+shown separately. This option is mutually exclusive with --output,
+--file-offsets, and --only-matching.
+
+
+--locale=locale-name
+This option specifies a locale to be used for pattern matching. It overrides
+the value in the LC_ALL or LC_CTYPE environment variables. If no
+locale is specified, the PCRE2 library's default (usually the "C" locale) is
+used. There is no short form for this option.
+
+
+-M, --multiline
+Allow patterns to match more than one line. When this option is set, the PCRE2
+library is called in "multiline" mode, and a match is allowed to continue past
+the end of the initial line and onto one or more subsequent lines.
+
+
+Patterns used with -M may usefully contain literal newline characters and
+internal occurrences of ^ and $ characters, because in multiline mode these can
+match at internal newlines. Because pcre2grep is scanning multiple lines,
+the \Z and \z assertions match only at the end of the last line in the file.
+The \A assertion matches at the start of the first line of a match. This can
+be any line in the file; it is not anchored to the first line.
+
+
+The output for a successful match may consist of more than one line. The first
+line is the line in which the match started, and the last line is the line in
+which the match ended. If the matched string ends with a newline sequence, the
+output ends at the end of that line. If -v is set, none of the lines in a
+multi-line match are output. Once a match has been handled, scanning restarts
+at the beginning of the line after the one in which the match ended.
+
+
+The newline sequence that separates multiple lines must be matched as part of
+the pattern. For example, to find the phrase "regular expression" in a file
+where "regular" might be at the end of a line and "expression" at the start of
+the next line, you could use this command:
+
+ pcre2grep -M 'regular\s+expression' <file>
+
+The \s escape sequence matches any white space character, including newlines,
+and is followed by + so as to match trailing white space on the first line as
+well as possibly handling a two-character newline sequence.
+
+
+There is a limit to the number of lines that can be matched, imposed by the way
+that pcre2grep buffers the input file as it scans it. With a sufficiently
+large processing buffer, this should not be a problem.
+
+
+The -M option does not work when input is read line by line (see
+--line-buffered.)
+
+
+-m number, --max-count=number
+Stop processing after finding number matching lines, or non-matching
+lines if -v is also set. Any trailing context lines are output after the
+final match. In multiline mode, each multiline match counts as just one line
+for this purpose. If this limit is reached when reading the standard input from
+a regular file, the file is left positioned just after the last matching line.
+If -c is also set, the count that is output is never greater than
+number. This option has no effect if used with -L, -l, or
+-q, or when just checking for a match in a binary file.
+
+
+--match-limit=number
+Processing some regular expression patterns may take a very long time to search
+for all possible matching strings. Others may require a very large amount of
+memory. There are three options that set resource limits for matching.
+
+
+The --match-limit option provides a means of limiting computing resource
+usage when processing patterns that are not going to match, but which have a
+very large number of possibilities in their search trees. The classic example
+is a pattern that uses nested unlimited repeats. Internally, PCRE2 has a
+counter that is incremented each time around its main processing loop. If the
+value set by --match-limit is reached, an error occurs.
+
+
+The --heap-limit option specifies, as a number of kibibytes (units of
+1024 bytes), the maximum amount of heap memory that may be used for matching.
+
+
+The --depth-limit option limits the depth of nested backtracking points,
+which indirectly limits the amount of memory that is used. The amount of memory
+needed for each backtracking point depends on the number of capturing
+parentheses in the pattern, so the amount of memory that is used before this
+limit acts varies from pattern to pattern. This limit is of use only if it is
+set smaller than --match-limit.
+
+
+There are no short forms for these options. The default limits can be set
+when the PCRE2 library is compiled; if they are not specified, the defaults
+are very large and so effectively unlimited.
+
+
+--max-buffer-size=number
+This limits the expansion of the processing buffer, whose initial size can be
+set by --buffer-size. The maximum buffer size is silently forced to be no
+smaller than the starting buffer size.
+
+
+-N newline-type, --newline=newline-type
+Six different conventions for indicating the ends of lines in scanned files are
+supported. For example:
+
+ pcre2grep -N CRLF 'some pattern' <file>
+
+The newline type may be specified in upper, lower, or mixed case. If the
+newline type is NUL, lines are separated by binary zero characters. The other
+types are the single-character sequences CR (carriage return) and LF
+(linefeed), the two-character sequence CRLF, an "anycrlf" type, which
+recognizes any of the preceding three types, and an "any" type, for which any
+Unicode line ending sequence is assumed to end a line. The Unicode sequences
+are the three just mentioned, plus VT (vertical tab, U+000B), FF (form feed,
+U+000C), NEL (next line, U+0085), LS (line separator, U+2028), and PS
+(paragraph separator, U+2029).
+
+
+When the PCRE2 library is built, a default line-ending sequence is specified.
+This is normally the standard sequence for the operating system. Unless
+otherwise specified by this option, pcre2grep uses the library's default.
+
+
+This option makes it possible to use pcre2grep to scan files that have
+come from other environments without having to modify their line endings. If
+the data that is being scanned does not agree with the convention set by this
+option, pcre2grep may behave in strange ways. Note that this option does
+not apply to files specified by the -f, --exclude-from, or
+--include-from options, which are expected to use the operating system's
+standard newline sequence.
+
+
+-n, --line-number
+Precede each output line by its line number in the file, followed by a colon
+for matching lines or a hyphen for context lines. If the file name is also
+being output, it precedes the line number. When the -M option causes a
+pattern to match more than one line, only the first is preceded by its line
+number. This option is forced if --line-offsets is used.
+
+
+--no-group-separator
+Do not output a separator between groups of lines when -A, -B, or
+-C is in use. The default is to output a line containing two hyphens. See
+also --group-separator.
+
+
+--no-jit
+If the PCRE2 library is built with support for just-in-time compiling (which
+speeds up matching), pcre2grep automatically makes use of this, unless it
+was explicitly disabled at build time. This option can be used to disable the
+use of JIT at run time. It is provided for testing and working around problems.
+It should never be needed in normal use.
+
+
+-O text, --output=text
+When there is a match, instead of outputting the line that matched, output just
+the text specified in this option, followed by an operating-system standard
+newline. In this mode, --colour has no effect, and no context is shown.
+That is, the -A, -B, and -C options are ignored. The
+--newline option has no effect on this option, which is mutually
+exclusive with --only-matching, --file-offsets, and
+--line-offsets. However, like --only-matching, if there is more
+than one match in a line, each of them causes a line of output.
+
+
+Escape sequences starting with a dollar character may be used to insert the
+contents of the matched part of the line and/or captured substrings into the
+text.
+
+
+$<digits> or ${<digits>} is replaced by the captured substring of the given
+decimal number; $& (or the legacy $0) substitutes the whole match. If the
+number is greater than the number of capturing substrings, or if the capture
+is unset, the replacement is empty.
+
+
+$a is replaced by bell; $b by backspace; $e by escape; $f by form feed; $n by
+newline; $r by carriage return; $t by tab; $v by vertical tab.
+
+
+$o<digits> or $o{<digits>} is replaced by the character whose code point is the
+given octal number. In the first form, up to three octal digits are processed.
+When more digits are needed in Unicode mode to specify a wide character, the
+second form must be used.
+
+
+$x<digits> or $x{<digits>} is replaced by the character represented by the
+given hexadecimal number. In the first form, up to two hexadecimal digits are
+processed. When more digits are needed in Unicode mode to specify a wide
+character, the second form must be used.
+
+
+Any other character is substituted by itself. In particular, $$ is replaced by
+a single dollar.
+
+
+-o, --only-matching
+Show only the part of the line that matched a pattern instead of the whole
+line. In this mode, no context is shown. That is, the -A, -B, and
+-C options are ignored. If there is more than one match in a line, each
+of them is shown separately, on a separate line of output. If -o is
+combined with -v (invert the sense of the match to find non-matching
+lines), no output is generated, but the return code is set appropriately. If
+the matched portion of the line is empty, nothing is output unless the file
+name or line number are being printed, in which case they are shown on an
+otherwise empty line. This option is mutually exclusive with --output,
+--file-offsets and --line-offsets.
+
+
+-onumber, --only-matching=number
+Show only the part of the line that matched the capturing parentheses of the
+given number. Up to 50 capturing parentheses are supported by default. This
+limit can be changed via the --om-capture option. A pattern may contain
+any number of capturing parentheses, but only those whose number is within the
+limit can be accessed by -o. An error occurs if the number specified by
+-o is greater than the limit.
+
+
+-o0 is the same as -o without a number. Because these options can be
+given without an argument (see above), if an argument is present, it must be
+given in the same shell item, for example, -o3 or --only-matching=2. The
+comments given for the non-argument case above also apply to this option. If
+the specified capturing parentheses do not exist in the pattern, or were not
+set in the match, nothing is output unless the file name or line number are
+being output.
+
+
+If this option is given multiple times, multiple substrings are output for each
+match, in the order the options are given, and all on one line. For example,
+-o3 -o1 -o3 causes the substrings matched by capturing parentheses 3 and 1 and
+then 3 again to be output. By default, there is no separator (but see the next
+but one option).
+
+
+--om-capture=number
+Set the number of capturing parentheses that can be accessed by -o. The
+default is 50.
+
+
+--om-separator=text
+Specify a separating string for multiple occurrences of -o. The default
+is an empty string. Separating strings are never coloured.
+
+
+-P, --no-ucp
+Starting from release 10.43, when UTF/Unicode mode is specified with -u
+or -U, the PCRE2_UCP option is used by default. This means that the
+POSIX classes in patterns match more than just ASCII characters. For example,
+[:digit:] matches any Unicode decimal digit. The --no-ucp option
+suppresses PCRE2_UCP, thus restricting the POSIX classes to ASCII characters,
+as was the case in earlier releases. Note that there are now more fine-grained
+option settings within patterns that affect individual classes. For example,
+when in UCP mode, the sequence (?aP) restricts [:word:] to ASCII letters, while
+allowing \w to match Unicode letters and digits.
+
+
+--posix-pattern-file
+When patterns are provided with the -f option, do not trim trailing
+spaces or ignore empty lines in a similar way than other grep tools. To keep
+the behaviour consistent with older versions, if the pattern read was
+terminated with CRLF (as character literals) then both characters won't be
+included as part of it, so if you really need to have pattern ending in '\r',
+use a escape sequence or provide it by a different method.
+
+
+-q, --quiet
+Work quietly, that is, display nothing except error messages. The exit
+status indicates whether or not any matches were found.
+
+
+-r, --recursive
+If any given path is a directory, recursively scan the files it contains,
+taking note of any --include and --exclude settings. By default, a
+directory is read as a normal file; in some operating systems this gives an
+immediate end-of-file. This option is a shorthand for setting the -d
+option to "recurse".
+
+
+--recursion-limit=number
+This is an obsolete synonym for --depth-limit. See --match-limit
+above for details.
+
+
+-s, --no-messages
+Suppress error messages about non-existent or unreadable files. Such files are
+quietly skipped. However, the return code is still 2, even if matches were
+found in other files.
+
+
+-t, --total-count
+This option is useful when scanning more than one file. If used on its own,
+-t suppresses all output except for a grand total number of matching
+lines (or non-matching lines if -v is used) in all the files. If -t
+is used with -c, a grand total is output except when the previous output
+is just one line. In other words, it is not output when just one file's count
+is listed. If file names are being output, the grand total is preceded by
+"TOTAL:". Otherwise, it appears as just another number. The -t option is
+ignored when used with -L (list files without matches), because the grand
+total would always be zero.
+
+
+-u, --utf
+Operate in UTF/Unicode mode. This option is available only if PCRE2 has been
+compiled with UTF-8 support. All patterns (including those for any
+--exclude and --include options) and all lines that are scanned
+must be valid strings of UTF-8 characters. If an invalid UTF-8 string is
+encountered, an error occurs.
+
+
+-U, --utf-allow-invalid
+As --utf, but in addition subject lines may contain invalid UTF-8 code
+unit sequences. These can never form part of any pattern match. Patterns
+themselves, however, must still be valid UTF-8 strings. This facility allows
+valid UTF-8 strings to be sought within arbitrary byte sequences in executable
+or other binary files. For more details about matching in non-valid UTF-8
+strings, see the
+pcre2unicode(3)
+documentation.
+
+
+-V, --version
+Write the version numbers of pcre2grep and the PCRE2 library to the
+standard output and then exit. Anything else on the command line is
+ignored.
+
+
+-v, --invert-match
+Invert the sense of the match, so that lines which do not match any of
+the patterns are the ones that are found. When this option is set, options such
+as --only-matching and --output, which specify parts of a match
+that are to be output, are ignored.
+
+
+-w, --word-regex, --word-regexp
+Force the patterns only to match "words". That is, there must be a word
+boundary at the start and end of each matched string. This is equivalent to
+having "\b(?:" at the start of each pattern, and ")\b" at the end. This
+option applies only to the patterns that are matched against the contents of
+files; it does not apply to patterns specified by any of the --include or
+--exclude options.
+
+
+-x, --line-regex, --line-regexp
+Force the patterns to start matching only at the beginnings of lines, and in
+addition, require them to match entire lines. In multiline mode the match may
+be more than one line. This is equivalent to having "^(?:" at the start of each
+pattern and ")$" at the end. This option applies only to the patterns that are
+matched against the contents of files; it does not apply to patterns specified
+by any of the --include or --exclude options.
+
+
+-Z, --null
+Terminate files names in the regular output with a zero byte (the NUL
+character) instead of what would normally appear. This is useful when file
+names contain unusual characters such as colons, hyphens, or even newlines. The
+option does not apply to file names in error messages.
+
+
+
+The environment variables LC_ALL and LC_CTYPE are examined, in that
+order, for a locale. The first one that is set is used. This can be overridden
+by the --locale option. If no locale is set, the PCRE2 library's default
+(usually the "C" locale) is used.
+
+
+
+The -N (--newline) option allows pcre2grep to scan files with
+newline conventions that differ from the default. This option affects only the
+way scanned files are processed. It does not affect the interpretation of files
+specified by the -f, --file-list, --exclude-from, or
+--include-from options.
+
+
+Any parts of the scanned input files that are written to the standard output
+are copied with whatever newline sequences they have in the input. However, if
+the final line of a file is output, and it does not end with a newline
+sequence, a newline sequence is added. If the newline setting is CR, LF, CRLF
+or NUL, that line ending is output; for the other settings (ANYCRLF or ANY) a
+single NL is used.
+
+
+The newline setting does not affect the way in which pcre2grep writes
+newlines in informational messages to the standard output and error streams.
+Under Windows, the standard output is set to be binary, so that "\r\n" at the
+ends of output lines that are copied from the input is not converted to
+"\r\r\n" by the C I/O library. This means that any messages written to the
+standard output must end with "\r\n". For all other operating systems, and
+for all messages to the standard error stream, "\n" is used.
+
+
+
+Many of the short and long forms of pcre2grep's options are the same as
+in the GNU grep program. Any long option of the form --xxx-regexp
+(GNU terminology) is also available as --xxx-regex (PCRE2 terminology).
+However, the --case-restrict, --depth-limit, -E,
+--file-list, --file-offsets, --heap-limit,
+--include-dir, --line-offsets, --locale, --match-limit,
+-M, --multiline, -N, --newline, --no-ucp,
+--om-separator, --output, -P, -u, --utf,
+-U, and --utf-allow-invalid options are specific to
+pcre2grep, as is the use of the --only-matching option with a
+capturing parentheses number.
+
+
+Although most of the common options work the same way, a few are different in
+pcre2grep. For example, the --include option's argument is a glob
+for GNU grep, but in pcre2grep it is a regular expression to which
+the -i option applies. If both the -c and -l options are
+given, GNU grep lists only file names, without counts, but pcre2grep
+gives the counts as well.
+
+
+
+There are four different ways in which an option with data can be specified.
+If a short form option is used, the data may follow immediately, or (with one
+exception) in the next command line item. For example:
+
+ -f/some/file
+ -f /some/file
+
+The exception is the -o option, which may appear with or without data.
+Because of this, if data is present, it must follow immediately in the same
+item, for example -o3.
+
+
+If a long form option is used, the data may appear in the same command line
+item, separated by an equals character, or (with two exceptions) it may appear
+in the next command line item. For example:
+
+ --file=/some/file
+ --file /some/file
+
+Note, however, that if you want to supply a file name beginning with ~ as data
+in a shell command, and have the shell expand ~ to a home directory, you must
+separate the file name from the option, because the shell does not treat ~
+specially unless it is at the start of an item.
+
+
+The exceptions to the above are the --colour (or --color) and
+--only-matching options, for which the data is optional. If one of these
+options does have data, it must be given in the first form, using an equals
+character. Otherwise pcre2grep will assume that it has no data.
+
+
+
+pcre2grep has, by default, support for calling external programs or
+scripts or echoing specific strings during matching by making use of PCRE2's
+callout facility. However, this support can be completely or partially disabled
+when pcre2grep is built. You can find out whether your binary has support
+for callouts by running it with the --help option. If callout support is
+completely disabled, callouts in patterns are forbidden by pcre2grep.
+If the facility is partially disabled, calling external programs is not
+supported, and callouts that request it are ignored.
+
+
+A callout in a PCRE2 pattern is of the form (?C<arg>) where the argument is
+either a number or a quoted string (see the
+pcre2callout
+documentation for details). Numbered callouts are ignored by pcre2grep;
+only callouts with string arguments are useful.
+
+
+Echoing a specific string
+
+
+Starting the callout string with a pipe character invokes an echoing facility
+that avoids calling an external program or script. This facility is always
+available, provided that callouts were not completely disabled when
+pcre2grep was built. The rest of the callout string is processed as a
+zero-terminated string, which means it should not contain any internal binary
+zeros. It is written to the output, having first been passed through the same
+escape processing as text from the --output (-O) option (see
+above). However, $0 or $& cannot be used to insert a matched substring because
+the match is still in progress. Instead, the single character '0' is inserted.
+Any syntax errors in the string (for example, a dollar not followed by another
+character) causes the callout to be ignored. No terminator is added to the
+output string, so if you want a newline, you must include it explicitly using
+the escape $n. For example:
+
+ pcre2grep '(.)(..(.))(?C"|[$1] [$2] [$3]$n")' <some file>
+
+Matching continues normally after the string is output. If you want to see only
+the callout output but not any output from an actual match, you should end the
+pattern with (*FAIL).
+
+
+Calling external programs or scripts
+
+
+This facility can be independently disabled when pcre2grep is built. It
+is supported for Windows, where a call to _spawnvp() is used, for VMS,
+where lib$spawn() is used, and for any Unix-like environment where
+fork() and execv() are available.
+
+
+If the callout string does not start with a pipe (vertical bar) character, it
+is parsed into a list of substrings separated by pipe characters. The first
+substring must be an executable name, with the following substrings specifying
+arguments:
+
+ executable_name|arg1|arg2|...
+
+Any substring (including the executable name) may contain escape sequences
+started by a dollar character. These are the same as for the --output
+(-O) option documented above, except that $0 or $& cannot insert the
+matched string because the match is still in progress. Instead, the character
+'0' is inserted. If you need a literal dollar or pipe character in any
+substring, use $$ or $| respectively. Here is an example:
+
+ echo -e "abcde\n12345" | pcre2grep \
+ '(?x)(.)(..(.))
+ (?C"/bin/echo|Arg1: [$1] [$2] [$3]|Arg2: $|${1}$| ($4)")()' -
+
+ Output:
+
+ Arg1: [a] [bcd] [d] Arg2: |a| ()
+ abcde
+ Arg1: [1] [234] [4] Arg2: |1| ()
+ 12345
+
+The parameters for the system call that is used to run the program or script
+are zero-terminated strings. This means that binary zero characters in the
+callout argument will cause premature termination of their substrings, and
+therefore should not be present. Any syntax errors in the string (for example,
+a dollar not followed by another character) causes the callout to be ignored.
+If running the program fails for any reason (including the non-existence of the
+executable), a local matching failure occurs and the matcher backtracks in the
+normal way.
+
+
+
+It is possible to supply a regular expression that takes a very long time to
+fail to match certain lines. Such patterns normally involve nested indefinite
+repeats, for example: (a+)*\d when matched against a line of a's with no final
+digit. The PCRE2 matching function has a resource limit that causes it to abort
+in these circumstances. If this happens, pcre2grep outputs an error
+message and the line that caused the problem to the standard error stream. If
+there are more than 20 such errors, pcre2grep gives up.
+
+
+The --match-limit option of pcre2grep can be used to set the
+overall resource limit. There are also other limits that affect the amount of
+memory used during matching; see the discussion of --heap-limit and
+--depth-limit above.
+
+
+
+Exit status is 0 if any matches were found, 1 if no matches were found, and 2
+for syntax errors, overlong lines, non-existent or inaccessible files (even if
+matches were found in other files) or too many matching errors. Using the
+-s option to suppress error messages about inaccessible files does not
+affect the return code.
+
+
+When run under VMS, the return code is placed in the symbol PCRE2GREP_RC
+because VMS does not distinguish between exit(0) and exit(1).
+
+
+
+pcre2pattern(3), pcre2syntax(3), pcre2callout(3),
+pcre2unicode(3).
+
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+
+Last updated: 24 January 2025
+
+Copyright © 1997-2023 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2jit.html b/doc/html/pcre2jit.html
new file mode 100644
index 0000000..c3f18f4
--- /dev/null
+++ b/doc/html/pcre2jit.html
@@ -0,0 +1,506 @@
+
+
+pcre2jit specification
+
+
+pcre2jit man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+Just-in-time compiling is a heavyweight optimization that can greatly speed up
+pattern matching. However, it comes at the cost of extra processing before the
+match is performed, so it is of most benefit when the same pattern is going to
+be matched many times. This does not necessarily mean many calls of a matching
+function; if the pattern is not anchored, matching attempts may take place many
+times at various positions in the subject, even for a single call. Therefore,
+if the subject string is very long, it may still pay to use JIT even for
+one-off matches. JIT support is available for all of the 8-bit, 16-bit and
+32-bit PCRE2 libraries.
+
+
+JIT support applies only to the traditional Perl-compatible matching function.
+It does not apply when the DFA matching function is being used. The code for
+JIT support was written by Zoltan Herczeg.
+
+
+
+JIT support is an optional feature of PCRE2. The "configure" option
+--enable-jit (or equivalent CMake option) must be set when PCRE2 is built if
+you want to use JIT. The support is limited to the following hardware
+platforms:
+
+ ARM 32-bit (v7, and Thumb2)
+ ARM 64-bit
+ IBM s390x 64 bit
+ Intel x86 32-bit and 64-bit
+ LoongArch 64 bit
+ MIPS 32-bit and 64-bit
+ Power PC 32-bit and 64-bit
+ RISC-V 32-bit and 64-bit
+
+If --enable-jit is set on an unsupported platform, compilation fails.
+
+
+A client program can tell if JIT support has been compiled by calling
+pcre2_config() with the PCRE2_CONFIG_JIT option. The result is one if
+PCRE2 was built with JIT support, and zero otherwise. However, having the JIT
+code available does not guarantee that it will be used for any particular
+match. One reason for this is that there are a number of options and pattern
+items that are
+not supported by JIT
+(see below). Another reason is that in some environments JIT is unable to get
+executable memory in which to build its compiled code. The only guarantee from
+pcre2_config() is that if it returns zero, JIT will definitely not
+be used.
+
+
+As of release 10.45 there is a more informative way to test for JIT support. If
+pcre2_compile_jit() is called with the single option PCRE2_JIT_TEST_ALLOC
+it returns zero if JIT is available and has a working allocator. Otherwise it
+returns PCRE2_ERROR_NOMEMORY if JIT is available but cannot allocate executable
+memory, or PCRE2_ERROR_JIT_UNSUPPORTED if JIT support is not compiled. The
+code argument is ignored, so it can be a NULL value.
+
+
+A simple program does not need to check availability in order to use JIT when
+possible. The API is implemented in a way that falls back to the interpretive
+code if JIT is not available or cannot be used for a given match. For programs
+that need the best possible performance, there is a
+"fast path"
+API that is JIT-specific.
+
+
+
+To make use of the JIT support in the simplest way, all you have to do is to
+call pcre2_jit_compile() after successfully compiling a pattern with
+pcre2_compile(). This function has two arguments: the first is the
+compiled pattern pointer that was returned by pcre2_compile(), and the
+second is zero or more of the following option bits: PCRE2_JIT_COMPLETE,
+PCRE2_JIT_PARTIAL_HARD, or PCRE2_JIT_PARTIAL_SOFT.
+
+
+If JIT support is not available, a call to pcre2_jit_compile() does
+nothing and returns PCRE2_ERROR_JIT_BADOPTION. Otherwise, the compiled pattern
+is passed to the JIT compiler, which turns it into machine code that executes
+much faster than the normal interpretive code, but yields exactly the same
+results. The returned value from pcre2_jit_compile() is zero on success,
+or a negative error code.
+
+
+There is a limit to the size of pattern that JIT supports, imposed by the size
+of machine stack that it uses. The exact rules are not documented because they
+may change at any time, in particular, when new optimizations are introduced.
+If a pattern is too big, a call to pcre2_jit_compile() returns
+PCRE2_ERROR_NOMEMORY.
+
+
+PCRE2_JIT_COMPLETE requests the JIT compiler to generate code for complete
+matches. If you want to run partial matches using the PCRE2_PARTIAL_HARD or
+PCRE2_PARTIAL_SOFT options of pcre2_match(), you should set one or both
+of the other options as well as, or instead of PCRE2_JIT_COMPLETE. The JIT
+compiler generates different optimized code for each of the three modes
+(normal, soft partial, hard partial). When pcre2_match() is called, the
+appropriate code is run if it is available. Otherwise, the pattern is matched
+using interpretive code.
+
+
+You can call pcre2_jit_compile() multiple times for the same compiled
+pattern. It does nothing if it has previously compiled code for any of the
+option bits. For example, you can call it once with PCRE2_JIT_COMPLETE and
+(perhaps later, when you find you need partial matching) again with
+PCRE2_JIT_COMPLETE and PCRE2_JIT_PARTIAL_HARD. This time it will ignore
+PCRE2_JIT_COMPLETE and just compile code for partial matching. If
+pcre2_jit_compile() is called with no option bits set, it immediately
+returns zero. This is an alternative way of testing whether JIT support has
+been compiled.
+
+
+At present, it is not possible to free JIT compiled code except when the entire
+compiled pattern is freed by calling pcre2_code_free().
+
+
+In some circumstances you may need to call additional functions. These are
+described in the section entitled
+"Controlling the JIT stack"
+below.
+
+
+There are some pcre2_match() options that are not supported by JIT, and
+there are also some pattern items that JIT cannot handle. Details are given
+below.
+In both cases, matching automatically falls back to the interpretive code. If
+you want to know whether JIT was actually used for a particular match, you
+should arrange for a JIT callback function to be set up as described in the
+section entitled
+"Controlling the JIT stack"
+below, even if you do not need to supply a non-default JIT stack. Such a
+callback function is called whenever JIT code is about to be obeyed. If the
+match-time options are not right for JIT execution, the callback function is
+not obeyed.
+
+
+If the JIT compiler finds an unsupported item, no JIT data is generated. You
+can find out if JIT compilation was successful for a compiled pattern by
+calling pcre2_pattern_info() with the PCRE2_INFO_JITSIZE option. A
+non-zero result means that JIT compilation was successful. A result of 0 means
+that JIT support is not available, or the pattern was not processed by
+pcre2_jit_compile(), or the JIT compiler was not able to handle the
+pattern. Successful JIT compilation does not, however, guarantee the use of JIT
+at match time because there are some match time options that are not supported
+by JIT.
+
+
+
+When a pattern is compiled with the PCRE2_UTF option, subject strings are
+normally expected to be a valid sequence of UTF code units. By default, this is
+checked at the start of matching and an error is generated if invalid UTF is
+detected. The PCRE2_NO_UTF_CHECK option can be passed to pcre2_match() to
+skip the check (for improved performance) if you are sure that a subject string
+is valid. If this option is used with an invalid string, the result is
+undefined. The calling program may crash or loop or otherwise misbehave.
+
+
+However, a way of running matches on strings that may contain invalid UTF
+sequences is available. Calling pcre2_compile() with the
+PCRE2_MATCH_INVALID_UTF option has two effects: it tells the interpreter in
+pcre2_match() to support invalid UTF, and, if pcre2_jit_compile()
+is subsequently called, the compiled JIT code also supports invalid UTF.
+Details of how this support works, in both the JIT and the interpretive cases,
+is given in the
+pcre2unicode
+documentation.
+
+
+There is also an obsolete option for pcre2_jit_compile() called
+PCRE2_JIT_INVALID_UTF, which currently exists only for backward compatibility.
+It is superseded by the pcre2_compile() option PCRE2_MATCH_INVALID_UTF
+and should no longer be used. It may be removed in future.
+
+
+
+The pcre2_match() options that are supported for JIT matching are
+PCRE2_COPY_MATCHED_SUBJECT, PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY,
+PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and
+PCRE2_PARTIAL_SOFT. The PCRE2_ANCHORED and PCRE2_ENDANCHORED options are not
+supported at match time.
+
+
+If the PCRE2_NO_JIT option is passed to pcre2_match() it disables the
+use of JIT, forcing matching by the interpreter code.
+
+
+The only unsupported pattern items are \C (match a single data unit) when
+running in a UTF mode, and a callout immediately before an assertion condition
+in a conditional group.
+
+
+
+When a pattern is matched using JIT, the return values are the same as those
+given by the interpretive pcre2_match() code, with the addition of one
+new error code: PCRE2_ERROR_JIT_STACKLIMIT. This means that the memory used for
+the JIT stack was insufficient. See
+"Controlling the JIT stack"
+below for a discussion of JIT stack usage.
+
+
+The error code PCRE2_ERROR_MATCHLIMIT is returned by the JIT code if searching
+a very large pattern tree goes on for too long, as it is in the same
+circumstance when JIT is not used, but the details of exactly what is counted
+are not the same. The PCRE2_ERROR_DEPTHLIMIT error code is never returned
+when JIT matching is used.
+
+
+
+When the compiled JIT code runs, it needs a block of memory to use as a stack.
+By default, it uses 32KiB on the machine stack. However, some large or
+complicated patterns need more than this. The error PCRE2_ERROR_JIT_STACKLIMIT
+is given when there is not enough stack. Three functions are provided for
+managing blocks of memory for use as JIT stacks. There is further discussion
+about the use of JIT stacks in the section entitled
+"JIT stack FAQ"
+below.
+
+
+The pcre2_jit_stack_create() function creates a JIT stack. Its arguments
+are a starting size, a maximum size, and a general context (for memory
+allocation functions, or NULL for standard memory allocation). It returns a
+pointer to an opaque structure of type pcre2_jit_stack, or NULL if there
+is an error. The pcre2_jit_stack_free() function is used to free a stack
+that is no longer needed. If its argument is NULL, this function returns
+immediately, without doing anything. (For the technically minded: the address
+space is allocated by mmap or VirtualAlloc.) A maximum stack size of 512KiB to
+1MiB should be more than enough for any pattern.
+
+
+The pcre2_jit_stack_assign() function specifies which stack JIT code
+should use. Its arguments are as follows:
+
+ pcre2_match_context *mcontext
+ pcre2_jit_callback callback
+ void *data
+
+The first argument is a pointer to a match context. When this is subsequently
+passed to a matching function, its information determines which JIT stack is
+used. If this argument is NULL, the function returns immediately, without doing
+anything. There are three cases for the values of the other two options:
+
+ (1) If callback is NULL and data is NULL, an internal 32KiB block
+ on the machine stack is used. This is the default when a match
+ context is created.
+
+ (2) If callback is NULL and data is not NULL, data must be
+ a pointer to a valid JIT stack, the result of calling
+ pcre2_jit_stack_create().
+
+ (3) If callback is not NULL, it must point to a function that is
+ called with data as an argument at the start of matching, in
+ order to set up a JIT stack. If the return from the callback
+ function is NULL, the internal 32KiB stack is used; otherwise the
+ return value must be a valid JIT stack, the result of calling
+ pcre2_jit_stack_create().
+
+A callback function is obeyed whenever JIT code is about to be run; it is not
+obeyed when pcre2_match() is called with options that are incompatible
+for JIT matching. A callback function can therefore be used to determine
+whether a match operation was executed by JIT or by the interpreter.
+
+
+You may safely use the same JIT stack for more than one pattern (either by
+assigning directly or by callback), as long as the patterns are matched
+sequentially in the same thread. Currently, the only way to set up
+non-sequential matches in one thread is to use callouts: if a callout function
+starts another match, that match must use a different JIT stack to the one used
+for currently suspended match(es).
+
+
+In a multithread application, if you do not specify a JIT stack, or if you
+assign or pass back NULL from a callback, that is thread-safe, because each
+thread has its own machine stack. However, if you assign or pass back a
+non-NULL JIT stack, this must be a different stack for each thread so that the
+application is thread-safe.
+
+
+Strictly speaking, even more is allowed. You can assign the same non-NULL stack
+to a match context that is used by any number of patterns, as long as they are
+not used for matching by multiple threads at the same time. For example, you
+could use the same stack in all compiled patterns, with a global mutex in the
+callback to wait until the stack is available for use. However, this is an
+inefficient solution, and not recommended.
+
+
+This is a suggestion for how a multithreaded program that needs to set up
+non-default JIT stacks might operate:
+
+ During thread initialization
+ thread_local_var = pcre2_jit_stack_create(...)
+
+ During thread exit
+ pcre2_jit_stack_free(thread_local_var)
+
+ Use a one-line callback function
+ return thread_local_var
+
+All the functions described in this section do nothing if JIT is not available.
+
+
+
+(1) Why do we need JIT stacks?
+
+
+PCRE2 (and JIT) is a recursive, depth-first engine, so it needs a stack where
+the local data of the current node is pushed before checking its child nodes.
+Allocating real machine stack on some platforms is difficult. For example, the
+stack chain needs to be updated every time if we extend the stack on PowerPC.
+Although it is possible, its updating time overhead decreases performance. So
+we do the recursion in memory.
+
+
+(2) Why don't we simply allocate blocks of memory with malloc()?
+
+
+Modern operating systems have a nice feature: they can reserve an address space
+instead of allocating memory. We can safely allocate memory pages inside this
+address space, so the stack could grow without moving memory data (this is
+important because of pointers). Thus we can allocate 1MiB address space, and
+use only a single memory page (usually 4KiB) if that is enough. However, we can
+still grow up to 1MiB anytime if needed.
+
+
+(3) Who "owns" a JIT stack?
+
+
+The owner of the stack is the user program, not the JIT studied pattern or
+anything else. The user program must ensure that if a stack is being used by
+pcre2_match(), (that is, it is assigned to a match context that is passed
+to the pattern currently running), that stack must not be used by any other
+threads (to avoid overwriting the same memory area). The best practice for
+multithreaded programs is to allocate a stack for each thread, and return this
+stack through the JIT callback function.
+
+
+(4) When should a JIT stack be freed?
+
+
+You can free a JIT stack at any time, as long as it will not be used by
+pcre2_match() again. When you assign the stack to a match context, only a
+pointer is set. There is no reference counting or any other magic. You can free
+compiled patterns, contexts, and stacks in any order, anytime.
+Just do not call pcre2_match() with a match context pointing to an
+already freed stack, as that will cause SEGFAULT. (Also, do not free a stack
+currently used by pcre2_match() in another thread). You can also replace
+the stack in a context at any time when it is not in use. You should free the
+previous stack before assigning a replacement.
+
+
+(5) Should I allocate/free a stack every time before/after calling
+pcre2_match()?
+
+
+No, because this is too costly in terms of resources. However, you could
+implement some clever idea which release the stack if it is not used in let's
+say two minutes. The JIT callback can help to achieve this without keeping a
+list of patterns.
+
+
+(6) OK, the stack is for long term memory allocation. But what happens if a
+pattern causes stack overflow with a stack of 1MiB? Is that 1MiB kept until the
+stack is freed?
+
+
+Especially on embedded systems, it might be a good idea to release memory
+sometimes without freeing the stack. There is no API for this at the moment.
+Probably a function call which returns with the currently allocated memory for
+any stack and another which allows releasing memory (shrinking the stack) would
+be a good idea if someone needs this.
+
+
+(7) This is too much of a headache. Isn't there any better solution for JIT
+stack handling?
+
+
+No, thanks to Windows. If POSIX threads were used everywhere, we could throw
+out this complicated API.
+
+
+
+void pcre2_jit_free_unused_memory(pcre2_general_context *gcontext);
+
+
+The JIT executable allocator does not free all memory when it is possible. It
+expects new allocations, and keeps some free memory around to improve
+allocation speed. However, in low memory conditions, it might be better to free
+all possible memory. You can cause this to happen by calling
+pcre2_jit_free_unused_memory(). Its argument is a general context, for custom
+memory management, or NULL for standard memory management.
+
+
+
+This is a single-threaded example that specifies a JIT stack without using a
+callback. A real program should include error checking after all the function
+calls.
+
+ int rc;
+ pcre2_code *re;
+ pcre2_match_data *match_data;
+ pcre2_match_context *mcontext;
+ pcre2_jit_stack *jit_stack;
+
+ re = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED, 0,
+ &errornumber, &erroffset, NULL);
+ rc = pcre2_jit_compile(re, PCRE2_JIT_COMPLETE);
+ mcontext = pcre2_match_context_create(NULL);
+ jit_stack = pcre2_jit_stack_create(32*1024, 512*1024, NULL);
+ pcre2_jit_stack_assign(mcontext, NULL, jit_stack);
+ match_data = pcre2_match_data_create(re, 10);
+ rc = pcre2_match(re, subject, length, 0, 0, match_data, mcontext);
+ /* Process result */
+
+ pcre2_code_free(re);
+ pcre2_match_data_free(match_data);
+ pcre2_match_context_free(mcontext);
+ pcre2_jit_stack_free(jit_stack);
+
+
+
+
+
+Because the API described above falls back to interpreted matching when JIT is
+not available, it is convenient for programs that are written for general use
+in many environments. However, calling JIT via pcre2_match() does have a
+performance impact. Programs that are written for use where JIT is known to be
+available, and which need the best possible performance, can instead use a
+"fast path" API to call JIT matching directly instead of calling
+pcre2_match() (obviously only for patterns that have been successfully
+processed by pcre2_jit_compile()).
+
+
+The fast path function is called pcre2_jit_match(), and it takes exactly
+the same arguments as pcre2_match(). However, the subject string must be
+specified with a length; PCRE2_ZERO_TERMINATED is not supported. Unsupported
+option bits (for example, PCRE2_ANCHORED, PCRE2_ENDANCHORED, and
+PCRE2_COPY_MATCHED_SUBJECT) are ignored, as is the PCRE2_NO_JIT option. The
+return values are also the same as for pcre2_match(), plus
+PCRE2_ERROR_JIT_BADOPTION if a matching mode (partial or complete) is requested
+that was not compiled.
+
+
+When you call pcre2_match(), as well as testing for invalid options, a
+number of other sanity checks are performed on the arguments. For example, if
+the subject pointer is NULL but the length is non-zero, an immediate error is
+given. Also, unless PCRE2_NO_UTF_CHECK is set, a UTF subject string is tested
+for validity. In the interests of speed, these checks do not happen on the JIT
+fast path. If invalid UTF data is passed when PCRE2_MATCH_INVALID_UTF was not
+set for pcre2_compile(), the result is undefined. The program may crash
+or loop or give wrong results. In the absence of PCRE2_MATCH_INVALID_UTF you
+should call pcre2_jit_match() in UTF mode only if you are sure the
+subject is valid.
+
+
+Bypassing the sanity checks and the pcre2_match() wrapping can give
+speedups of more than 10%.
+
+
+
+pcre2api(3), pcre2unicode(3)
+
+
+
+Philip Hazel (FAQ by Zoltan Herczeg)
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+
+Last updated: 08 August 2026
+
+Copyright © 1997-2024 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2limits.html b/doc/html/pcre2limits.html
new file mode 100644
index 0000000..968a7f2
--- /dev/null
+++ b/doc/html/pcre2limits.html
@@ -0,0 +1,108 @@
+
+
+pcre2limits specification
+
+
+pcre2limits man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+SIZE AND OTHER LIMITATIONS
+
+
+There are some size limitations in PCRE2 but it is hoped that they will never
+in practice be relevant.
+
+
+The maximum size of a compiled pattern is approximately 64 thousand code units
+for the 8-bit and 16-bit libraries if PCRE2 is compiled with the default
+internal linkage size, which is 2 bytes for these libraries. If you want to
+process regular expressions that are truly enormous, you can compile PCRE2 with
+an internal linkage size of 3 or 4 (when building the 16-bit library, 3 is
+rounded up to 4). See the README file in the source distribution and the
+pcre2build
+documentation for details. In these cases the limit is substantially larger.
+However, the speed of execution is slower. In the 32-bit library, the internal
+linkage size is always 4.
+
+
+The maximum length of a source pattern string is essentially unlimited; it is
+the largest number a PCRE2_SIZE variable can hold. However, the program that
+calls pcre2_compile() can specify a smaller limit.
+
+
+The maximum length (in code units) of a subject string is one less than the
+largest number a PCRE2_SIZE variable can hold. PCRE2_SIZE is an unsigned
+integer type, usually defined as size_t. Its maximum value (that is
+~(PCRE2_SIZE)0) is reserved as a special indicator for zero-terminated strings
+and unset offsets.
+
+
+All values in repeating quantifiers must be less than 65536.
+
+
+There are two different limits that apply to branches of lookbehind assertions.
+If every branch in such an assertion matches a fixed number of characters,
+the maximum length of any branch is 65535 characters. If any branch matches a
+variable number of characters, then the maximum matching length for every
+branch is limited. The default limit is set at compile time, defaulting to 255,
+but can be changed by the calling program.
+
+
+There is no limit to the number of parenthesized groups, but there can be no
+more than 65535 capture groups, and there is a limit to the depth of nesting of
+parenthesized subpatterns of all kinds. This is imposed in order to limit the
+amount of system stack used at compile time. The default limit can be specified
+when PCRE2 is built; if not, the default is set to 250. An application can
+change this limit by calling pcre2_set_parens_nest_limit() to set the limit in
+a compile context.
+
+
+The maximum length of the name for a named capture group as well as the number
+of such groups is configurable at build time. The maximum length for the name
+defaults to
+128 code units, and the maximum number of such groups to
+10000.
+
+
+The maximum length of a name in a (*MARK), (*PRUNE), (*SKIP), or (*THEN) verb
+is 255 code units for the 8-bit library and 65535 code units for the 16-bit and
+32-bit libraries.
+
+
+The maximum length of a string argument to a callout is the largest number a
+32-bit unsigned integer can hold.
+
+
+The maximum amount of heap memory used for matching is controlled by the heap
+limit, which can be set in a pattern or in a match context. The default is a
+very large number, effectively unlimited.
+
+
+AUTHOR
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+REVISION
+
+
+Last updated: 03 September 2025
+
+Copyright © 1997-2023 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2matching.html b/doc/html/pcre2matching.html
new file mode 100644
index 0000000..f015355
--- /dev/null
+++ b/doc/html/pcre2matching.html
@@ -0,0 +1,262 @@
+
+
+pcre2matching specification
+
+
+pcre2matching man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+This document describes the two different algorithms that are available in
+PCRE2 for matching a compiled regular expression against a given subject
+string. The "standard" algorithm is the one provided by the pcre2_match()
+function. This works in the same way as Perl's matching function, and provides a
+Perl-compatible matching operation. The just-in-time (JIT) optimization that is
+described in the
+pcre2jit
+documentation is compatible with this function.
+
+
+An alternative algorithm is provided by the pcre2_dfa_match() function;
+it operates in a different way, and is not Perl-compatible. This alternative
+has advantages and disadvantages compared with the standard algorithm, and
+these are described below.
+
+
+When there is only one possible way in which a given subject string can match a
+pattern, the two algorithms give the same answer. A difference arises, however,
+when there are multiple possibilities. For example, if the anchored pattern
+
+ ^<.*>
+
+is matched against the string
+
+ <something> <something else> <something further>
+
+there are three possible answers. The standard algorithm finds only one of
+them, whereas the alternative algorithm finds all three.
+
+
+
+The set of strings that are matched by a regular expression can be represented
+as a tree structure. An unlimited repetition in the pattern makes the tree of
+infinite size, but it is still a tree. Matching the pattern to a given subject
+string (from a given starting point) can be thought of as a search of the tree.
+There are two ways to search a tree: depth-first and breadth-first, and these
+correspond to the two matching algorithms provided by PCRE2.
+
+
+
+In the terminology of Jeffrey Friedl's book "Mastering Regular Expressions",
+the standard algorithm is an "NFA algorithm". It conducts a depth-first search
+of the pattern tree. That is, it proceeds along a single path through the tree,
+checking that the subject matches what is required. When there is a mismatch,
+the algorithm tries any alternatives at the current point, and if they all
+fail, it backs up to the previous branch point in the tree, and tries the next
+alternative branch at that level. This often involves backing up (moving to the
+left) in the subject string as well. The order in which repetition branches are
+tried is controlled by the greedy or ungreedy nature of the quantifier.
+
+
+If a leaf node is reached, a matching string has been found, and at that point
+the algorithm stops. Thus, if there is more than one possible match, this
+algorithm returns the first one that it finds. Whether this is the shortest,
+the longest, or some intermediate length depends on the way the alternations
+and the greedy or ungreedy repetition quantifiers are specified in the
+pattern.
+
+
+Because it ends up with a single path through the tree, it is relatively
+straightforward for this algorithm to keep track of the substrings that are
+matched by portions of the pattern in parentheses. This provides support for
+capturing parentheses and backreferences.
+
+
+
+This algorithm conducts a breadth-first search of the tree. Starting from the
+first matching point in the subject, it scans the subject string from left to
+right, once, character by character, and as it does this, it remembers all the
+paths through the tree that represent valid matches. In Friedl's terminology,
+this is a kind of "DFA algorithm", though it is not implemented as a
+traditional finite state machine (it keeps multiple states active
+simultaneously).
+
+
+Although the general principle of this matching algorithm is that it scans the
+subject string only once, without backtracking, there is one exception: when a
+lookaround assertion is encountered, the characters following or preceding the
+current point have to be independently inspected.
+
+
+The scan continues until either the end of the subject is reached, or there are
+no more unterminated paths. At this point, terminated paths represent the
+different matching possibilities (if there are none, the match has failed).
+Thus, if there is more than one possible match, this algorithm finds all of
+them, and in particular, it finds the longest. The matches are returned in
+the output vector in decreasing order of length. There is an option to stop the
+algorithm after the first match (which is necessarily the shortest) is found.
+
+
+Note that the size of vector needed to contain all the results depends on the
+number of simultaneous matches, not on the number of capturing parentheses in
+the pattern. Using pcre2_match_data_create_from_pattern() to create the
+match data block is therefore not advisable when doing DFA matching.
+
+
+Note also that all the matches that are found start at the same point in the
+subject. If the pattern
+
+ cat(er(pillar)?)?
+
+is matched against the string "the caterpillar catchment", the result is the
+three strings "caterpillar", "cater", and "cat" that start at the fifth
+character of the subject. The algorithm does not automatically move on to find
+matches that start at later positions.
+
+
+PCRE2's "auto-possessification" optimization usually applies to character
+repeats at the end of a pattern (as well as internally). For example, the
+pattern "a\d+" is compiled as if it were "a\d++" because there is no point
+even considering the possibility of backtracking into the repeated digits. For
+DFA matching, this means that only one possible match is found. If you really
+do want multiple matches in such cases, either use an ungreedy repeat
+("a\d+?") or set the PCRE2_NO_AUTO_POSSESS option when compiling.
+
+
+There are a number of features of PCRE2 regular expressions that are not
+supported or behave differently in the alternative matching function. Those
+that are not supported cause an error if encountered.
+
+
+1. Because the algorithm finds all possible matches, the greedy or ungreedy
+nature of repetition quantifiers is not relevant (though it may affect
+auto-possessification, as just described). During matching, greedy and ungreedy
+quantifiers are treated in exactly the same way. However, possessive
+quantifiers can make a difference when what follows could also match what is
+quantified, for example in a pattern like this:
+
+ ^a++\w!
+
+This pattern matches "aaab!" but not "aaa!", which would be matched by a
+non-possessive quantifier. Similarly, if an atomic group is present, it is
+matched as if it were a standalone pattern at the current point, and the
+longest match is then "locked in" for the rest of the overall pattern.
+
+
+2. When dealing with multiple paths through the tree simultaneously, it is not
+straightforward to keep track of captured substrings for the different matching
+possibilities, and PCRE2's implementation of this algorithm does not attempt to
+do this. This means that no captured substrings are available.
+
+
+3. Because no substrings are captured, a number of related features are not
+available:
+
+
+(a) Backreferences;
+
+
+(b) Conditional expressions that use a backreference as the condition or test
+for a specific group recursion;
+
+
+(c) Script runs;
+
+
+(d) Scan substring assertions.
+
+
+4. Because many paths through the tree may be active, the \K escape sequence,
+which resets the start of the match when encountered (but may be on some paths
+and not on others), is not supported.
+
+
+5. Callouts are supported, but the value of the capture_top field is
+always 1, and the value of the capture_last field is always 0.
+
+
+6. The \C escape sequence, which (in the standard algorithm) always matches a
+single code unit, even in a UTF mode, is not supported in UTF modes because
+the alternative algorithm moves through the subject string one character (not
+code unit) at a time, for all active paths through the tree.
+
+
+7. Except for (*FAIL), the backtracking control verbs such as (*PRUNE) are not
+supported. (*FAIL) is supported, and behaves like a failing negative assertion.
+
+
+8. The PCRE2_MATCH_INVALID_UTF option for pcre2_compile() is not
+supported by pcre2_dfa_match().
+
+
+
+The main advantage of the alternative algorithm is that all possible matches
+(at a single point in the subject) are automatically found, and in particular,
+the longest match is found. To find more than one match at the same point using
+the standard algorithm, you have to do kludgy things with callouts.
+
+
+Partial matching is possible with this algorithm, though it has some
+limitations. The
+pcre2partial
+documentation gives details of partial matching and discusses multi-segment
+matching.
+
+
+
+The alternative algorithm suffers from a number of disadvantages:
+
+
+1. It is substantially slower than the standard algorithm. This is partly
+because it has to search for all possible matches, but is also because it is
+less susceptible to optimization.
+
+
+2. Capturing parentheses and other features such as backreferences that rely on
+them are not supported.
+
+
+3. Matching within invalid UTF strings is not supported.
+
+
+4. Although atomic groups are supported, their use does not provide the
+performance advantage that it does for the standard algorithm.
+
+
+5. JIT optimization is not supported.
+
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+
+Last updated: 22 February 2025
+
+Copyright © 1997-2024 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2partial.html b/doc/html/pcre2partial.html
new file mode 100644
index 0000000..acce666
--- /dev/null
+++ b/doc/html/pcre2partial.html
@@ -0,0 +1,422 @@
+
+
+pcre2partial specification
+
+
+pcre2partial man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+In normal use of PCRE2, if there is a match up to the end of a subject string,
+but more characters are needed to match the entire pattern, PCRE2_ERROR_NOMATCH
+is returned, just like any other failing match. There are circumstances where
+it might be helpful to distinguish this "partial match" case.
+
+
+One example is an application where the subject string is very long, and not
+all available at once. The requirement here is to be able to do the matching
+segment by segment, but special action is needed when a matched substring spans
+the boundary between two segments.
+
+
+Another example is checking a user input string as it is typed, to ensure that
+it conforms to a required format. Invalid characters can be immediately
+diagnosed and rejected, giving instant feedback.
+
+
+Partial matching is a PCRE2-specific feature; it is not Perl-compatible. It is
+requested by setting one of the PCRE2_PARTIAL_HARD or PCRE2_PARTIAL_SOFT
+options when calling a matching function. The difference between the two
+options is whether or not a partial match is preferred to an alternative
+complete match, though the details differ between the two types of matching
+function. If both options are set, PCRE2_PARTIAL_HARD takes precedence.
+
+
+If you want to use partial matching with just-in-time optimized code, as well
+as setting a partial match option for the matching function, you must also call
+pcre2_jit_compile() with one or both of these options:
+
+ PCRE2_JIT_PARTIAL_HARD
+ PCRE2_JIT_PARTIAL_SOFT
+
+PCRE2_JIT_COMPLETE should also be set if you are going to run non-partial
+matches on the same pattern. Separate code is compiled for each mode. If the
+appropriate JIT mode has not been compiled, interpretive matching code is used.
+
+
+Setting a partial matching option disables two of PCRE2's standard
+optimization hints. PCRE2 remembers the last literal code unit in a pattern,
+and abandons matching immediately if it is not present in the subject string.
+This optimization cannot be used for a subject string that might match only
+partially. PCRE2 also remembers a minimum length of a matching string, and does
+not bother to run the matching function on shorter strings. This optimization
+is also disabled for partial matching.
+
+
+
+A possible partial match occurs during matching when the end of the subject
+string is reached successfully, but either more characters are needed to
+complete the match, or the addition of more characters might change what is
+matched.
+
+
+Example 1: if the pattern is /abc/ and the subject is "ab", more characters are
+definitely needed to complete a match. In this case both hard and soft matching
+options yield a partial match.
+
+
+Example 2: if the pattern is /ab+/ and the subject is "ab", a complete match
+can be found, but the addition of more characters might change what is
+matched. In this case, only PCRE2_PARTIAL_HARD returns a partial match;
+PCRE2_PARTIAL_SOFT returns the complete match.
+
+
+On reaching the end of the subject, when PCRE2_PARTIAL_HARD is set, if the next
+pattern item is \z, \Z, \b, \B, or $ there is always a partial match.
+Otherwise, for both options, the next pattern item must be one that inspects a
+character, and at least one of the following must be true:
+
+
+(1) At least one character has already been inspected. An inspected character
+need not form part of the final matched string; lookbehind assertions and the
+\K escape sequence provide ways of inspecting characters before the start of a
+matched string.
+
+
+(2) The pattern contains one or more lookbehind assertions. This condition
+exists in case there is a lookbehind that inspects characters before the start
+of the match.
+
+
+(3) There is a special case when the whole pattern can match an empty string.
+When the starting point is at the end of the subject, the empty string match is
+a possibility, and if PCRE2_PARTIAL_SOFT is set and neither of the above
+conditions is true, it is returned. However, because adding more characters
+might result in a non-empty match, PCRE2_PARTIAL_HARD returns a partial match,
+which in this case means "there is going to be a match at this point, but until
+some more characters are added, we do not know if it will be an empty string or
+something longer".
+
+
+
+When a partial matching option is set, the result of calling
+pcre2_match() can be one of the following:
+
+
+A successful match
+A complete match has been found, starting and ending within this subject.
+
+
+PCRE2_ERROR_NOMATCH
+No match can start anywhere in this subject.
+
+
+PCRE2_ERROR_PARTIAL
+Adding more characters may result in a complete match that uses one or more
+characters from the end of this subject.
+
+
+When a partial match is returned, the first two elements in the ovector point
+to the portion of the subject that was matched, but the values in the rest of
+the ovector are undefined. The appearance of \K in the pattern has no effect
+for a partial match. Consider this pattern:
+
+ /abc\K123/
+
+If it is matched against "456abc123xyz" the result is a complete match, and the
+ovector defines the matched string as "123", because \K resets the "start of
+match" point. However, if a partial match is requested and the subject string
+is "456abc12", a partial match is found for the string "abc12", because all
+these characters are needed for a subsequent re-match with additional
+characters.
+
+
+If there is more than one partial match, the first one that was found provides
+the data that is returned. Consider this pattern:
+
+ /123\w+X|dogY/
+
+If this is matched against the subject string "abc123dog", both alternatives
+fail to match, but the end of the subject is reached during matching, so
+PCRE2_ERROR_PARTIAL is returned. The offsets are set to 3 and 9, identifying
+"123dog" as the first partial match. (In this example, there are two partial
+matches, because "dog" on its own partially matches the second alternative.)
+
+
+How a partial match is processed by pcre2_match()
+
+
+What happens when a partial match is identified depends on which of the two
+partial matching options is set.
+
+
+If PCRE2_PARTIAL_HARD is set, PCRE2_ERROR_PARTIAL is returned as soon as a
+partial match is found, without continuing to search for possible complete
+matches. This option is "hard" because it prefers an earlier partial match over
+a later complete match. For this reason, the assumption is made that the end of
+the supplied subject string is not the true end of the available data, which is
+why \z, \Z, \b, \B, and $ always give a partial match.
+
+
+If PCRE2_PARTIAL_SOFT is set, the partial match is remembered, but matching
+continues as normal, and other alternatives in the pattern are tried. If no
+complete match can be found, PCRE2_ERROR_PARTIAL is returned instead of
+PCRE2_ERROR_NOMATCH. This option is "soft" because it prefers a complete match
+over a partial match. All the various matching items in a pattern behave as if
+the subject string is potentially complete; \z, \Z, and $ match at the end of
+the subject, as normal, and for \b and \B the end of the subject is treated
+as a non-alphanumeric.
+
+
+The difference between the two partial matching options can be illustrated by a
+pattern such as:
+
+ /dog(sbody)?/
+
+This matches either "dog" or "dogsbody", greedily (that is, it prefers the
+longer string if possible). If it is matched against the string "dog" with
+PCRE2_PARTIAL_SOFT, it yields a complete match for "dog". However, if
+PCRE2_PARTIAL_HARD is set, the result is PCRE2_ERROR_PARTIAL. On the other
+hand, if the pattern is made ungreedy the result is different:
+
+ /dog(sbody)??/
+
+In this case the result is always a complete match because that is found first,
+and matching never continues after finding a complete match. It might be easier
+to follow this explanation by thinking of the two patterns like this:
+
+ /dog(sbody)?/ is the same as /dogsbody|dog/
+ /dog(sbody)??/ is the same as /dog|dogsbody/
+
+The second pattern will never match "dogsbody", because it will always find the
+shorter match first.
+
+
+Example of partial matching using pcre2test
+
+
+The pcre2test data modifiers partial_hard (or ph) and
+partial_soft (or ps) set PCRE2_PARTIAL_HARD and PCRE2_PARTIAL_SOFT,
+respectively, when calling pcre2_match(). Here is a run of
+pcre2test using a pattern that matches the whole subject in the form of a
+date:
+
+ re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
+ data> 25dec3\=ph
+ Partial match: 23dec3
+ data> 3ju\=ph
+ Partial match: 3ju
+ data> 3juj\=ph
+ No match
+
+This example gives the same results for both hard and soft partial matching
+options. Here is an example where there is a difference:
+
+ re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
+ data> 25jun04\=ps
+ 0: 25jun04
+ 1: jun
+ data> 25jun04\=ph
+ Partial match: 25jun04
+
+With PCRE2_PARTIAL_SOFT, the subject is matched completely. For
+PCRE2_PARTIAL_HARD, however, the subject is assumed not to be complete, so
+there is only a partial match.
+
+
+
+PCRE was not originally designed with multi-segment matching in mind. However,
+over time, features (including partial matching) that make multi-segment
+matching possible have been added. A very long string can be searched segment
+by segment by calling pcre2_match() repeatedly, with the aim of achieving
+the same results that would happen if the entire string was available for
+searching all the time. Normally, the strings that are being sought are much
+shorter than each individual segment, and are in the middle of very long
+strings, so the pattern is normally not anchored.
+
+
+Special logic must be implemented to handle a matched substring that spans a
+segment boundary. PCRE2_PARTIAL_HARD should be used, because it returns a
+partial match at the end of a segment whenever there is the possibility of
+changing the match by adding more characters. The PCRE2_NOTBOL option should
+also be set for all but the first segment.
+
+
+When a partial match occurs, the next segment must be added to the current
+subject and the match re-run, using the startoffset argument of
+pcre2_match() to begin at the point where the partial match started.
+For example:
+
+ re> /\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d/
+ data> ...the date is 23ja\=ph
+ Partial match: 23ja
+ data> ...the date is 23jan19 and on that day...\=offset=15
+ 0: 23jan19
+ 1: jan
+
+Note the use of the offset modifier to start the new match where the
+partial match was found. In this example, the next segment was added to the one
+in which the partial match was found. This is the most straightforward
+approach, typically using a memory buffer that is twice the size of each
+segment. After a partial match, the first half of the buffer is discarded, the
+second half is moved to the start of the buffer, and a new segment is added
+before repeating the match as in the example above. After a no match, the
+entire buffer can be discarded.
+
+
+If there are memory constraints, you may want to discard text that precedes a
+partial match before adding the next segment. Unfortunately, this is not at
+present straightforward. In cases such as the above, where the pattern does not
+contain any lookbehinds, it is sufficient to retain only the partially matched
+substring. However, if the pattern contains a lookbehind assertion, characters
+that precede the start of the partial match may have been inspected during the
+matching process. When pcre2test displays a partial match, it indicates
+these characters with '<' if the allusedtext modifier is set:
+
+ re> "(?<=123)abc"
+ data> xx123ab\=ph,allusedtext
+ Partial match: 123ab
+ <<<
+
+However, the allusedtext modifier is not available for JIT matching,
+because JIT matching does not record the first (or last) consulted characters.
+For this reason, this information is not available via the API. It is therefore
+not possible in general to obtain the exact number of characters that must be
+retained in order to get the right match result. If you cannot retain the
+entire segment, you must find some heuristic way of choosing.
+
+
+If you know the approximate length of the matching substrings, you can use that
+to decide how much text to retain. The only lookbehind information that is
+currently available via the API is the length of the longest individual
+lookbehind in a pattern, but this can be misleading if there are nested
+lookbehinds. The value returned by calling pcre2_pattern_info() with the
+PCRE2_INFO_MAXLOOKBEHIND option is the maximum number of characters (not code
+units) that any individual lookbehind moves back when it is processed. A
+pattern such as "(?<=(?<!b)a)" has a maximum lookbehind value of one, but
+inspects two characters before its starting point.
+
+
+In a non-UTF or a 32-bit case, moving back is just a subtraction, but in
+UTF-8 or UTF-16 you have to count characters while moving back through the code
+units.
+
+
+
+The DFA function moves along the subject string character by character, without
+backtracking, searching for all possible matches simultaneously. If the end of
+the subject is reached before the end of the pattern, there is the possibility
+of a partial match.
+
+
+When PCRE2_PARTIAL_SOFT is set, PCRE2_ERROR_PARTIAL is returned only if there
+have been no complete matches. Otherwise, the complete matches are returned.
+If PCRE2_PARTIAL_HARD is set, a partial match takes precedence over any
+complete matches. The portion of the string that was matched when the longest
+partial match was found is set as the first matching string.
+
+
+Because the DFA function always searches for all possible matches, and there is
+no difference between greedy and ungreedy repetition, its behaviour is
+different from the pcre2_match(). Consider the string "dog" matched
+against this ungreedy pattern:
+
+ /dog(sbody)??/
+
+Whereas the standard function stops as soon as it finds the complete match for
+"dog", the DFA function also finds the partial match for "dogsbody", and so
+returns that when PCRE2_PARTIAL_HARD is set.
+
+
+
+When a partial match has been found using the DFA matching function, it is
+possible to continue the match by providing additional subject data and calling
+the function again with the same compiled regular expression, this time setting
+the PCRE2_DFA_RESTART option. You must pass the same working space as before,
+because this is where details of the previous partial match are stored. You can
+set the PCRE2_PARTIAL_SOFT or PCRE2_PARTIAL_HARD options with PCRE2_DFA_RESTART
+to continue partial matching over multiple segments. Here is an example using
+pcre2test:
+
+ re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
+ data> 23ja\=dfa,ps
+ Partial match: 23ja
+ data> n05\=dfa,dfa_restart
+ 0: n05
+
+The first call has "23ja" as the subject, and requests partial matching; the
+second call has "n05" as the subject for the continued (restarted) match.
+Notice that when the match is complete, only the last part is shown; PCRE2 does
+not retain the previously partially-matched string. It is up to the calling
+program to do that if it needs to. This means that, for an unanchored pattern,
+if a continued match fails, it is not possible to try again at a new starting
+point. All this facility is capable of doing is continuing with the previous
+match attempt. For example, consider this pattern:
+
+ 1234|3789
+
+If the first part of the subject is "ABC123", a partial match of the first
+alternative is found at offset 3. There is no partial match for the second
+alternative, because such a match does not start at the same point in the
+subject string. Attempting to continue with the string "7890" does not yield a
+match because only those alternatives that match at one point in the subject
+are remembered. Depending on the application, this may or may not be what you
+want.
+
+
+If you do want to allow for starting again at the next character, one way of
+doing it is to retain some or all of the segment and try a new complete match,
+as described for pcre2_match() above. Another possibility is to work with
+two buffers. If a partial match at offset n in the first buffer is
+followed by "no match" when PCRE2_DFA_RESTART is used on the second buffer, you
+can then try a new match starting at offset n+1 in the first buffer.
+
+
+Therefore, PCRE2_DFA_RESTART does not remove the need to keep earlier subject
+data. In order to perform a bumpalong and continue matching at the next
+character, all subject data from the current match start must be retained,
+together with enough preceding data to satisfy the requirements of lookbehind
+assertions (remembering as above that PCRE2_INFO_MAXLOOKBEHIND only describes
+the buffer requirement of a single lookbehind, and nested lookbehinds can read
+back further from the match start). This makes streaming match processing
+using PCRE2_DFA_RESTART challenging, and the application cannot easily set a
+bound on the number of chunks to buffer. For multi-segment searching that is
+intended to produce the same result as searching the whole subject, it is
+usually simpler to avoid PCRE2_DFA_RESTART and run a fresh match, using either
+matching function, over the retained text.
+
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+
+Last updated: 16 August 2026
+
+Copyright © 1997-2019 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2pattern.html b/doc/html/pcre2pattern.html
new file mode 100644
index 0000000..9ff064e
--- /dev/null
+++ b/doc/html/pcre2pattern.html
@@ -0,0 +1,4192 @@
+
+
+pcre2pattern specification
+
+
+pcre2pattern man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+The syntax and semantics of the regular expressions that are supported by PCRE2
+are described in detail below. There is a quick-reference syntax summary in the
+pcre2syntax
+page. PCRE2 tries to match Perl syntax and semantics as closely as it can.
+PCRE2 also supports some alternative regular expression syntax that does not
+conflict with the Perl syntax in order to provide some compatibility with
+regular expressions in Python, .NET, and Oniguruma. There are in addition some
+options that enable alternative syntax and semantics that are not the same as
+in Perl.
+
+
+Perl's regular expressions are described in its own documentation, and regular
+expressions in general are covered in a number of books, some of which have
+copious examples. Jeffrey Friedl's "Mastering Regular Expressions", published
+by O'Reilly, covers regular expressions in great detail. This description of
+PCRE2's regular expressions is intended as reference material.
+
+
+This document discusses the regular expression patterns that are supported by
+PCRE2 when its main matching function, pcre2_match(), is used. PCRE2 also
+has an alternative matching function, pcre2_dfa_match(), which matches
+using a different algorithm that is not Perl-compatible. Some of the features
+discussed below are not available when DFA matching is used. The advantages and
+disadvantages of the alternative function, and how it differs from the normal
+function, are discussed in the
+pcre2matching
+page.
+
+
+
+Most computers use ASCII or Unicode for encoding characters, and PCRE2 assumes
+this by default. However, it can be compiled to run in an environment that uses
+the EBCDIC code, which is the case for some IBM mainframe operating systems. In
+the sections below, character code values are ASCII or Unicode; in an EBCDIC
+environment these characters may have different code values, and there are no
+code points greater than 255. Differences in behaviour when PCRE2 is running in
+an EBCDIC environment are described in the section
+"EBCDIC environments"
+below, which you can ignore unless you really are in an EBCDIC environment.
+
+
+
+A number of options that can be passed to pcre2_compile() can also be set
+by special items at the start of a pattern. These are not Perl-compatible, but
+are provided to make these options accessible to pattern writers who are not
+able to change the program that processes the pattern. Any number of these
+items may appear, but they must all be together right at the start of the
+pattern string, and the letters must be in upper case.
+
+
+UTF support
+
+
+In the 8-bit and 16-bit PCRE2 libraries, characters may be coded either as
+single code units, or as multiple UTF-8 or UTF-16 code units. UTF-32 can be
+specified for the 32-bit library, in which case it constrains the character
+values to valid Unicode code points. To process UTF strings, PCRE2 must be
+built to include Unicode support (which is the default). When using UTF strings
+you must either call the compiling function with one or both of the PCRE2_UTF
+or PCRE2_MATCH_INVALID_UTF options, or the pattern must start with the special
+sequence (*UTF), which is equivalent to setting the relevant PCRE2_UTF. How
+setting a UTF mode affects pattern matching is mentioned in several places
+below. There is also a summary of features in the
+pcre2unicode
+page.
+
+
+Some applications that allow their users to supply patterns may wish to
+restrict them to non-UTF data for security reasons. If the PCRE2_NEVER_UTF
+option is passed to pcre2_compile(), (*UTF) is not allowed, and its
+appearance in a pattern causes an error.
+
+
+Unicode property support
+
+
+Another special sequence that may appear at the start of a pattern is (*UCP).
+This has the same effect as setting the PCRE2_UCP option: it causes sequences
+such as \d and \w to use Unicode properties to determine character types,
+instead of recognizing only characters with codes less than 256 via a lookup
+table. If also causes upper/lower casing operations to use Unicode properties
+for characters with code points greater than 127, even when UTF is not set.
+These behaviours can be changed within the pattern; see the section entitled
+"Internal Option Setting"
+below.
+
+
+Some applications that allow their users to supply patterns may wish to
+restrict them for security reasons. If the PCRE2_NEVER_UCP option is passed to
+pcre2_compile(), (*UCP) is not allowed, and its appearance in a pattern
+causes an error.
+
+
+Locking out empty string matching
+
+
+Starting a pattern with (*NOTEMPTY) or (*NOTEMPTY_ATSTART) has the same effect
+as passing the PCRE2_NOTEMPTY or PCRE2_NOTEMPTY_ATSTART option to whichever
+matching function is subsequently called to match the pattern. These options
+lock out the matching of empty strings, either entirely, or only at the start
+of the subject.
+
+
+Disabling auto-possessification
+
+
+If a pattern starts with (*NO_AUTO_POSSESS), it has the same effect as setting
+the PCRE2_NO_AUTO_POSSESS option, or calling pcre2_set_optimize() with
+a PCRE2_AUTO_POSSESS_OFF directive. This stops PCRE2 from making quantifiers
+possessive when what follows cannot match the repeated item. For example, by
+default a+b is treated as a++b. For more details, see the
+pcre2api
+documentation.
+
+
+Disabling start-up optimizations
+
+
+If a pattern starts with (*NO_START_OPT), it has the same effect as setting the
+PCRE2_NO_START_OPTIMIZE option, or calling pcre2_set_optimize() with
+a PCRE2_START_OPTIMIZE_OFF directive. This disables several optimizations for
+quickly reaching "no match" results. For more details, see the
+pcre2api
+documentation.
+
+
+Disabling automatic anchoring
+
+
+If a pattern starts with (*NO_DOTSTAR_ANCHOR), it has the same effect as
+setting the PCRE2_NO_DOTSTAR_ANCHOR option, or
+calling pcre2_set_optimize() with a PCRE2_DOTSTAR_ANCHOR_OFF directive.
+This disables optimizations that apply to patterns whose top-level branches
+all start with .* (match any number of arbitrary characters). For more details,
+see the
+pcre2api
+documentation.
+
+
+Disabling JIT compilation
+
+
+If a pattern that starts with (*NO_JIT) is successfully compiled, an attempt by
+the application to apply the JIT optimization by calling
+pcre2_jit_compile() is ignored.
+
+
+Setting match resource limits
+
+
+The pcre2_match() function contains a counter that is incremented every
+time it goes round its main loop. The caller of pcre2_match() can set a
+limit on this counter, which therefore limits the amount of computing resource
+used for a match. The maximum depth of nested backtracking can also be limited;
+this indirectly restricts the amount of heap memory that is used, but there is
+also an explicit memory limit that can be set.
+
+
+These facilities are provided to catch runaway matches that are provoked by
+patterns with huge matching trees. A common example is a pattern with nested
+unlimited repeats applied to a long string that does not match. When one of
+these limits is reached, pcre2_match() gives an error return. The limits
+can also be set by items at the start of the pattern of the form
+
+ (*LIMIT_HEAP=d)
+ (*LIMIT_MATCH=d)
+ (*LIMIT_DEPTH=d)
+
+where d is any number of decimal digits. However, the value of the setting must
+be less than the value set (or defaulted) by the caller of pcre2_match()
+for it to have any effect. In other words, the pattern writer can lower the
+limits set by the programmer, but not raise them. If there is more than one
+setting of one of these limits, the lower value is used. The heap limit is
+specified in kibibytes (units of 1024 bytes).
+
+
+Prior to release 10.30, LIMIT_DEPTH was called LIMIT_RECURSION. This name is
+still recognized for backwards compatibility.
+
+
+The heap limit applies only when the pcre2_match() or
+pcre2_dfa_match() interpreters are used for matching. It does not apply
+to JIT. The match limit is used (but in a different way) when JIT is being
+used, or when pcre2_dfa_match() is called, to limit computing resource
+usage by those matching functions. The depth limit is ignored by JIT but is
+relevant for DFA matching, which uses function recursion for recursions within
+the pattern and for lookaround assertions and atomic groups. In this case, the
+depth limit controls the depth of such recursion.
+
+
+Newline conventions
+
+
+PCRE2 supports six different conventions for indicating line breaks in
+strings: a single CR (carriage return) character, a single LF (linefeed)
+character, the two-character sequence CRLF, any of the three preceding, any
+Unicode newline sequence, or the NUL character (binary zero). The
+pcre2api
+page has
+further discussion
+about newlines, and shows how to set the newline convention when calling
+pcre2_compile().
+
+
+It is also possible to specify a newline convention by starting a pattern
+string with one of the following sequences:
+
+ (*CR) carriage return
+ (*LF) linefeed
+ (*CRLF) carriage return, followed by linefeed
+ (*ANYCRLF) any of the three above
+ (*ANY) all Unicode newline sequences
+ (*NUL) the NUL character (binary zero)
+
+These override the default and the options given to the compiling function. For
+example, on a Unix system where LF is the default newline sequence, the pattern
+
+ (*CR)a.b
+
+changes the convention to CR. That pattern matches "a\nb" because LF is no
+longer a newline. If more than one of these settings is present, the last one
+is used.
+
+
+The newline convention affects where the circumflex and dollar assertions are
+true. It also affects the interpretation of the dot metacharacter when
+PCRE2_DOTALL is not set, and the behaviour of \N when not followed by an
+opening brace. However, it does not affect what the \R escape sequence
+matches. By default, this is any Unicode newline sequence, for Perl
+compatibility. However, this can be changed; see the next section and the
+description of \R in the section entitled
+"Newline sequences"
+below. A change of \R setting can be combined with a change of newline
+convention.
+
+
+Specifying what \R matches
+
+
+It is possible to restrict \R to match only CR, LF, or CRLF (instead of the
+complete set of Unicode line endings) by setting the option PCRE2_BSR_ANYCRLF
+at compile time. This effect can also be achieved by starting a pattern with
+(*BSR_ANYCRLF). For completeness, (*BSR_UNICODE) is also recognized,
+corresponding to PCRE2_BSR_UNICODE.
+
+
+
+A regular expression is a pattern that is matched against a subject string from
+left to right. Most characters stand for themselves in a pattern, and match the
+corresponding characters in the subject. As a trivial example, the pattern
+
+ The quick brown fox
+
+matches a portion of a subject string that is identical to itself. When
+caseless matching is specified (the PCRE2_CASELESS option or (?i) within the
+pattern), letters are matched independently of case. Note that there are two
+ASCII characters, K and S, that, in addition to their lower case ASCII
+equivalents, are case-equivalent with Unicode U+212A (Kelvin sign) and U+017F
+(long S) respectively when either PCRE2_UTF or PCRE2_UCP is set, unless the
+PCRE2_EXTRA_CASELESS_RESTRICT option is in force (either passed to
+pcre2_compile() or set by (*CASELESS_RESTRICT) or (?r) within the
+pattern). If the PCRE2_EXTRA_TURKISH_CASING option is in force (either passed
+to pcre2_compile() or set by (*TURKISH_CASING) within the pattern), then
+the 'i' letters are matched according to Turkish and Azeri languages.
+
+
+The power of regular expressions comes from the ability to include wild cards,
+character classes, alternatives, and repetitions in the pattern. These are
+encoded in the pattern by the use of metacharacters, which do not stand
+for themselves but instead are interpreted in some special way.
+
+
+There are two different sets of metacharacters: those that are recognized
+anywhere in the pattern except within square brackets, and those that are
+recognized within square brackets. Outside square brackets, the metacharacters
+are as follows:
+
+ \ general escape character with several uses
+ ^ assert start of string (or line, in multiline mode)
+ $ assert end of string (or line, in multiline mode)
+ . match any character except newline (by default)
+ [ start character class definition
+ | start of alternative branch
+ ( start group or control verb
+ ) end group or control verb
+ * 0 or more quantifier
+ + 1 or more quantifier; also "possessive quantifier"
+ ? 0 or 1 quantifier; also quantifier minimizer
+ { potential start of min/max quantifier
+
+Brace characters { and } are also used to enclose data for constructions such
+as \g{2} or \k{name}. In almost all uses of braces, space and/or horizontal
+tab characters that follow { or precede } are allowed and are ignored. In the
+case of quantifiers, they may also appear before or after the comma. The
+exception to this is \u{...} which is an ECMAScript compatibility feature
+that is recognized only when the PCRE2_EXTRA_ALT_BSUX option is set. ECMAScript
+does not ignore such white space; it causes the item to be interpreted as
+literal.
+
+
+Part of a pattern that is in square brackets is called a "character class". In
+a character class the only metacharacters are:
+
+ \ general escape character
+ ^ negate the class, but only if the first character
+ - indicates character range
+ [ POSIX character class (if followed by POSIX syntax)
+ ] terminates the character class
+
+If a pattern is compiled with the PCRE2_EXTENDED option, most white space in
+the pattern, other than in a character class, within a \Q...\E sequence, or
+between a # outside a character class and the next newline, inclusive, is
+ignored. An escaping backslash can be used to include a white space or a #
+character as part of the pattern. If the PCRE2_EXTENDED_MORE option is set, the
+same applies, but in addition unescaped space and horizontal tab characters are
+ignored inside a character class. Note: only these two characters are ignored,
+not the full set of pattern white space characters that are ignored outside a
+character class. Option settings can be changed within a pattern; see the
+section entitled
+"Internal Option Setting"
+below.
+
+
+The following sections describe the use of each of the metacharacters.
+
+
+
+The backslash character has several uses. Firstly, if it is followed by a
+character that is not a digit or a letter, it takes away any special meaning
+that character may have. This use of backslash as an escape character applies
+both inside and outside character classes.
+
+
+For example, if you want to match a * character, you must write \* in the
+pattern. This escaping action applies whether or not the following character
+would otherwise be interpreted as a metacharacter, so it is always safe to
+precede a non-alphanumeric with backslash to specify that it stands for itself.
+In particular, if you want to match a backslash, you write \\.
+
+
+Only ASCII digits and letters have any special meaning after a backslash. All
+other characters (in particular, those whose code points are greater than 127)
+are treated as literals.
+
+
+If you want to treat all characters in a sequence as literals, you can do so by
+putting them between \Q and \E. Note that this includes white space even when
+the PCRE2_EXTENDED option is set so that most other white space is ignored. The
+behaviour is different from Perl in that $ and @ are handled as literals in
+\Q...\E sequences in PCRE2, whereas in Perl, $ and @ cause variable
+interpolation. Also, Perl does "double-quotish backslash interpolation" on any
+backslashes between \Q and \E which, its documentation says, "may lead to
+confusing results". PCRE2 treats a backslash between \Q and \E just like any
+other character. Note the following examples:
+
+ Pattern PCRE2 matches Perl matches
+
+ \Qabc$xyz\E abc$xyz abc followed by the contents of $xyz
+ \Qabc\$xyz\E abc\$xyz abc\$xyz
+ \Qabc\E\$\Qxyz\E abc$xyz abc$xyz
+ \QA\B\E A\B A\B
+ \Q\\E \ \\E
+
+The \Q...\E sequence is recognized both inside and outside character classes.
+An isolated \E that is not preceded by \Q is ignored. If \Q is not followed
+by \E later in the pattern, the literal interpretation continues to the end of
+the pattern (that is, \E is assumed at the end). If the isolated \Q is inside
+a character class, this causes an error, because the character class is then
+not terminated by a closing square bracket.
+
+
+Another difference from Perl is that any appearance of \Q or \E inside what
+might otherwise be a quantifier causes PCRE2 not to recognize the sequence as a
+quantifier. Perl recognizes a quantifier if (redundantly) either of the numbers
+is inside \Q...\E, but not if the separating comma is. When not recognized as
+a quantifier a sequence such as {\Q1\E,2} is treated as the literal string
+"{1,2}".
+
+
+Non-printing characters
+
+
+A second use of backslash provides a way of encoding non-printing characters
+in patterns in a visible manner. There is no restriction on the appearance of
+non-printing characters in a pattern, but when a pattern is being prepared by
+text editing, it is often easier to use one of the following escape sequences
+instead of the binary character it represents. In an ASCII or Unicode
+environment, these escapes are as follows:
+
+ \a alarm, that is, the BEL character (hex 07)
+ \cx "control-x", where x is a non-control ASCII character
+ \e escape (hex 1B)
+ \f form feed (hex 0C)
+ \n linefeed (hex 0A)
+ \r carriage return (hex 0D) (but see below)
+ \t tab (hex 09)
+ \0dd character with octal code 0dd
+ \ddd character with octal code ddd, or back reference
+ \o{ddd..} character with octal code ddd..
+ \xhh character with hex code hh
+ \x{hhh..} character with hex code hhh..
+ \N{U+hhh..} character with Unicode hex code point hhh..
+
+A description of how back references work is given
+later,
+following the discussion of
+parenthesized groups.
+
+
+By default, after \x that is not followed by {, one or two hexadecimal
+digits are read (letters can be in upper or lower case). If the character that
+follows \x is neither { nor a hexadecimal digit, an error occurs. This is
+different from Perl's default behaviour, which generates a NUL character, but
+is in line with the behaviour of Perl's 'strict' mode in re.
+
+
+Any number of hexadecimal digits may appear between \x{ and }. If a character
+other than a hexadecimal digit appears between \x{ and }, or if there is no
+terminating }, an error occurs.
+
+
+Characters whose code points are less than 256 can be defined by either of the
+two syntaxes for \x or by an octal sequence. There is no difference in the way
+they are handled. For example, \xdc is exactly the same as \x{dc} or \334.
+However, using the braced versions does make such sequences easier to read.
+
+
+Support is available for some ECMAScript (aka JavaScript) escape sequences via
+two compile-time options. If PCRE2_ALT_BSUX is set, the sequence \x followed
+by { is not recognized. Only if \x is followed by two hexadecimal digits is it
+recognized as a character escape. Otherwise it is interpreted as a literal "x"
+character. In this mode, support for code points greater than 256 is provided
+by \u, which must be followed by four hexadecimal digits; otherwise it is
+interpreted as a literal "u" character.
+
+
+PCRE2_EXTRA_ALT_BSUX has the same effect as PCRE2_ALT_BSUX and, in addition,
+\u{hhh..} is recognized as the character specified by hexadecimal code point.
+There may be any number of hexadecimal digits, but unlike other places that
+also use curly brackets, spaces are not allowed and would result in the string
+being interpreted as a literal. This syntax is from ECMAScript 6.
+
+
+The \N{U+hhh..} escape sequence is recognized only when PCRE2 is operating in
+UTF mode. Perl also uses \N{name} to specify characters by Unicode name; PCRE2
+does not support this. Note that when \N is not followed by an opening brace
+(curly bracket) it has an entirely different meaning, matching any character
+that is not a newline.
+
+
+There are some legacy applications where the escape sequence \r is expected to
+match a newline. If the PCRE2_EXTRA_ESCAPED_CR_IS_LF option is set, \r in a
+pattern is converted to \n so that it matches a LF (linefeed) instead of a CR
+(carriage return) character.
+
+
+An error occurs if \c is not followed by a character whose ASCII code point
+is in the range 32 to 126. The precise effect of \cx is as follows: if x is a
+lower case letter, it is converted to upper case. Then bit 6 of the character
+(hex 40) is inverted. Thus \cA to \cZ become hex 01 to hex 1A (A is 41, Z is
+5A), but \c{ becomes hex 3B ({ is 7B), and \c; becomes hex 7B (; is 3B). If
+the code unit following \c has a code point less than 32 or greater than 126,
+a compile-time error occurs.
+
+
+For differences in the way some escapes behave in EBCDIC environments,
+see section
+"EBCDIC environments"
+below.
+
+
+Octal escapes and back references
+
+
+The escape \o must be followed by a sequence of octal digits, enclosed in
+braces. An error occurs if this is not the case. This escape provides a way of
+specifying character code points as octal numbers greater than 0777, and it
+also allows octal numbers and backreferences to be unambiguously distinguished.
+
+
+If braces are not used, after \0 up to two further octal digits are read.
+However, if the PCRE2_EXTRA_NO_BS0 option is set, at least one more octal digit
+must follow \0 (use \00 to generate a NUL character). Make sure you supply
+two digits after the initial zero if the pattern character that follows is
+itself an octal digit.
+
+
+Inside a character class, when a backslash is followed by any octal digit, up
+to three octal digits are read to generate a code point. Any subsequent digits
+stand for themselves. The sequences \8 and \9 are treated as the literal
+characters "8" and "9".
+
+
+Outside a character class, Perl's handling of a backslash followed by a digit
+other than 0 is complicated by ambiguity, and Perl has changed over time,
+causing PCRE2 also to change. From PCRE2 release 10.45 there is an option
+called PCRE2_EXTRA_PYTHON_OCTAL that causes PCRE2 to use Python's unambiguous
+rules. The next two subsections describe the two sets of rules.
+
+
+For greater clarity and unambiguity, it is best to avoid following \ by a
+digit greater than zero. Instead, use \o{...} or \x{...} to specify numerical
+character code points, and \g{...} to specify backreferences.
+
+
+Perl rules for non-class backslash 1-9
+
+
+All the digits that follow the backslash are read as a decimal number. If the
+number is less than 10, begins with the digit 8 or 9, or if there are at least
+that many previous capture groups in the expression, the entire sequence is
+taken as a back reference. Otherwise, up to three octal digits are read to form
+a character code. For example:
+
+ \040 is another way of writing an ASCII space
+ \40 is the same, provided there are fewer than 40 previous capture groups
+ \7 is always a backreference
+ \11 might be a backreference, or another way of writing a tab
+ \011 is always a tab
+ \0113 is a tab followed by the character "3"
+ \113 might be a backreference, otherwise the character with octal code 113
+ \377 might be a backreference, otherwise the value 255 (decimal)
+ \81 is always a backreference
+
+Note that octal values of 100 or greater that are specified using this syntax
+must not be introduced by a leading zero, because no more than three octal
+digits are ever read.
+
+
+Python rules for non_class backslash 1-9
+
+
+If there are at least three octal digits after the backslash, exactly three are
+read as an octal code point number, but the value must be no greater than
+\377, even in modes where higher code point values are supported. Any
+subsequent digits stand for themselves. If there are fewer than three octal
+digits, the sequence is taken as a decimal back reference. Thus, for example,
+\12 is always a back reference, independent of how many captures there are in
+the pattern. An error is generated for a reference to a non-existent capturing
+group.
+
+
+Constraints on character values
+
+
+Characters that are specified using octal or hexadecimal numbers are
+limited to certain values, as follows:
+
+ 8-bit non-UTF mode no greater than 0xff
+ 16-bit non-UTF mode no greater than 0xffff
+ 32-bit non-UTF mode no greater than 0xffffffff
+ All UTF modes no greater than 0x10ffff and a valid code point
+
+Invalid Unicode code points are all those in the range 0xd800 to 0xdfff (the
+so-called "surrogate" code points). The check for these can be disabled by the
+caller of pcre2_compile() by setting the option
+PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES. However, this is possible only in UTF-8
+and UTF-32 modes, because these values are not representable in UTF-16.
+
+
+Escape sequences in character classes
+
+
+All the sequences that define a single character value can be used both inside
+and outside character classes. In addition, inside a character class, \b is
+interpreted as the backspace character (hex 08).
+
+
+When not followed by an opening brace, \N is not allowed in a character class.
+\B, \R, and \X are not special inside a character class. Like other
+unrecognized alphabetic escape sequences, they cause an error. Outside a
+character class, these sequences have different meanings.
+
+
+Unsupported escape sequences
+
+
+In Perl, the sequences \F, \l, \L, \u, and \U are recognized by its string
+handler and used to modify the case of following characters. By default, PCRE2
+does not support these escape sequences in patterns. However, if either of the
+PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX options is set, \U matches a "U"
+character, and \u can be used to define a character by code point, as
+described above.
+
+
+Absolute and relative backreferences
+
+
+The sequence \g followed by a signed or unsigned number, optionally enclosed
+in braces, is an absolute or relative backreference. A named backreference
+can be coded as \g{name}. Backreferences are discussed
+later,
+following the discussion of
+parenthesized groups.
+
+
+Absolute and relative subroutine calls
+
+
+For compatibility with Oniguruma, the non-Perl syntax \g followed by a name or
+a number enclosed either in angle brackets or single quotes, is an alternative
+syntax for referencing a capture group as a subroutine. Details are discussed
+later.
+Note that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are not
+synonymous. The former is a backreference; the latter is a
+subroutine
+call.
+
+
+Generic character types
+
+
+Another use of backslash is for specifying generic character types:
+
+ \d any decimal digit
+ \D any character that is not a decimal digit
+ \h any horizontal white space character
+ \H any character that is not a horizontal white space character
+ \N any character that is not a newline
+ \s any white space character
+ \S any character that is not a white space character
+ \v any vertical white space character
+ \V any character that is not a vertical white space character
+ \w any "word" character
+ \W any "non-word" character
+
+The \N escape sequence has the same meaning as
+the "." metacharacter
+when PCRE2_DOTALL is not set, but setting PCRE2_DOTALL does not change the
+meaning of \N. Note that when \N is followed by an opening brace it has a
+different meaning. See the section entitled
+"Non-printing characters"
+above for details. Perl also uses \N{name} to specify characters by Unicode
+name; PCRE2 does not support this.
+
+
+Each pair of lower and upper case escape sequences partitions the complete set
+of characters into two disjoint sets. Any given character matches one, and only
+one, of each pair. The sequences can appear both inside and outside character
+classes. They each match one character of the appropriate type. If the current
+matching point is at the end of the subject string, all of them fail, because
+there is no character to match.
+
+
+The default \s characters are HT (9), LF (10), VT (11), FF (12), CR (13), and
+space (32), which are defined as white space in the "C" locale. This list may
+vary if locale-specific matching is taking place. For example, in some locales
+the "non-breaking space" character (\xA0) is recognized as white space, and in
+others the VT character is not.
+
+
+A "word" character is an underscore or any character that is a letter or digit.
+By default, the definition of letters and digits is controlled by PCRE2's
+low-valued character tables, and may vary if locale-specific matching is taking
+place (see
+"Locale support"
+in the
+pcre2api
+page). For example, in a French locale such as "fr_FR" in Unix-like systems,
+or "french" in Windows, some character codes greater than 127 are used for
+accented letters, and these are then matched by \w. The use of locales with
+Unicode is discouraged.
+
+
+By default, characters whose code points are greater than 127 never match \d,
+\s, or \w, and always match \D, \S, and \W, although this may be different
+for characters in the range 128-255 when locale-specific matching is happening.
+These escape sequences retain their original meanings from before Unicode
+support was available, mainly for efficiency reasons. If the PCRE2_UCP option
+is set, the behaviour is changed so that Unicode properties are used to
+determine character types, as follows:
+
+ \d any character that matches \p{Nd} (decimal digit)
+ \s any character that matches \p{Z} or \h or \v
+ \w any character that matches \p{L}, \p{N}, \p{Mn}, or \p{Pc}
+
+The addition of \p{Mn} (non-spacing mark) and the replacement of an explicit
+test for underscore with a test for \p{Pc} (connector punctuation) happened in
+PCRE2 release 10.43. This brings PCRE2 into line with Perl.
+
+
+The upper case escapes match the inverse sets of characters. Note that \d
+matches only decimal digits, whereas \w matches any Unicode digit, as well as
+other character categories. Note also that PCRE2_UCP affects \b, and
+\B because they are defined in terms of \w and \W. Matching these sequences
+is noticeably slower when PCRE2_UCP is set.
+
+
+The effect of PCRE2_UCP on any one of these escape sequences can be negated by
+the options PCRE2_EXTRA_ASCII_BSD, PCRE2_EXTRA_ASCII_BSS, and
+PCRE2_EXTRA_ASCII_BSW, respectively. These options can be set and reset within
+a pattern by means of an internal option setting
+(see below).
+
+
+The sequences \h, \H, \v, and \V, in contrast to the other sequences, which
+match only ASCII characters by default, always match a specific list of code
+points, whether or not PCRE2_UCP is set. The horizontal space characters are:
+
+ U+0009 Horizontal tab (HT)
+ U+0020 Space
+ U+00A0 Non-break space
+ U+1680 Ogham space mark
+ U+180E Mongolian vowel separator
+ U+2000 En quad
+ U+2001 Em quad
+ U+2002 En space
+ U+2003 Em space
+ U+2004 Three-per-em space
+ U+2005 Four-per-em space
+ U+2006 Six-per-em space
+ U+2007 Figure space
+ U+2008 Punctuation space
+ U+2009 Thin space
+ U+200A Hair space
+ U+202F Narrow no-break space
+ U+205F Medium mathematical space
+ U+3000 Ideographic space
+
+The vertical space characters are:
+
+ U+000A Linefeed (LF)
+ U+000B Vertical tab (VT)
+ U+000C Form feed (FF)
+ U+000D Carriage return (CR)
+ U+0085 Next line (NEL)
+ U+2028 Line separator
+ U+2029 Paragraph separator
+
+In 8-bit, non-UTF-8 mode, only the characters with code points less than 256
+are relevant.
+
+
+Newline sequences
+
+
+Outside a character class, by default, the escape sequence \R matches any
+Unicode newline sequence. In 8-bit non-UTF-8 mode \R is equivalent to the
+following:
+
+ (?>\r\n|\n|\x0b|\f|\r|\x85)
+
+This is an example of an "atomic group", details of which are given
+below.
+This particular group matches either the two-character sequence CR followed by
+LF, or one of the single characters LF (linefeed, U+000A), VT (vertical tab,
+U+000B), FF (form feed, U+000C), CR (carriage return, U+000D), or NEL (next
+line, U+0085). Because this is an atomic group, the two-character sequence is
+treated as a single unit that cannot be split.
+
+
+In other modes, two additional characters whose code points are greater than 255
+are added: LS (line separator, U+2028) and PS (paragraph separator, U+2029).
+Unicode support is not needed for these characters to be recognized.
+
+
+It is possible to restrict \R to match only CR, LF, or CRLF (instead of the
+complete set of Unicode line endings) by setting the option PCRE2_BSR_ANYCRLF
+at compile time. (BSR is an abbreviation for "backslash R".) This can be made
+the default when PCRE2 is built; if this is the case, the other behaviour can
+be requested via the PCRE2_BSR_UNICODE option. It is also possible to specify
+these settings by starting a pattern string with one of the following
+sequences:
+
+ (*BSR_ANYCRLF) CR, LF, or CRLF only
+ (*BSR_UNICODE) any Unicode newline sequence
+
+These override the default and the options given to the compiling function.
+Note that these special settings, which are not Perl-compatible, are recognized
+only at the very start of a pattern, and that they must be in upper case. If
+more than one of them is present, the last one is used. They can be combined
+with a change of newline convention; for example, a pattern can start with:
+
+ (*ANY)(*BSR_ANYCRLF)
+
+They can also be combined with the (*UTF) or (*UCP) special sequences. Inside a
+character class, \R is treated as an unrecognized escape sequence, and causes
+an error.
+
+
+Unicode character properties
+
+
+When PCRE2 is built with Unicode support (the default), three additional escape
+sequences that match characters with specific properties are available. They
+can be used in any mode, though in 8-bit and 16-bit non-UTF modes these
+sequences are of course limited to testing characters whose code points are
+less than U+0100 or U+10000, respectively. In 32-bit non-UTF mode, code points
+greater than 0x10ffff (the Unicode limit) may be encountered. These are all
+treated as being in the Unknown script and with an unassigned type.
+
+
+Matching characters by Unicode property is not fast, because PCRE2 has to do a
+multistage table lookup in order to find a character's property. That is why
+the traditional escape sequences such as \d and \w do not use Unicode
+properties in PCRE2 by default, though you can make them do so by setting the
+PCRE2_UCP option or by starting the pattern with (*UCP).
+
+
+The extra escape sequences that provide property support are:
+
+ \p{xx} a character with the xx property
+ \P{xx} a character without the xx property
+ \X a Unicode extended grapheme cluster
+
+For compatibility with Perl, negation can be specified by including a
+circumflex between the opening brace and the property. For example, \p{^Lu} is
+the same as \P{Lu}.
+
+
+In accordance with Unicode's "loose matching" rules, ASCII white space
+characters, hyphens, and underscores are ignored in the properties represented
+by xx above. As well as the space character, ASCII white space can be
+tab, linefeed, vertical tab, formfeed, or carriage return.
+
+
+Some properties are specified as a name only; others as a name and a value,
+separated by a colon or an equals sign. The names and values consist of ASCII
+letters and digits (with one Perl-specific exception, see below). They are not
+case sensitive. Note, however, that the escapes themselves, \p and \P,
+are case sensitive. There are abbreviations for many names. The following
+examples are all equivalent:
+
+ \p{bidiclass=al}
+ \p{BC=al}
+ \p{ Bidi_Class : AL }
+ \p{ Bi-di class = Al }
+ \P{ ^ Bi-di class = Al }
+
+There is support for Unicode script names, Unicode general category properties,
+"Any", which matches any character (including newline), Bidi_Class, a number of
+binary (yes/no) properties, and some special PCRE2 properties (described
+below).
+Certain other Perl properties such as "InMusicalSymbols" are not supported by
+PCRE2. Note that \P{Any} does not match any characters, so always causes a
+match failure.
+
+
+Script properties for \p and \P
+
+
+There are three different syntax forms for matching a script. Each Unicode
+character has a basic script and, optionally, a list of other scripts ("Script
+Extensions") with which it is commonly used. Using the Adlam script as an
+example, \p{sc:Adlam} matches characters whose basic script is Adlam, whereas
+\p{scx:Adlam} matches, in addition, characters that have Adlam in their
+extensions list. The full names "script" and "script extensions" for the
+property types are recognized and, as for all property specifications, an
+equals sign is an alternative to the colon. If a script name is given without a
+property type, for example, \p{Adlam}, it is treated as \p{scx:Adlam}. Perl
+changed to this interpretation at release 5.26 and PCRE2 changed at release
+10.40.
+
+
+Unassigned characters (and in non-UTF 32-bit mode, characters with code points
+greater than 0x10FFFF) are assigned the "Unknown" script. Others that are not
+part of an identified script are lumped together as "Common". The current list
+of recognized script names and their 4-character abbreviations can be obtained
+by running this command:
+
+ pcre2test -LS
+
+
+
+
+The general category property for \p and \P
+
+
+Each character has exactly one Unicode general category property, specified by
+a two-letter abbreviation. If only one letter is specified with \p or \P, it
+includes all the general category properties that start with that letter. In
+this case, in the absence of negation, the curly brackets in the escape
+sequence are optional; these two examples have the same effect:
+
+ \p{L}
+ \pL
+
+The following general category property codes are supported:
+
+ C Other
+ Cc Control
+ Cf Format
+ Cn Unassigned
+ Co Private use
+ Cs Surrogate
+
+ L Letter
+ Lc Cased letter
+ Ll Lower case letter
+ Lm Modifier letter
+ Lo Other letter
+ Lt Title case letter
+ Lu Upper case letter
+
+ M Mark
+ Mc Spacing mark
+ Me Enclosing mark
+ Mn Non-spacing mark
+
+ N Number
+ Nd Decimal number
+ Nl Letter number
+ No Other number
+
+ P Punctuation
+ Pc Connector punctuation
+ Pd Dash punctuation
+ Pe Close punctuation
+ Pf Final punctuation
+ Pi Initial punctuation
+ Po Other punctuation
+ Ps Open punctuation
+
+ S Symbol
+ Sc Currency symbol
+ Sk Modifier symbol
+ Sm Mathematical symbol
+ So Other symbol
+
+ Z Separator
+ Zl Line separator
+ Zp Paragraph separator
+ Zs Space separator
+
+Perl originally used the name L& for the Lc property. This is still supported
+by Perl, but discouraged. PCRE2 also still supports it. This property matches
+any character that has the Lu, Ll, or Lt property, in other words, any letter
+that is not classified as a modifier or "other". From release 10.45 of PCRE2
+the properties Lu, Ll, and Lt are all treated as Lc when case-independent
+matching is set by the PCRE2_CASELESS option or (?i) within the pattern. The
+other properties are not affected by caseless matching.
+
+
+The Cs (Surrogate) property applies only to characters whose code points are in
+the range U+D800 to U+DFFF. These characters are no different to any other
+character when PCRE2 is not in UTF mode (using the 16-bit or 32-bit library).
+However, they are not valid in Unicode strings and so cannot be tested by PCRE2
+in UTF mode, unless UTF validity checking has been turned off (see the
+discussion of PCRE2_NO_UTF_CHECK in the
+pcre2api
+page).
+
+
+The long synonyms for property names that Perl supports (such as \p{Letter})
+are not supported by PCRE2, nor is it permitted to prefix any of these
+properties with "Is".
+
+
+No character that is in the Unicode table has the Cn (unassigned) property.
+Instead, this property is assumed for any code point that is not in the
+Unicode table.
+
+
+Binary (yes/no) properties for \p and \P
+
+
+Unicode defines a number of binary properties, that is, properties whose only
+values are true or false. You can obtain a list of those that are recognized by
+\p and \P, along with their abbreviations, by running this command:
+
+ pcre2test -LP
+
+
+
+
+The Bidi_Class property for \p and \P
+
+
+
+ \p{Bidi_Class:<class>} matches a character with the given class
+ \p{BC:<class>} matches a character with the given class
+
+The recognized classes are:
+
+ AL Arabic letter
+ AN Arabic number
+ B paragraph separator
+ BN boundary neutral
+ CS common separator
+ EN European number
+ ES European separator
+ ET European terminator
+ FSI first strong isolate
+ L left-to-right
+ LRE left-to-right embedding
+ LRI left-to-right isolate
+ LRO left-to-right override
+ NSM non-spacing mark
+ ON other neutral
+ PDF pop directional format
+ PDI pop directional isolate
+ R right-to-left
+ RLE right-to-left embedding
+ RLI right-to-left isolate
+ RLO right-to-left override
+ S segment separator
+ WS white space
+
+As in all property specifications, an equals sign may be used instead of a
+colon and the class names are case-insensitive. Only the short names listed
+above are recognized; PCRE2 does not at present support any long alternatives.
+
+
+Extended grapheme clusters
+
+
+The \X escape matches any number of Unicode characters that form an "extended
+grapheme cluster", and treats the sequence as an atomic group
+(see below).
+Unicode supports various kinds of composite character by giving each character
+a grapheme breaking property, and having rules that use these properties to
+define the boundaries of extended grapheme clusters. The rules are defined in
+Unicode Standard Annex 29, "Unicode Text Segmentation". Unicode 11.0.0
+abandoned the use of some previous properties that had been used for emojis.
+Instead it introduced various emoji-specific properties. PCRE2 uses only the
+Extended Pictographic property.
+
+
+\X always matches at least one character. Then it decides whether to add
+additional characters according to the following rules for ending a cluster:
+
+
+1. End at the end of the subject string.
+
+
+2. Do not end between CR and LF; otherwise end after any control character.
+
+
+3. Do not break Hangul (a Korean script) syllable sequences. Hangul characters
+are of five types: L, V, T, LV, and LVT. An L character may be followed by an
+L, V, LV, or LVT character; an LV or V character may be followed by a V or T
+character; an LVT or T character may be followed only by a T character.
+
+
+4. Do not end before extending characters or spacing marks or the zero-width
+joiner (ZWJ) character. Characters with the "mark" property always have the
+"extend" grapheme breaking property.
+
+
+5. Do not end after prepend characters.
+
+
+6. Do not end within emoji modifier sequences or emoji ZWJ (zero-width
+joiner) sequences. An emoji ZWJ sequence consists of a character with the
+Extended_Pictographic property, optionally followed by one or more characters
+with the Extend property, followed by the ZWJ character, followed by another
+Extended_Pictographic character.
+
+
+7. Do not break within emoji flag sequences. That is, do not break between
+regional indicator (RI) characters if there are an odd number of RI characters
+before the break point.
+
+
+8. Otherwise, end the cluster.
+
+
+PCRE2's additional properties
+
+
+As well as the standard Unicode properties described above, PCRE2 supports four
+more that make it possible to convert traditional escape sequences such as \w
+and \s to use Unicode properties. PCRE2 uses these non-standard, non-Perl
+properties internally when PCRE2_UCP is set. However, they may also be used
+explicitly. These properties are:
+
+ Xan Any alphanumeric character
+ Xps Any POSIX space character
+ Xsp Any Perl space character
+ Xwd Any Perl "word" character
+
+Xan matches characters that have either the L (letter) or the N (number)
+property. Xps matches the characters tab, linefeed, vertical tab, form feed, or
+carriage return, and any other character that has the Z (separator) property
+(this includes the space character). Xsp is the same as Xps; in PCRE1 it used
+to exclude vertical tab, for Perl compatibility, but Perl changed. Xwd matches
+the same characters as Xan, plus those that match Mn (non-spacing mark) or Pc
+(connector punctuation, which includes underscore).
+
+
+There is another non-standard property, Xuc, which matches any character that
+can be represented by a Universal Character Name in C++ and other programming
+languages. These are the characters $, @, ` (grave accent), and all characters
+with Unicode code points greater than or equal to U+00A0, except for the
+surrogates U+D800 to U+DFFF. Note that most base (ASCII) characters are
+excluded. (Universal Character Names are of the form \uHHHH or \UHHHHHHHH
+where H is a hexadecimal digit. Note that the Xuc property does not match these
+sequences but the characters that they represent.)
+
+
+Resetting the match start
+
+
+In normal use, the escape sequence \K causes any previously matched characters
+not to be included in the final matched sequence that is returned. For example,
+the pattern:
+
+ foo\Kbar
+
+matches "foobar", but reports that it has matched "bar". \K does not interact
+with anchoring in any way. The pattern:
+
+ ^foo\Kbar
+
+matches only when the subject begins with "foobar" (in single line mode),
+though it again reports the matched string as "bar". This feature is similar to
+a lookbehind assertion
+(described below),
+but the part of the pattern that precedes \K is not constrained to match a
+limited number of characters, as is required for a lookbehind assertion. The
+use of \K does not interfere with the setting of
+captured substrings.
+For example, when the pattern
+
+ (foo)\Kbar
+
+matches "foobar", the first substring is still set to "foo".
+
+
+From version 5.32.0 Perl forbids the use of \K in lookaround assertions. From
+release 10.38 PCRE2 also forbids this by default. However, the
+PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK option can be used when calling
+pcre2_compile() to re-enable the previous behaviour. When this option is
+set, \K is acted upon when it occurs inside positive assertions, but is
+ignored in negative assertions. Note that when a pattern such as (?=ab\K)
+matches, the reported start of the match can be greater than the end of the
+match. Using \K in a lookbehind assertion at the start of a pattern can also
+lead to odd effects. For example, consider this pattern:
+
+ (?<=\Kfoo)bar
+
+If the subject is "foobar", a call to pcre2_match() with a starting
+offset of 3 succeeds and reports the matching string as "foobar", that is, the
+start of the reported match is earlier than where the match started.
+
+
+Simple assertions
+
+
+The final use of backslash is for certain simple assertions. An assertion
+specifies a condition that has to be met at a particular point in a match,
+without consuming any characters from the subject string. The use of
+groups for more complicated assertions is described
+below.
+The backslashed assertions are:
+
+ \b matches at a word boundary
+ \B matches when not at a word boundary
+ \A matches at the start of the subject
+ \Z matches at the end of the subject
+ also matches before a newline at the end of the subject
+ \z matches only at the end of the subject
+ \G matches at the first matching position in the subject
+
+Inside a character class, \b has a different meaning; it matches the backspace
+character. If any other of these assertions appears in a character class, an
+"invalid escape sequence" error is generated.
+
+
+A word boundary is a position in the subject string where the current character
+and the previous character do not both match \w or \W (i.e. one matches
+\w and the other matches \W), or the start or end of the string if the
+first or last character matches \w, respectively. When PCRE2 is built with
+Unicode support, the meanings of \w and \W can be changed by setting the
+PCRE2_UCP option. When this is done, it also affects \b and \B. Neither PCRE2
+nor Perl has a separate "start of word" or "end of word" metasequence. However,
+whatever follows \b normally determines which it is. For example, the fragment
+\ba matches "a" at the start of a word.
+
+
+The \A, \Z, and \z assertions differ from the traditional circumflex and
+dollar (described in the next section) in that they only ever match at the very
+start and end of the subject string, whatever options are set. Thus, they are
+independent of multiline mode. These three assertions are not affected by the
+PCRE2_NOTBOL or PCRE2_NOTEOL options, which affect only the behaviour of the
+circumflex and dollar metacharacters. However, if the startoffset
+argument of pcre2_match() is non-zero, indicating that matching is to
+start at a point other than the beginning of the subject, \A can never match.
+The difference between \Z and \z is that \Z matches before a newline at the
+end of the string as well as at the very end, whereas \z matches only at the
+end.
+
+
+The \G assertion is true only when the current matching position is at the
+start point of the matching process, as specified by the startoffset
+argument of pcre2_match(). It differs from \A when the value of
+startoffset is non-zero. By calling pcre2_match() multiple times
+with appropriate arguments, you can mimic Perl's /g option, and it is in this
+kind of implementation where \G can be useful.
+
+
+Note, however, that PCRE2's implementation of \G, being true at the starting
+character of the matching process, is subtly different from Perl's, which
+defines it as true at the end of the previous match. In Perl, these can be
+different when the previously matched string was empty. Because PCRE2 does just
+one match at a time, it cannot reproduce this behaviour.
+
+
+If all the alternatives of a pattern begin with \G, the expression is anchored
+to the starting match position, and the "anchored" flag is set in the compiled
+regular expression.
+
+
+
+The circumflex and dollar metacharacters are zero-width assertions. That is,
+they test for a particular condition being true without consuming any
+characters from the subject string. These two metacharacters are concerned with
+matching the starts and ends of lines. If the newline convention is set so that
+only the two-character sequence CRLF is recognized as a newline, isolated CR
+and LF characters are treated as ordinary data characters, and are not
+recognized as newlines.
+
+
+Outside a character class, in the default matching mode, the circumflex
+character is an assertion that is true only if the current matching point is at
+the start of the subject string. If the startoffset argument of
+pcre2_match() is non-zero, or if PCRE2_NOTBOL is set, circumflex can
+never match if the PCRE2_MULTILINE option is unset. Inside a character class,
+circumflex has an entirely different meaning
+(see below).
+
+
+Circumflex need not be the first character of the pattern if a number of
+alternatives are involved, but it should be the first thing in each alternative
+in which it appears if the pattern is ever to match that branch. If all
+possible alternatives start with a circumflex, that is, if the pattern is
+constrained to match only at the start of the subject, it is said to be an
+"anchored" pattern. (There are also other constructs that can cause a pattern
+to be anchored.)
+
+
+The dollar character is an assertion that is true only if the current matching
+point is at the end of the subject string, or immediately before a newline at
+the end of the string (by default), unless PCRE2_NOTEOL is set. Note, however,
+that it does not actually match the newline. Dollar need not be the last
+character of the pattern if a number of alternatives are involved, but it
+should be the last item in any branch in which it appears. Dollar has no
+special meaning in a character class.
+
+
+The meaning of dollar can be changed so that it matches only at the very end of
+the string, by setting the PCRE2_DOLLAR_ENDONLY option at compile time. This
+does not affect the \Z assertion.
+
+
+The meanings of the circumflex and dollar metacharacters are changed if the
+PCRE2_MULTILINE option is set. When this is the case, a dollar character
+matches before any newlines in the string, as well as at the very end, and a
+circumflex matches immediately after internal newlines as well as at the start
+of the subject string. It does not match after a newline that ends the string,
+for compatibility with Perl. However, this can be changed by setting the
+PCRE2_ALT_CIRCUMFLEX option.
+
+
+For example, the pattern /^abc$/ matches the subject string "def\nabc" (where
+\n represents a newline) in multiline mode, but not otherwise. Consequently,
+patterns that are anchored in single line mode because all branches start with
+^ are not anchored in multiline mode, and a match for circumflex is possible
+when the startoffset argument of pcre2_match() is non-zero. The
+PCRE2_DOLLAR_ENDONLY option is ignored if PCRE2_MULTILINE is set.
+
+
+When the newline convention (see
+"Newline conventions"
+below) recognizes the two-character sequence CRLF as a newline, this is
+preferred, even if the single characters CR and LF are also recognized as
+newlines. For example, if the newline convention is "any", a multiline mode
+circumflex matches before "xyz" in the string "abc\r\nxyz" rather than after
+CR, even though CR on its own is a valid newline. (It also matches at the very
+start of the string, of course.)
+
+
+Note that the sequences \A, \Z, and \z can be used to match the start and
+end of the subject in both modes, and if all branches of a pattern start with
+\A it is always anchored, whether or not PCRE2_MULTILINE is set.
+
+
+
+Outside a character class, a dot in the pattern matches any one character in
+the subject string except (by default) a character that signifies the end of a
+line. One or more characters may be specified as line terminators (see
+"Newline conventions"
+above).
+
+
+Dot never matches a single line-ending character. When the two-character
+sequence CRLF is the only line ending, dot does not match CR if it is
+immediately followed by LF, but otherwise it matches all characters (including
+isolated CRs and LFs). When ANYCRLF is selected for line endings, no occurrences
+of CR of LF match dot. When all Unicode line endings are being recognized, dot
+does not match CR or LF or any of the other line ending characters.
+
+
+The behaviour of dot with regard to newlines can be changed. If the
+PCRE2_DOTALL option is set, a dot matches any one character, without exception.
+If the two-character sequence CRLF is present in the subject string, it takes
+two dots to match it.
+
+
+The handling of dot is entirely independent of the handling of circumflex and
+dollar, the only relationship being that they both involve newlines. Dot has no
+special meaning in a character class.
+
+
+The escape sequence \N when not followed by an opening brace behaves like a
+dot, except that it is not affected by the PCRE2_DOTALL option. In other words,
+it matches any character except one that signifies the end of a line.
+
+
+When \N is followed by an opening brace it has a different meaning. See the
+section entitled
+"Non-printing characters"
+above for details. Perl also uses \N{name} to specify characters by Unicode
+name; PCRE2 does not support this.
+
+
+
+Outside a character class, the escape sequence \C matches any one code unit,
+whether or not a UTF mode is set. In the 8-bit library, one code unit is one
+byte; in the 16-bit library it is a 16-bit unit; in the 32-bit library it is a
+32-bit unit. Unlike a dot, \C always matches line-ending characters. The
+feature is provided in Perl in order to match individual bytes in UTF-8 mode,
+but it is unclear how it can usefully be used.
+
+
+Because \C breaks up characters into individual code units, matching one unit
+with \C in UTF-8 or UTF-16 mode means that the rest of the string may start
+with a malformed UTF character. This has undefined results, because PCRE2
+assumes that it is matching character by character in a valid UTF string (by
+default it checks the subject string's validity at the start of processing
+unless the PCRE2_NO_UTF_CHECK or PCRE2_MATCH_INVALID_UTF option is used).
+
+
+An application can lock out the use of \C by setting the
+PCRE2_NEVER_BACKSLASH_C option when compiling a pattern. It is also possible to
+build PCRE2 with the use of \C permanently disabled.
+
+
+PCRE2 does not allow \C to appear in lookbehind assertions
+(described below)
+in UTF-8 or UTF-16 modes, because this would make it impossible to calculate
+the length of the lookbehind. Neither the alternative matching function
+pcre2_dfa_match() nor the JIT optimizer support \C in these UTF modes.
+The former gives a match-time error; the latter fails to optimize and so the
+match is always run using the interpreter.
+
+
+In the 32-bit library, however, \C is always supported (when not explicitly
+locked out) because it always matches a single code unit, whether or not UTF-32
+is specified.
+
+
+In general, the \C escape sequence is best avoided. However, one way of using
+it that avoids the problem of malformed UTF-8 or UTF-16 characters is to use a
+lookahead to check the length of the next character, as in this pattern, which
+could be used with a UTF-8 string (ignore white space and line breaks):
+
+ (?| (?=[\x00-\x7f])(\C) |
+ (?=[\x80-\x{7ff}])(\C)(\C) |
+ (?=[\x{800}-\x{ffff}])(\C)(\C)(\C) |
+ (?=[\x{10000}-\x{1fffff}])(\C)(\C)(\C)(\C))
+
+In this example, a group that starts with (?| resets the capturing parentheses
+numbers in each alternative (see
+"Duplicate Group Numbers"
+below). The assertions at the start of each branch check the next UTF-8
+character for values whose encoding uses 1, 2, 3, or 4 bytes, respectively. The
+character's individual bytes are then captured by the appropriate number of
+\C groups.
+
+
+
+An opening square bracket introduces a character class, terminated by a closing
+square bracket. A closing square bracket on its own is not special by default.
+If a closing square bracket is required as a member of the class, it should be
+the first data character in the class (after an initial circumflex, if present)
+or escaped with a backslash. This means that, by default, an empty class cannot
+be defined. However, if the PCRE2_ALLOW_EMPTY_CLASS option is set, a closing
+square bracket at the start does end the (empty) class.
+
+
+A character class matches a single character in the subject. A matched
+character must be in the set of characters defined by the class, unless the
+first character in the class definition is a circumflex, in which case the
+subject character must not be in the set defined by the class. If a circumflex
+is actually required as a member of the class, ensure it is not the first
+character, or escape it with a backslash.
+
+
+For example, the character class [aeiou] matches any lower case English vowel,
+whereas [^aeiou] matches all other characters. Note that a circumflex is just a
+convenient notation for specifying the characters that are in the class by
+enumerating those that are not. A class that starts with a circumflex is not an
+assertion; it still consumes a character from the subject string, and therefore
+it fails to match if the current pointer is at the end of the string.
+
+
+Characters in a class may be specified by their code points using \o, \x, or
+\N{U+hh..} in the usual way. When caseless matching is set, any letters in a
+class represent both their upper case and lower case versions, so for example,
+a caseless [aeiou] matches "A" as well as "a", and a caseless [^aeiou] does not
+match "A", whereas a caseful version would. Note that there are two ASCII
+characters, K and S, that, in addition to their lower case ASCII equivalents,
+are case-equivalent with Unicode U+212A (Kelvin sign) and U+017F (long S)
+respectively when either PCRE2_UTF or PCRE2_UCP is set. If you do not want
+these ASCII/non-ASCII case equivalences, you can suppress them by setting
+PCRE2_EXTRA_CASELESS_RESTRICT, either as an option in a compile context, or by
+including (*CASELESS_RESTRICT) or (?r) within a pattern.
+
+
+Characters that might indicate line breaks are never treated in any special way
+when matching character classes, whatever line-ending sequence is in use, and
+whatever setting of the PCRE2_DOTALL and PCRE2_MULTILINE options is used. A
+class such as [^a] always matches one of these characters.
+
+
+The generic character type escape sequences \d, \D, \h, \H, \p, \P, \s,
+\S, \v, \V, \w, and \W may appear in a character class, and add the
+characters that they match to the class. For example, [\dABCDEF] matches any
+hexadecimal digit. In UTF modes, the PCRE2_UCP option affects the meanings of
+\d, \s, \w and their upper case partners, just as it does when they appear
+outside a character class, as described in the section entitled
+"Generic character types"
+above. The escape sequence \b has a different meaning inside a character
+class; it matches the backspace character. The sequences \B, \R, and \X are
+not special inside a character class. Like any other unrecognized escape
+sequences, they cause an error. The same is true for \N when not followed by
+an opening brace.
+
+
+The minus (hyphen) character can be used to specify a range of characters in a
+character class. For example, [d-m] matches any letter between d and m,
+inclusive. If a minus character is required in a class, it must be escaped with
+a backslash or appear in a position where it cannot be interpreted as
+indicating a range, typically as the first or last character in the class,
+or immediately after a range. For example, [b-d-z] matches letters in the range
+b to d, a hyphen character, or z.
+
+
+There is some special treatment for alphabetic ranges in EBCDIC environments;
+see the section
+"EBCDIC environments"
+below.
+
+
+Perl treats a hyphen as a literal if it appears before or after a POSIX class
+(see below) or before or after a character type escape such as \d or \H.
+However, unless the hyphen is the last character in the class, Perl outputs a
+warning in its warning mode, as this is most likely a user error. As PCRE2 has
+no facility for warning, an error is given in these cases.
+
+
+It is not possible to have the literal character "]" as the end character of a
+range. A pattern such as [W-]46] is interpreted as a class of two characters
+("W" and "-") followed by a literal string "46]", so it would match "W46]" or
+"-46]". However, if the "]" is escaped with a backslash it is interpreted as
+the end of a range, so [W-\]46] is interpreted as a class containing a range
+and two other characters. The octal or hexadecimal representation of "]" can
+also be used to end a range.
+
+
+Ranges normally include all code points between the start and end characters,
+inclusive. They can also be used for code points specified numerically, for
+example [\000-\037]. Ranges can include any characters that are valid for the
+current mode. In any UTF mode, the so-called "surrogate" characters (those
+whose code points lie between 0xd800 and 0xdfff inclusive) may not be specified
+explicitly by default (the PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES option disables
+this check). However, ranges such as [\x{d7ff}-\x{e000}], which include the
+surrogates, are always permitted.
+
+
+If a range that includes letters is used when caseless matching is set, it
+matches the letters in either case. For example, [W-c] is equivalent to
+[][\\^_`wxyzabc], matched caselessly, and in a non-UTF mode, if character
+tables for a French locale are in use, [\xc8-\xcb] matches accented E
+characters in both cases.
+
+
+A circumflex can conveniently be used with the upper case character types to
+specify a more restricted set of characters than the matching lower case type.
+For example, the class [^\W_] matches any letter or digit, but not underscore,
+whereas [\w] includes underscore. A positive character class should be read as
+"something OR something OR ..." and a negative class as "NOT something AND NOT
+something AND NOT ...".
+
+
+The metacharacters that are recognized in character classes are backslash,
+hyphen (when it can be interpreted as specifying a range), circumflex
+(only at the start), and the terminating closing square bracket. An opening
+square bracket is also special when it can be interpreted as introducing a
+POSIX class (see
+"Posix character classes"
+below), or a special compatibility feature (see
+"Compatibility feature for word boundaries"
+below. Escaping any non-alphanumeric character in a class turns it into a
+literal, whether or not it would otherwise be a metacharacter.
+
+
+
+From release 10.45 PCRE2 supports Perl's (?[...]) extended character class
+syntax. This can be used to perform set operations such as intersection on
+character classes.
+
+
+The syntax permitted within (?[...]) is quite different to ordinary character
+classes. Inside the extended class, there is an expression syntax consisting of
+"atoms", operators, and ordinary parentheses "()" used for grouping. Such
+classes always have the Perl /xx modifier (PCRE2 option PCRE2_EXTENDED_MORE)
+turned on within them. This means that literal space and tab characters are
+ignored everywhere in the class.
+
+
+The allowed atoms are individual characters specified by escape sequences such
+as \n or \x{123}, character types such as \d, POSIX classes such as
+[:alpha:], and nested ordinary (non-extended) character classes. For example,
+in (?[\d & [...]]) the nested class [...] follows the usual rules for ordinary
+character classes, in which parentheses are not metacharacters, and character
+literals and ranges are permitted.
+
+
+Character literals and ranges may not appear outside a nested ordinary
+character class because they are not atoms in the extended syntax. The extended
+syntax does not introduce any additional escape sequences, so (?[\y]) is an
+unknown escape, as it would be in [\y].
+
+
+In the extended syntax, ^ does not negate a class (except within an
+ordinary class nested inside an extended class); it is instead a binary
+operator.
+
+
+The binary operators are "&" (intersection), "|" or "+" (union), "-"
+(subtraction) and "^" (symmetric difference). These are left-associative and
+"&" has higher (tighter) precedence, while the others have equal lower
+precedence. The one prefix unary operator is "!" (complement), with highest
+precedence.
+
+
+
+The PCRE2_ALT_EXTENDED_CLASS option enables an alternative to Perl's (?[...])
+syntax, allowing instead extended class behaviour inside ordinary [...]
+character classes. This altered syntax for [...] classes is loosely described
+by the Unicode standard UTS#18. The PCRE2_ALT_EXTENDED_CLASS option does not
+prevent use of (?[...]) classes; it just changes the meaning of all
+[...] classes that are not nested inside a Perl (?[...]) class.
+
+
+Firstly, in ordinary Perl [...] syntax, an expression such as "[a[]" is a
+character class with two literal characters "a" and "[", but in UTS#18 extended
+classes the "[" character becomes an additional metacharacter within classes,
+denoting the start of a nested class, so a literal "[" must be escaped as "\[".
+
+
+Secondly, within the UTS#18 extended syntax, there are operators "||", "&&",
+"--" and "~~" which denote character class union, intersection, subtraction,
+and symmetric difference respectively. In standard Perl syntax, these would
+simply be needlessly-repeated literals (except for "--" which could be the
+start or end of a range). In UTS#18 extended classes these operators can be used
+in constructs such as [\p{L}--[QW]] for "Unicode letters, other than Q and W".
+A literal "-" at the start or end of a range must be escaped, so while "[--1]"
+in Perl syntax is the range from hyphen to "1", it must be escaped as "[\--1]"
+in UTS#18 extended classes.
+
+
+Unlike Perl's (?[...]) extended classes, the PCRE2_EXTENDED_MORE option to
+ignore space and tab characters is not automatically enabled for UTS#18
+extended classes, but it is honoured if set.
+
+
+Extended UTS#18 classes can be nested, and nested classes are themselves
+extended classes (unlike Perl, where nested classes must be simple classes).
+For example, [\p{L}&&[\p{Thai}||\p{Greek}]] matches any letter that is in
+the Thai or Greek scripts. Note that this means that no special grouping
+characters (such as the parentheses used in Perl's (?[...]) class syntax) are
+needed.
+
+
+Individual class items (literal characters, literal ranges, properties such as
+\d or \p{...}, and nested classes) can be combined by juxtaposition or by an
+operator. Juxtaposition is the implicit union operator, and binds more tightly
+than any explicit operator. Thus a sequence of literals and/or ranges behaves
+as if it is enclosed in square brackets. For example, [A-Z0-9&&[^E8]] is the
+same as [[A-Z0-9]&&[^E8]], which matches any upper case alphanumeric character
+except "E" or "8".
+
+
+Precedence between the explicit operators is not defined, so mixing operators
+is a syntax error. For example, [A&&B--C] is an error, but [A&&[B--C]] is
+valid.
+
+
+This is an emerging syntax which is being adopted gradually across the regex
+ecosystem: for example JavaScript adopted the "/v" flag in ECMAScript 2024;
+Python's "re" module reserves the syntax for future use with a FutureWarning
+for unescaped use of "[" as a literal within character classes. Due to UTS#18
+providing insufficient guidance, engines interpret the syntax differently.
+Rust's "regex" crate and Python's "regex" PyPi module both implement UTS#18
+extended classes, but with slight incompatibilities ([A||B&&C] is parsed as
+[A||[B&&C]] in Python's "regex" but as [[A||B]&&C] in Rust's "regex").
+
+
+PCRE2's syntax adds syntax restrictions similar to ECMASCript's /v flag, so
+that all the UTS#18 extended classes accepted as valid by PCRE2 have the
+property that they are interpreted either with the same behaviour, or as
+invalid, by all other major engines. Please file an issue if you are aware of
+cross-engine differences in behaviour between PCRE2 and another major engine.
+
+
+
+Perl supports the POSIX notation for character classes. This uses names
+enclosed by [: and :] within the enclosing square brackets. PCRE2 also supports
+this notation, in both ordinary and extended classes. For example,
+
+ [01[:alpha:]%]
+
+matches "0", "1", any alphabetic character, or "%". The supported class names
+are:
+
+ alnum letters and digits
+ alpha letters
+ ascii character codes 0 - 127
+ blank space or tab only
+ cntrl control characters
+ digit decimal digits (same as \d)
+ graph printing characters, excluding space
+ lower lower case letters
+ print printing characters, including space
+ punct printing characters, excluding letters and digits and space
+ space white space (the same as \s from PCRE2 8.34)
+ upper upper case letters
+ word "word" characters (same as \w)
+ xdigit hexadecimal digits
+
+The default "space" characters are HT (9), LF (10), VT (11), FF (12), CR (13),
+and space (32). If locale-specific matching is taking place, the list of space
+characters may be different; there may be fewer or more of them. "Space" and
+\s match the same set of characters, as do "word" and \w.
+
+
+The name "word" is a Perl extension, and "blank" is a GNU extension from Perl
+5.8. Another Perl extension is negation, which is indicated by a ^ character
+after the colon. For example,
+
+ [12[:^digit:]]
+
+matches "1", "2", or any non-digit. PCRE2 (and Perl) also recognize the POSIX
+syntax [.ch.] and [=ch=] where "ch" is a "collating element", but these are not
+supported, and an error is given if they are encountered.
+
+
+By default, characters with values greater than 127 do not match any of the
+POSIX character classes, although this may be different for characters in the
+range 128-255 when locale-specific matching is happening. However, in UCP mode,
+unless certain options are set (see below), some of the classes are changed so
+that Unicode character properties are used. This is achieved by replacing
+POSIX classes with other sequences, as follows:
+
+ [:alnum:] becomes \p{Xan}
+ [:alpha:] becomes \p{L}
+ [:blank:] becomes \h
+ [:cntrl:] becomes \p{Cc}
+ [:digit:] becomes \p{Nd}
+ [:lower:] becomes \p{Ll}
+ [:space:] becomes \p{Xps}
+ [:upper:] becomes \p{Lu}
+ [:word:] becomes \p{Xwd}
+
+Negated versions, such as [:^alpha:] use \P instead of \p. Four other POSIX
+classes are handled specially in UCP mode:
+
+
+[:graph:]
+This matches characters that have glyphs that mark the page when printed. In
+Unicode property terms, it matches all characters with the L, M, N, P, S, or Cf
+properties, except for:
+
+ U+061C Arabic Letter Mark
+ U+180E Mongolian Vowel Separator
+ U+2066 - U+2069 Various "isolate"s
+
+
+
+
+[:print:]
+This matches the same characters as [:graph:] plus space characters that are
+not controls, that is, characters with the Zs property.
+
+
+[:punct:]
+This matches all characters that have the Unicode P (punctuation) property,
+plus those characters with code points less than 256 that have the S (Symbol)
+property.
+
+
+[:xdigit:]
+In addition to the ASCII hexadecimal digits, this also matches the "fullwidth"
+versions of those characters, whose Unicode code points start at U+FF10. This
+is a change that was made in PCRE2 release 10.43 for Perl compatibility.
+
+
+The other POSIX classes are unchanged by PCRE2_UCP, and match only characters
+with code points less than 256.
+
+
+There are two options that can be used to restrict the POSIX classes to ASCII
+characters when PCRE2_UCP is set. The option PCRE2_EXTRA_ASCII_DIGIT affects
+just [:digit:] and [:xdigit:]. Within a pattern, this can be set and unset by
+(?aT) and (?-aT). The PCRE2_EXTRA_ASCII_POSIX option disables UCP processing
+for all POSIX classes, including [:digit:] and [:xdigit:]. Within a pattern,
+(?aP) and (?-aP) set and unset both these options for consistency.
+
+
+
+In the POSIX.2 compliant library that was included in 4.4BSD Unix, the ugly
+syntax [[:<:]] and [[:>:]] is used for matching "start of word" and "end of
+word". PCRE2 treats these items as follows:
+
+ [[:<:]] is converted to \b(?=\w)
+ [[:>:]] is converted to \b(?<=\w)
+
+Only these exact character sequences are recognized. A sequence such as
+[a[:<:]b] provokes error for an unrecognized POSIX class name. This support is
+not compatible with Perl. It is provided to help migrations from other
+environments, and is best not used in any new patterns. Note that \b matches
+at the start and the end of a word (see
+"Simple assertions"
+above), and in a Perl-style pattern the preceding or following character
+normally shows which is wanted, without the need for the assertions that are
+used above in order to give exactly the POSIX behaviour. Note also that the
+PCRE2_UCP option changes the meaning of \w (and therefore \b) by default, so
+it also affects these POSIX sequences.
+
+
+
+Vertical bar characters are used to separate alternative patterns. For example,
+the pattern
+
+ gilbert|sullivan
+
+matches either "gilbert" or "sullivan". Any number of alternatives may appear,
+and an empty alternative is permitted (matching the empty string). The matching
+process tries each alternative in turn, from left to right, and the first one
+that succeeds is used. If the alternatives are within a group
+(defined below),
+"succeeds" means matching the rest of the main pattern as well as the
+alternative in the group.
+
+
+
+The settings of several options can be changed within a pattern by a sequence
+of letters enclosed between "(?" and ")". The following are Perl-compatible,
+and are described in detail in the
+pcre2api
+documentation. The option letters are:
+
+ i for PCRE2_CASELESS
+ m for PCRE2_MULTILINE
+ n for PCRE2_NO_AUTO_CAPTURE
+ s for PCRE2_DOTALL
+ x for PCRE2_EXTENDED
+ xx for PCRE2_EXTENDED_MORE
+
+For example, (?im) sets caseless, multiline matching. It is also possible to
+unset these options by preceding the relevant letters with a hyphen, for
+example (?-im). The two "extended" options are not independent; unsetting
+either one cancels the effects of both of them.
+
+
+A combined setting and unsetting such as (?im-sx), which sets PCRE2_CASELESS
+and PCRE2_MULTILINE while unsetting PCRE2_DOTALL and PCRE2_EXTENDED, is also
+permitted. Only one hyphen may appear in the options string. If a letter
+appears both before and after the hyphen, the option is unset. An empty options
+setting "(?)" is allowed. Needless to say, it has no effect.
+
+
+If the first character following (? is a circumflex, it causes all of the above
+options to be unset. Letters may follow the circumflex to cause some options to
+be re-instated, but a hyphen may not appear.
+
+
+Some PCRE2-specific options can be changed by the same mechanism using these
+pairs or individual letters:
+
+ aD for PCRE2_EXTRA_ASCII_BSD
+ aS for PCRE2_EXTRA_ASCII_BSS
+ aW for PCRE2_EXTRA_ASCII_BSW
+ aP for PCRE2_EXTRA_ASCII_POSIX and PCRE2_EXTRA_ASCII_DIGIT
+ aT for PCRE2_EXTRA_ASCII_DIGIT
+ r for PCRE2_EXTRA_CASELESS_RESTRICT
+ J for PCRE2_DUPNAMES
+ U for PCRE2_UNGREEDY
+
+However, except for 'r', these are not unset by (?^), which is equivalent to
+(?-imnrsx). If 'a' is not followed by any of the upper case letters shown
+above, it sets (or unsets) all the ASCII options.
+
+
+PCRE2_EXTRA_ASCII_DIGIT has no additional effect when PCRE2_EXTRA_ASCII_POSIX
+is set, but including it in (?aP) means that (?-aP) suppresses all ASCII
+restrictions for POSIX classes.
+
+
+When one of these option changes occurs at top level (that is, not inside group
+parentheses), the change applies until a subsequent change, or the end of the
+pattern. An option change within a group (see below for a description of
+groups) affects only that part of the group that follows it. At the end of the
+group these options are reset to the state they were before the group. For
+example,
+
+ (a(?i)b)c
+
+matches abc and aBc and no other strings (assuming PCRE2_CASELESS is not set
+externally). Any changes made in one alternative do carry on into subsequent
+branches within the same group. For example,
+
+ (a(?i)b|c)
+
+matches "ab", "aB", "c", and "C", even though when matching "C" the first
+branch is abandoned before the option setting. This is because the effects of
+option settings happen at compile time. There would be some very weird
+behaviour otherwise.
+
+
+As a convenient shorthand, if any option settings are required at the start of
+a non-capturing group (see the next section), the option letters may
+appear between the "?" and the ":". Thus the two patterns
+
+ (?i:saturday|sunday)
+ (?:(?i)saturday|sunday)
+
+match exactly the same set of strings.
+
+
+Note: There are other PCRE2-specific options, applying to the whole
+pattern, which can be set by the application when the compiling function is
+called. In addition, the pattern can contain special leading sequences such as
+(*CRLF) to override what the application has set or what has been defaulted.
+Details are given in the section entitled
+"Newline sequences"
+above. There are also the (*UTF) and (*UCP) leading sequences that can be used
+to set UTF and Unicode property modes; they are equivalent to setting the
+PCRE2_UTF and PCRE2_UCP options, respectively. However, the application can set
+the PCRE2_NEVER_UTF or PCRE2_NEVER_UCP options, which lock out the use of the
+(*UTF) and (*UCP) sequences.
+
+
+
+Groups are delimited by parentheses (round brackets), which can be nested.
+Turning part of a pattern into a group does two things:
+
+
+1. It localizes a set of alternatives. For example, the pattern
+
+ cat(aract|erpillar|)
+
+matches "cataract", "caterpillar", or "cat". Without the parentheses, it would
+match "cataract", "erpillar" or an empty string.
+
+
+2. It creates a "capture group". This means that, when the whole pattern
+matches, the portion of the subject string that matched the group is passed
+back to the caller, separately from the portion that matched the whole pattern.
+(This applies only to the traditional matching function; the DFA matching
+function does not support capturing.)
+
+
+Opening parentheses are counted from left to right (starting from 1) to obtain
+numbers for capture groups. For example, if the string "the red king" is
+matched against the pattern
+
+ the ((red|white) (king|queen))
+
+the captured substrings are "red king", "red", and "king", and are numbered 1,
+2, and 3, respectively.
+
+
+The fact that plain parentheses fulfil two functions is not always helpful.
+There are often times when grouping is required without capturing. If an
+opening parenthesis is followed by a question mark and a colon, the group
+does not do any capturing, and is not counted when computing the number of any
+subsequent capture groups. For example, if the string "the white queen"
+is matched against the pattern
+
+ the ((?:red|white) (king|queen))
+
+the captured substrings are "white queen" and "queen", and are numbered 1 and
+2. The maximum number of capture groups is 65535.
+
+
+As a convenient shorthand, if any option settings are required at the start of
+a non-capturing group, the option letters may appear between the "?" and the
+":". Thus the two patterns
+
+ (?i:saturday|sunday)
+ (?:(?i)saturday|sunday)
+
+match exactly the same set of strings. Because alternative branches are tried
+from left to right, and options are not reset until the end of the group is
+reached, an option setting in one branch does affect subsequent branches, so
+the above patterns match "SUNDAY" as well as "Saturday".
+
+
+
+Perl 5.10 introduced a feature whereby each alternative in a group uses the
+same numbers for its capturing parentheses. Such a group starts with (?| and is
+itself a non-capturing group. For example, consider this pattern:
+
+ (?|(Sat)ur|(Sun))day
+
+Because the two alternatives are inside a (?| group, both sets of capturing
+parentheses are numbered one. Thus, when the pattern matches, you can look
+at captured substring number one, whichever alternative matched. This construct
+is useful when you want to capture part, but not all, of one of a number of
+alternatives. Inside a (?| group, parentheses are numbered as usual, but the
+number is reset at the start of each branch. The numbers of any capturing
+parentheses that follow the whole group start after the highest number used in
+any branch. The following example is taken from the Perl documentation. The
+numbers underneath show in which buffer the captured content will be stored.
+
+ # before ---------------branch-reset----------- after
+ / ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x
+ # 1 2 2 3 2 3 4
+
+A backreference to a capture group uses the most recent value that is set for
+the group. The following pattern matches "abcabc" or "defdef":
+
+ /(?|(abc)|(def))\1/
+
+In contrast, a subroutine call to a capture group always refers to the
+first one in the pattern with the given number. The following pattern matches
+"abcabc" or "defabc":
+
+ /(?|(abc)|(def))(?1)/
+
+A relative reference such as (?-1) is no different: it is just a convenient way
+of computing an absolute group number.
+
+
+If a
+condition test
+for a group's having matched refers to a non-unique number, the test is
+true if any group with that number has matched.
+
+
+An alternative approach to using this "branch reset" feature is to use
+duplicate named groups, as described in the next section.
+
+
+
+Identifying capture groups by number is simple, but it can be very hard to keep
+track of the numbers in complicated patterns. Furthermore, if an expression is
+modified, the numbers may change. To help with this difficulty, PCRE2 supports
+the naming of capture groups. This feature was not added to Perl until release
+5.10. Python had the feature earlier, and PCRE1 introduced it at release 4.0,
+using the Python syntax. PCRE2 supports both the Perl and the Python syntax.
+
+
+In PCRE2, a capture group can be named in one of three ways: (?<name>...) or
+(?'name'...) as in Perl, or (?P<name>...) as in Python. Names may be up to
+128 code units long. When PCRE2_UTF is not set, they may contain only ASCII
+alphanumeric characters and underscores, but must start with a non-digit. When
+PCRE2_UTF is set, the syntax of group names is extended to allow any Unicode
+letter or Unicode decimal digit. In other words, group names must match one of
+these patterns:
+
+ ^[_A-Za-z][_A-Za-z0-9]*\z when PCRE2_UTF is not set
+ ^[_\p{L}][_\p{L}\p{Nd}]*\z when PCRE2_UTF is set
+
+References to capture groups from other parts of the pattern, such as
+backreferences,
+recursion,
+and
+conditions,
+can all be made by name as well as by number.
+
+
+Named capture groups are allocated numbers as well as names, exactly as
+if the names were not present. In both PCRE2 and Perl, capture groups
+are primarily identified by numbers; any names are just aliases for these
+numbers. The PCRE2 API provides function calls for extracting the complete
+name-to-number translation table from a compiled pattern, as well as
+convenience functions for extracting captured substrings by name.
+
+
+Warning: When more than one capture group has the same number, as
+described in the previous section, a name given to one of them applies to all
+of them. Perl allows identically numbered groups to have different names.
+Consider this pattern, where there are two capture groups, both numbered 1:
+
+ (?|(?<AA>aa)|(?<BB>bb))
+
+Perl allows this, with both names AA and BB as aliases of group 1. Thus, after
+a successful match, both names yield the same value (either "aa" or "bb").
+
+
+In an attempt to reduce confusion, PCRE2 does not allow the same group number
+to be associated with more than one name. The example above provokes a
+compile-time error. However, there is still scope for confusion. Consider this
+pattern:
+
+ (?|(?<AA>aa)|(bb))
+
+Although the second group number 1 is not explicitly named, the name AA is
+still an alias for any group 1. Whether the pattern matches "aa" or "bb", a
+reference by name to group AA yields the matched string.
+
+
+By default, a name must be unique within a pattern, except that duplicate names
+are permitted for groups with the same number, for example:
+
+ (?|(?<AA>aa)|(?<AA>bb))
+
+The duplicate name constraint can be disabled by setting the PCRE2_DUPNAMES
+option at compile time, or by the use of (?J) within the pattern, as described
+in the section entitled
+"Internal Option Setting"
+above.
+
+
+Duplicate names can be useful for patterns where only one instance of the named
+capture group can match. Suppose you want to match the name of a weekday,
+either as a 3-letter abbreviation or as the full name, and in both cases you
+want to extract the abbreviation. This pattern (ignoring the line breaks) does
+the job:
+
+ (?J)
+ (?<DN>Mon|Fri|Sun)(?:day)?|
+ (?<DN>Tue)(?:sday)?|
+ (?<DN>Wed)(?:nesday)?|
+ (?<DN>Thu)(?:rsday)?|
+ (?<DN>Sat)(?:urday)?
+
+There are five capture groups, but only one is ever set after a match. The
+convenience functions for extracting the data by name returns the substring for
+the first (and in this example, the only) group of that name that matched. This
+saves searching to find which numbered group it was. (An alternative way of
+solving this problem is to use a "branch reset" group, as described in the
+previous section.)
+
+
+If you make a backreference to a non-unique named group from elsewhere in the
+pattern, the groups to which the name refers are checked in the order in which
+they appear in the overall pattern. The first one that is set is used for the
+reference. For example, this pattern matches both "foofoo" and "barbar" but not
+"foobar" or "barfoo":
+
+ (?J)(?:(?<n>foo)|(?<n>bar))\k<n>
+
+
+
+
+If you make a subroutine call to a non-unique named group, the one that
+corresponds to the first occurrence of the name is used. In the absence of
+duplicate numbers this is the one with the lowest number.
+
+
+If you use a named reference in a condition
+test (see the
+section about conditions
+below), either to check whether a capture group has matched, or to check for
+recursion, all groups with the same name are tested. If the condition is true
+for any one of them, the overall condition is true. This is the same behaviour
+as testing by number. For further details of the interfaces for handling named
+capture groups, see the
+pcre2api
+documentation.
+
+
+
+Repetition is specified by quantifiers, which may follow any one of these
+items:
+
+ a literal data character
+ the dot metacharacter
+ the \C escape sequence
+ the \R escape sequence
+ the \X escape sequence
+ any escape sequence that matches a single character
+ a character class
+ a backreference
+ a parenthesized group (including lookaround assertions)
+ a subroutine call (recursive or otherwise)
+
+If a quantifier does not follow a repeatable item, an error occurs. The
+general repetition quantifier specifies a minimum and maximum number of
+permitted matches by giving two numbers in curly brackets (braces), separated
+by a comma. The numbers must be less than 65536, and the first must be less
+than or equal to the second. For example,
+
+ z{2,4}
+
+matches "zz", "zzz", or "zzzz". A closing brace on its own is not a special
+character. If the second number is omitted, but the comma is present, there is
+no upper limit; if the second number and the comma are both omitted, the
+quantifier specifies an exact number of required matches. Thus
+
+ [aeiou]{3,}
+
+matches at least 3 successive vowels, but may match many more, whereas
+
+ \d{8}
+
+matches exactly 8 digits. If the first number is omitted, the lower limit is
+taken as zero; in this case the upper limit must be present.
+
+ X{,4} is interpreted as X{0,4}
+
+This is a change in behaviour that happened in Perl 5.34.0 and PCRE2 10.43. In
+earlier versions such a sequence was not interpreted as a quantifier. Other
+regular expression engines may behave either way.
+
+
+If the characters that follow an opening brace do not match the syntax of a
+quantifier, the brace is taken as a literal character. In particular, this
+means that {,} is a literal string of three characters.
+
+
+Note that not every opening brace is potentially the start of a quantifier
+because braces are used in other items such as \N{U+345} or \k{name}.
+
+
+In UTF modes, quantifiers apply to characters rather than to individual code
+units. Thus, for example, \x{100}{2} matches two characters, each of
+which is represented by a two-byte sequence in a UTF-8 string. Similarly,
+\X{3} matches three Unicode extended grapheme clusters, each of which may be
+several code units long (and they may be of different lengths).
+
+
+The quantifier {0} is permitted, causing the expression to behave as if the
+previous item and the quantifier were not present. This may be useful for
+capture groups that are referenced as
+subroutines
+from elsewhere in the pattern (but see also the section entitled
+"Defining capture groups for use by reference only"
+below). Except for parenthesized groups, items that have a {0} quantifier are
+omitted from the compiled pattern.
+
+
+For convenience, the three most common quantifiers have single-character
+abbreviations:
+
+ * is equivalent to {0,}
+ + is equivalent to {1,}
+ ? is equivalent to {0,1}
+
+It is possible to construct infinite loops by following a group that can match
+no characters with a quantifier that has no upper limit, for example:
+
+ (a?)*
+
+Earlier versions of Perl and PCRE1 used to give an error at compile time for
+such patterns. However, because there are cases where this can be useful, such
+patterns are now accepted, but whenever an iteration of such a group matches no
+characters, matching moves on to the next item in the pattern instead of
+repeatedly matching an empty string. This does not prevent backtracking into
+any of the iterations if a subsequent item fails to match.
+
+
+By default, quantifiers are "greedy", that is, they match as much as possible
+(up to the maximum number of permitted repetitions), without causing the rest
+of the pattern to fail. The classic example of where this gives problems is in
+trying to match comments in C programs. These appear between /* and */ and
+within the comment, individual * and / characters may appear. An attempt to
+match C comments by applying the pattern
+
+ /\*.*\*/
+
+to the string
+
+ /* first comment */ not comment /* second comment */
+
+fails, because it matches the entire string owing to the greediness of the .*
+item. However, if a quantifier is followed by a question mark, it ceases to be
+greedy, and instead matches the minimum number of times possible, so the
+pattern
+
+ /\*.*?\*/
+
+does the right thing with C comments. The meaning of the various quantifiers is
+not otherwise changed, just the preferred number of matches. Do not confuse
+this use of question mark with its use as a quantifier in its own right.
+Because it has two uses, it can sometimes appear doubled, as in
+
+ \d??\d
+
+which matches one digit by preference, but can match two if that is the only
+way the rest of the pattern matches.
+
+
+If the PCRE2_UNGREEDY option is set (an option that is not available in Perl),
+the quantifiers are not greedy by default, but individual ones can be made
+greedy by following them with a question mark. In other words, it inverts the
+default behaviour.
+
+
+When a parenthesized group is quantified with a minimum repeat count that
+is greater than 1 or with a limited maximum, more memory is required for the
+compiled pattern, in proportion to the size of the minimum or maximum.
+
+
+If a pattern starts with .* or .{0,} and the PCRE2_DOTALL option (equivalent
+to Perl's /s) is set, thus allowing the dot to match newlines, the pattern is
+implicitly anchored, because whatever follows will be tried against every
+character position in the subject string, so there is no point in retrying the
+overall match at any position after the first. PCRE2 normally treats such a
+pattern as though it were preceded by \A.
+
+
+In cases where it is known that the subject string contains no newlines, it is
+worth setting PCRE2_DOTALL in order to obtain this optimization, or
+alternatively, using ^ to indicate anchoring explicitly.
+
+
+However, there are some cases where the optimization cannot be used. When .*
+is inside capturing parentheses that are the subject of a backreference
+elsewhere in the pattern, a match at the start may fail where a later one
+succeeds. Consider, for example:
+
+ (.*)abc\1
+
+If the subject is "xyz123abc123" the match point is the fourth character. For
+this reason, such a pattern is not implicitly anchored.
+
+
+Another case where implicit anchoring is not applied is when the leading .* is
+inside an atomic group. Once again, a match at the start may fail where a later
+one succeeds. Consider this pattern:
+
+ (?>.*?a)b
+
+It matches "ab" in the subject "aab". The use of the backtracking control verbs
+(*PRUNE) and (*SKIP) also disable this optimization. To do so explicitly,
+either pass the compile option PCRE2_NO_DOTSTAR_ANCHOR, or call
+pcre2_set_optimize() with a PCRE2_DOTSTAR_ANCHOR_OFF directive.
+
+
+When a capture group is repeated, the value captured is the substring that
+matched the final iteration. For example, after
+
+ (tweedle[dume]{3}\s*)+
+
+has matched "tweedledum tweedledee" the value of the captured substring is
+"tweedledee". However, if there are nested capture groups, the corresponding
+captured values may have been set in previous iterations. For example, after
+
+ (a|(b))+
+
+matches "aba" the value of the second captured substring is "b".
+
+
+
+With both maximizing ("greedy") and minimizing ("ungreedy" or "lazy")
+repetition, failure of what follows normally causes the repeated item to be
+re-evaluated to see if a different number of repeats allows the rest of the
+pattern to match. Sometimes it is useful to prevent this, either to change the
+nature of the match, or to cause it fail earlier than it otherwise might, when
+the author of the pattern knows there is no point in carrying on.
+
+
+Consider, for example, the pattern \d+foo when applied to the subject line
+
+ 123456bar
+
+After matching all 6 digits and then failing to match "foo", the normal
+action of the matcher is to try again with only 5 digits matching the \d+
+item, and then with 4, and so on, before ultimately failing. "Atomic grouping"
+(a term taken from Jeffrey Friedl's book) provides the means for specifying
+that once a group has matched, it is not to be re-evaluated in this way.
+
+
+If we use atomic grouping for the previous example, the matcher gives up
+immediately on failing to match "foo" the first time. The notation is a kind of
+special parenthesis, starting with (?> as in this example:
+
+ (?>\d+)foo
+
+Perl 5.28 introduced an experimental alphabetic form starting with (* which may
+be easier to remember:
+
+ (*atomic:\d+)foo
+
+This kind of parenthesized group "locks up" the part of the pattern it contains
+once it has matched, and a failure further into the pattern is prevented from
+backtracking into it. Backtracking past it to previous items, however, works as
+normal.
+
+
+An alternative description is that a group of this type matches exactly the
+string of characters that an identical standalone pattern would match, if
+anchored at the current point in the subject string.
+
+
+Atomic groups are not capture groups. Simple cases such as the above example
+can be thought of as a maximizing repeat that must swallow everything it can.
+So, while both \d+ and \d+? are prepared to adjust the number of digits they
+match in order to make the rest of the pattern match, (?>\d+) can only match
+an entire sequence of digits.
+
+
+Atomic groups in general can of course contain arbitrarily complicated
+expressions, and can be nested. However, when the contents of an atomic
+group is just a single repeated item, as in the example above, a simpler
+notation, called a "possessive quantifier" can be used. This consists of an
+additional + character following a quantifier. Using this notation, the
+previous example can be rewritten as
+
+ \d++foo
+
+Note that a possessive quantifier can be used with an entire group, for
+example:
+
+ (abc|xyz){2,3}+
+
+Possessive quantifiers are always greedy; the setting of the PCRE2_UNGREEDY
+option is ignored. They are a convenient notation for the simpler forms of
+atomic group. However, there is no difference in the meaning of a possessive
+quantifier and the equivalent atomic group, though there may be a performance
+difference; possessive quantifiers should be slightly faster.
+
+
+The possessive quantifier syntax is an extension to the Perl 5.8 syntax.
+Jeffrey Friedl originated the idea (and the name) in the first edition of his
+book. Mike McCloskey liked it, so implemented it when he built Sun's Java
+package, and PCRE1 copied it from there. It found its way into Perl at release
+5.10.
+
+
+PCRE2 has an optimization that automatically "possessifies" certain simple
+pattern constructs. For example, the sequence A+B is treated as A++B because
+there is no point in backtracking into a sequence of A's when B must follow.
+This feature can be disabled by the PCRE2_NO_AUTO_POSSESS option, by calling
+pcre2_set_optimize() with a PCRE2_AUTO_POSSESS_OFF directive, or by
+starting the pattern with (*NO_AUTO_POSSESS).
+
+
+When a pattern contains an unlimited repeat inside a group that can itself be
+repeated an unlimited number of times, the use of an atomic group is the only
+way to avoid some failing matches taking a very long time indeed. The pattern
+
+ (\D+|<\d+>)*[!?]
+
+matches an unlimited number of substrings that either consist of non-digits, or
+digits enclosed in <>, followed by either ! or ?. When it matches, it runs
+quickly. However, if it is applied to
+
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+
+it takes a long time before reporting failure. This is because the string can
+be divided between the internal \D+ repeat and the external * repeat in a
+large number of ways, and all have to be tried. (The example uses [!?] rather
+than a single character at the end, because both PCRE2 and Perl have an
+optimization that allows for fast failure when a single character is used. They
+remember the last single character that is required for a match, and fail early
+if it is not present in the string.) If the pattern is changed so that it uses
+an atomic group, like this:
+
+ ((?>\D+)|<\d+>)*[!?]
+
+sequences of non-digits cannot be broken, and failure happens quickly.
+
+
+
+Outside a character class, a backslash followed by a digit greater than 0 (and
+possibly further digits) is a backreference to a capture group earlier (that
+is, to its left) in the pattern, provided there have been that many previous
+capture groups.
+
+
+However, if the decimal number following the backslash is less than 8, it is
+always taken as a backreference, and causes an error only if there are not that
+many capture groups in the entire pattern. In other words, the group that is
+referenced need not be to the left of the reference for numbers less than 8. A
+"forward backreference" of this type can make sense when a repetition is
+involved and the group to the right has participated in an earlier iteration.
+
+
+It is not possible to have a numerical "forward backreference" to a group whose
+number is 8 or more using this syntax because a sequence such as \50 is
+interpreted as a character defined in octal. See the subsection entitled
+"Non-printing characters"
+above
+for further details of the handling of digits following a backslash. Other
+forms of backreferencing do not suffer from this restriction. In particular,
+there is no problem when named capture groups are used (see below).
+
+
+Another way of avoiding the ambiguity inherent in the use of digits following a
+backslash is to use the \g escape sequence. This escape must be followed by a
+signed or unsigned number, optionally enclosed in braces. These examples are
+all identical:
+
+ (ring), \1
+ (ring), \g1
+ (ring), \g{1}
+
+An unsigned number specifies an absolute reference without the ambiguity that
+is present in the older syntax. It is also useful when literal digits follow
+the reference. A signed number is a relative reference. Consider this example:
+
+ (abc(def)ghi)\g{-1}
+
+The sequence \g{-1} is a reference to the capture group whose number is one
+less than the number of the next group to be started, so in this example (where
+the next group would be numbered 3) is it equivalent to \2, and \g{-2} would
+be equivalent to \1. Note that if this construct is inside a capture group,
+that group is included in the count, so in this example \g{-2} also refers to
+group 1:
+
+ (A)(\g{-2}B)
+
+The use of relative references can be helpful in long patterns, and also in
+patterns that are created by joining together fragments that contain references
+within themselves.
+
+
+The sequence \g{+1} is a reference to the next capture group that is started
+after this item, and \g{+2} refers to the one after that, and so on. This kind
+of forward reference can be useful in patterns that repeat. Perl does not
+support the use of + in this way.
+
+
+A backreference matches whatever actually most recently matched the capture
+group in the current subject string, rather than anything at all that matches
+the group (see
+"Groups as subroutines"
+below for a way of doing that). So the pattern
+
+ (sens|respons)e and \1ibility
+
+matches "sense and sensibility" and "response and responsibility", but not
+"sense and responsibility". If caseful matching is in force at the time of the
+backreference, the case of letters is relevant. For example,
+
+ ((?i)rah)\s+\1
+
+matches "rah rah" and "RAH RAH", but not "RAH rah", even though the original
+capture group is matched caselessly.
+
+
+There are several different ways of writing backreferences to named capture
+groups. The .NET syntax is \k{name}, the Python syntax is (?=name), and the
+original Perl syntax is \k<name> or \k'name'. All of these are now supported
+by both Perl and PCRE2. Perl 5.10's unified backreference syntax, in which \g
+can be used for both numeric and named references, is also supported by PCRE2.
+We could rewrite the above example in any of the following ways:
+
+ (?<p1>(?i)rah)\s+\k<p1>
+ (?'p1'(?i)rah)\s+\k{p1}
+ (?P<p1>(?i)rah)\s+(?P=p1)
+ (?<p1>(?i)rah)\s+\g{p1}
+
+A capture group that is referenced by name may appear in the pattern before or
+after the reference.
+
+
+There may be more than one backreference to the same group. If a group has not
+actually been used in a particular match, backreferences to it always fail by
+default. For example, the pattern
+
+ (a|(bc))\2
+
+always fails if it starts to match "a" rather than "bc". However, if the
+PCRE2_MATCH_UNSET_BACKREF option is set at compile time, a backreference to an
+unset value matches an empty string.
+
+
+Because there may be many capture groups in a pattern, all digits following a
+backslash are taken as part of a potential backreference number. If the pattern
+continues with a digit character, some delimiter must be used to terminate the
+backreference. If the PCRE2_EXTENDED or PCRE2_EXTENDED_MORE option is set, this
+can be white space. Otherwise, the \g{} syntax or an empty comment (see
+"Comments"
+below) can be used.
+
+
+Recursive backreferences
+
+
+A backreference that occurs inside the group to which it refers fails when the
+group is first used, so, for example, (a\1) never matches. However, such
+references can be useful inside repeated groups. For example, the pattern
+
+ (a|b\1)+
+
+matches any number of "a"s and also "aba", "ababbaa" etc. At each iteration of
+the group, the backreference matches the character string corresponding to the
+previous iteration. In order for this to work, the pattern must be such that
+the first iteration does not need to match the backreference. This can be done
+using alternation, as in the example above, or by a quantifier with a minimum
+of zero.
+
+
+For versions of PCRE2 less than 10.25, backreferences of this type used to
+cause the group that they reference to be treated as an
+atomic group.
+This restriction no longer applies, and backtracking into such groups can occur
+as normal.
+
+
+
+An assertion is a test that does not consume any characters. The test must
+succeed for the match to continue. The simple assertions coded as \b, \B,
+\A, \G, \Z, \z, ^ and $ are described
+above.
+
+
+More complicated assertions are coded as parenthesized groups. If matching such
+a group succeeds, matching continues after it, but with the matching position
+in the subject string reset to what it was before the assertion was processed.
+
+
+A special kind of assertion, called a "scan substring" assertion, matches a
+subpattern against a previously captured substring. This is described in the
+section entitled
+"Scan substring assertions"
+below. It is a PCRE2 extension, not compatible with Perl.
+
+
+The other goup-based assertions are of two kinds: those that look ahead of the
+current position in the subject string, and those that look behind it, and in
+each case an assertion may be positive (must match for the assertion to be
+true) or negative (must not match for the assertion to be true).
+
+
+The Perl-compatible lookaround assertions are atomic. If an assertion is true,
+but there is a subsequent matching failure, there is no backtracking into the
+assertion. However, there are some cases where non-atomic assertions can be
+useful. PCRE2 has some support for these, described in the section entitled
+"Non-atomic assertions"
+below, but they are not Perl-compatible.
+
+
+A lookaround assertion may appear as the condition in a
+conditional group
+(see below). In this case, the result of matching the assertion determines
+which branch of the condition is followed.
+
+
+Assertion groups are not capture groups. If an assertion contains capture
+groups within it, these are counted for the purposes of numbering the capture
+groups in the whole pattern. Within each branch of an assertion, locally
+captured substrings may be referenced in the usual way. For example, a sequence
+such as (.)\g{-1} can be used to check that two adjacent characters are the
+same.
+
+
+When a branch within an assertion fails to match, any substrings that were
+captured are discarded (as happens with any pattern branch that fails to
+match). A negative assertion is true only when all its branches fail to match;
+this means that no captured substrings are ever retained after a successful
+negative assertion. When an assertion contains a matching branch, what happens
+depends on the type of assertion.
+
+
+For a positive assertion, internally captured substrings in the successful
+branch are retained, and matching continues with the next pattern item after
+the assertion. For a negative assertion, a matching branch means that the
+assertion is not true. If such an assertion is being used as a condition in a
+conditional group
+(see below), captured substrings are retained, because matching continues with
+the "no" branch of the condition. For other failing negative assertions,
+control passes to the previous backtracking point, thus discarding any captured
+strings within the assertion.
+
+
+Most assertion groups may be repeated; though it makes no sense to assert the
+same thing several times, the side effect of capturing in positive assertions
+may occasionally be useful. However, an assertion that forms the condition for
+a conditional group may not be quantified. PCRE2 used to restrict the
+repetition of assertions, but from release 10.35 the only restriction is that
+an unlimited maximum repetition is changed to be one more than the minimum. For
+example, {3,} is treated as {3,4}.
+
+
+Alphabetic assertion names
+
+
+Traditionally, symbolic sequences such as (?= and (?<= have been used to
+specify lookaround assertions. Perl 5.28 introduced some experimental
+alphabetic alternatives which might be easier to remember. They all start with
+(* instead of (? and must be written using lower case letters. PCRE2 supports
+the following synonyms:
+
+ (*positive_lookahead: or (*pla: is the same as (?=
+ (*negative_lookahead: or (*nla: is the same as (?!
+ (*positive_lookbehind: or (*plb: is the same as (?<=
+ (*negative_lookbehind: or (*nlb: is the same as (?<!
+
+For example, (*pla:foo) is the same assertion as (?=foo). In the following
+sections, the various assertions are described using the original symbolic
+forms.
+
+
+Lookahead assertions
+
+
+Lookahead assertions start with (?= for positive assertions and (?! for
+negative assertions. For example,
+
+ \w+(?=;)
+
+matches a word followed by a semicolon, but does not include the semicolon in
+the match, and
+
+ foo(?!bar)
+
+matches any occurrence of "foo" that is not followed by "bar". Note that the
+apparently similar pattern
+
+ (?!foo)bar
+
+does not find an occurrence of "bar" that is preceded by something other than
+"foo"; it finds any occurrence of "bar" whatsoever, because the assertion
+(?!foo) is always true when the next three characters are "bar". A
+lookbehind assertion is needed to achieve the other effect.
+
+
+If you want to force a matching failure at some point in a pattern, the most
+convenient way to do it is with (?!) because an empty string always matches, so
+an assertion that requires there not to be an empty string must always fail.
+The backtracking control verb (*FAIL) or (*F) is a synonym for (?!).
+
+
+Lookbehind assertions
+
+
+Lookbehind assertions start with (?<= for positive assertions and (?<! for
+negative assertions. For example,
+
+ (?<!foo)bar
+
+does find an occurrence of "bar" that is not preceded by "foo". The contents of
+a lookbehind assertion are restricted such that there must be a known maximum
+to the lengths of all the strings it matches. There are two cases:
+
+
+If every top-level alternative matches a fixed length, for example
+
+ (?<=colour|color)
+
+there is a limit of 65535 characters to the lengths, which do not have to be
+the same, as this example demonstrates. This is the only kind of lookbehind
+supported by PCRE2 versions earlier than 10.43 and by the alternative matching
+function pcre2_dfa_match().
+
+
+In PCRE2 10.43 and later, pcre2_match() supports lookbehind assertions in
+which one or more top-level alternatives can match more than one string length,
+for example
+
+ (?<=colou?r)
+
+The maximum matching length for any branch of the lookbehind is limited to a
+value set by the calling program (default 255 characters). Unlimited repetition
+(for example \d*) is not supported. In some cases, the escape sequence \K
+(see above)
+can be used instead of a lookbehind assertion at the start of a pattern to get
+round the length limit restriction.
+
+
+In UTF-8 and UTF-16 modes, PCRE2 does not allow the \C escape (which matches a
+single code unit even in a UTF mode) to appear in lookbehind assertions,
+because it makes it impossible to calculate the length of the lookbehind. The
+\X and \R escapes, which can match different numbers of code units, are never
+permitted in lookbehinds.
+
+
+"Subroutine"
+calls (see below) such as (?2) or (?&X) are permitted in lookbehinds, as long
+as the called capture group matches a limited-length string. However,
+recursion,
+that is, a "subroutine" call into a group that is already active,
+is not supported.
+
+
+PCRE2 supports backreferences in lookbehinds, but only if certain conditions
+are met. The PCRE2_MATCH_UNSET_BACKREF option must not be set, there must be no
+use of (?| in the pattern (it creates duplicate group numbers), and if the
+backreference is by name, the name must be unique. Of course, the referenced
+group must itself match a limited length substring. The following pattern
+matches words containing at least two characters that begin and end with the
+same character:
+
+ \b(\w)\w++(?<=\1)
+
+
+
+Possessive quantifiers can be used in conjunction with lookbehind assertions to
+specify efficient matching at the end of subject strings. Consider a simple
+pattern such as
+
+ abcd$
+
+when applied to a long string that does not match. Because matching proceeds
+from left to right, PCRE2 will look for each "a" in the subject and then see if
+what follows matches the rest of the pattern. If the pattern is specified as
+
+ ^.*abcd$
+
+the initial .* matches the entire string at first, but when this fails (because
+there is no following "a"), it backtracks to match all but the last character,
+then all but the last two characters, and so on. Once again the search for "a"
+covers the entire string, from right to left, so we are no better off. However,
+if the pattern is written as
+
+ ^.*+(?<=abcd)
+
+there can be no backtracking for the .*+ item because of the possessive
+quantifier; it can match only the entire string. The subsequent lookbehind
+assertion does a single test on the last four characters. If it fails, the
+match fails immediately. For long strings, this approach makes a significant
+difference to the processing time.
+
+
+Using multiple assertions
+
+
+Several assertions (of any sort) may occur in succession. For example,
+
+ (?<=\d{3})(?<!999)foo
+
+matches "foo" preceded by three digits that are not "999". Notice that each of
+the assertions is applied independently at the same point in the subject
+string. First there is a check that the previous three characters are all
+digits, and then there is a check that the same three characters are not "999".
+This pattern does not match "foo" preceded by six characters, the first
+of which are digits and the last three of which are not "999". For example, it
+doesn't match "123abcfoo". A pattern to do that is
+
+ (?<=\d{3}...)(?<!999)foo
+
+This time the first assertion looks at the preceding six characters, checking
+that the first three are digits, and then the second assertion checks that the
+preceding three characters are not "999".
+
+
+Assertions can be nested in any combination. For example,
+
+ (?<=(?<!foo)bar)baz
+
+matches an occurrence of "baz" that is preceded by "bar" which in turn is not
+preceded by "foo", while
+
+ (?<=\d{3}(?!999)...)foo
+
+is another pattern that matches "foo" preceded by three digits and any three
+characters that are not "999".
+
+
+
+Traditional lookaround assertions are atomic. That is, if an assertion is true,
+but there is a subsequent matching failure, there is no backtracking into the
+assertion. However, there are some cases where non-atomic positive assertions
+can be useful. PCRE2 provides these using the following syntax:
+
+ (*non_atomic_positive_lookahead: or (*napla: or (?*
+ (*non_atomic_positive_lookbehind: or (*naplb: or (?<*
+
+Consider the problem of finding the right-most word in a string that also
+appears earlier in the string, that is, it must appear at least twice in total.
+This pattern returns the required result as captured substring 1:
+
+ ^(?x)(*napla: .* \b(\w++)) (?> .*? \b\1\b ){2}
+
+For a subject such as "word1 word2 word3 word2 word3 word4" the result is
+"word3". How does it work? At the start, ^(?x) anchors the pattern and sets the
+"x" option, which causes white space (introduced for readability) to be
+ignored. Inside the assertion, the greedy .* at first consumes the entire
+string, but then has to backtrack until the rest of the assertion can match a
+word, which is captured by group 1. In other words, when the assertion first
+succeeds, it captures the right-most word in the string.
+
+
+The current matching point is then reset to the start of the subject, and the
+rest of the pattern match checks for two occurrences of the captured word,
+using an ungreedy .*? to scan from the left. If this succeeds, we are done, but
+if the last word in the string does not occur twice, this part of the pattern
+fails. If a traditional atomic lookahead (?= or (*pla: had been used, the
+assertion could not be re-entered, and the whole match would fail. The pattern
+would succeed only if the very last word in the subject was found twice.
+
+
+Using a non-atomic lookahead, however, means that when the last word does not
+occur twice in the string, the lookahead can backtrack and find the second-last
+word, and so on, until either the match succeeds, or all words have been
+tested.
+
+
+Two conditions must be met for a non-atomic assertion to be useful: the
+contents of one or more capturing groups must change after a backtrack into the
+assertion, and there must be a backreference to a changed group later in the
+pattern. If this is not the case, the rest of the pattern match fails exactly
+as before because nothing has changed, so using a non-atomic assertion just
+wastes resources.
+
+
+There is one exception to backtracking into a non-atomic assertion. If an
+(*ACCEPT) control verb is triggered, the assertion succeeds atomically. That
+is, a subsequent match failure cannot backtrack into the assertion.
+
+
+Non-atomic assertions are not supported by the alternative matching function
+pcre2_dfa_match(). They are supported by JIT, but only if they do not
+contain any control verbs such as (*ACCEPT). (This may change in future). Note
+that assertions that appear as conditions for
+conditional groups
+(see below) must be atomic.
+
+
+
+A special kind of assertion, not compatible with Perl, makes it possible to
+check the contents of a captured substring by matching it with a subpattern.
+Because this involves capturing, this feature is not supported by
+pcre2_dfa_match().
+
+
+A scan substring assertion starts with the sequence (*scan_substring: or
+(*scs: which is followed by a list of substring numbers (absolute or relative)
+and/or substring names enclosed in single quotes or angle brackets, all within
+parentheses. The rest of the item is the subpattern that is applied to the
+substring, as shown in these examples:
+
+ (*scan_substring:(1)...)
+ (*scs:(-2)...)
+ (*scs:('AB')...)
+ (*scs:(1,'AB',-2)...)
+
+The list of groups is checked in the order they are given, and it is the
+contents of the first one that is found to be set that are scanned. When
+PCRE2_DUPNAMES is set and there are ambiguous group names, all groups with the
+same name are checked in numerical order. A scan substring assertion fails if
+none of the groups it references have been set.
+
+
+The pattern match on the substring is always anchored, that is, it must match
+from the start of the substring. There is no "bumpalong" if it does not match
+at the start. The end of the subject is temporarily reset to be the end of the
+substring, so \Z, \z, and $ will match there. However, the start of the
+subject is not reset. This means that ^ matches only if the substring is
+actually at the start of the main subject, but it also means that lookbehind
+assertions into what precedes the substring are possible.
+
+
+Here is a very simple example: find a word that contains the rare (in English)
+sequence of letters "rh" not at the start:
+
+ \b(\w++)(*scs:(1).+rh)
+
+The first group captures a word which is then scanned by the second group.
+This example does not actually need this heavyweight feature; the same match
+can be achieved with:
+
+ \b\w+?rh\w*\b
+
+When things are more complicated, however, scanning a captured substring can be
+a useful way to describe the required match. For exmple, there is a rather
+complicated pattern in the PCRE2 test data that checks an entire subject string
+for a palindrome, that is, the sequence of letters is the same in both
+directions. Suppose you want to search for individual words of two or more
+characters such as "level" that are palindromes:
+
+ (\b\w{2,}+\b)(*scs:(1)...palindrome-matching-pattern...)
+
+Within a substring scanning subpattern, references to other groups work as
+normal. Capturing groups may appear, and will retain their values during
+ongoing matching if the assertion succeeds.
+
+
+
+In concept, a script run is a sequence of characters that are all from the same
+Unicode script such as Latin or Greek. However, because some scripts are
+commonly used together, and because some diacritical and other marks are used
+with multiple scripts, it is not that simple. There is a full description of
+the rules that PCRE2 uses in the section entitled
+"Script Runs"
+in the
+pcre2unicode
+documentation.
+
+
+If part of a pattern is enclosed between (*script_run: or (*sr: and a closing
+parenthesis, it fails if the sequence of characters that it matches are not a
+script run. After a failure, normal backtracking occurs. Script runs can be
+used to detect spoofing attacks using characters that look the same, but are
+from different scripts. The string "paypal.com" is an infamous example, where
+the letters could be a mixture of Latin and Cyrillic. This pattern ensures that
+the matched characters in a sequence of non-spaces that follow white space are
+a script run:
+
+ \s+(*sr:\S+)
+
+To be sure that they are all from the Latin script (for example), a lookahead
+can be used:
+
+ \s+(?=\p{Latin})(*sr:\S+)
+
+This works as long as the first character is expected to be a character in that
+script, and not (for example) punctuation, which is allowed with any script. If
+this is not the case, a more creative lookahead is needed. For example, if
+digits, underscore, and dots are permitted at the start:
+
+ \s+(?=[0-9_.]*\p{Latin})(*sr:\S+)
+
+
+
+
+In many cases, backtracking into a script run pattern fragment is not
+desirable. The script run can employ an atomic group to prevent this. Because
+this is a common requirement, a shorthand notation is provided by
+(*atomic_script_run: or (*asr:
+
+ (*asr:...) is the same as (*sr:(?>...))
+
+Note that the atomic group is inside the script run. Putting it outside would
+not prevent backtracking into the script run pattern.
+
+
+Support for script runs is not available if PCRE2 is compiled without Unicode
+support. A compile-time error is given if any of the above constructs is
+encountered. Script runs are not supported by the alternate matching function,
+pcre2_dfa_match() because they use the same mechanism as capturing
+parentheses.
+
+
+Warning: The (*ACCEPT) control verb
+(see below)
+should not be used within a script run group, because it causes an immediate
+exit from the group, bypassing the script run checking.
+
+
+
+It is possible to cause the matching process to obey a pattern fragment
+conditionally or to choose between two alternative fragments, depending on
+the result of an assertion, or whether a specific capture group has
+already been matched. The two possible forms of conditional group are:
+
+ (?(condition)yes-pattern)
+ (?(condition)yes-pattern|no-pattern)
+
+If the condition is satisfied, the yes-pattern is used; otherwise the
+no-pattern (if present) is used. An absent no-pattern is equivalent to an empty
+string (it always matches). If there are more than two alternatives in the
+group, a compile-time error occurs. Each of the two alternatives may itself
+contain nested groups of any form, including conditional groups; the
+restriction to two alternatives applies only at the level of the condition
+itself. This pattern fragment is an example where the alternatives are complex:
+
+ (?(1) (A|B|C) | (D | (?(2)E|F) | E) )
+
+
+
+
+There are five kinds of condition: references to capture groups, references to
+recursion, two pseudo-conditions called DEFINE and VERSION, and assertions.
+
+
+Checking for a used capture group by number
+
+
+If the text between the parentheses consists of a sequence of digits, the
+condition is true if a capture group of that number has previously matched. If
+there is more than one capture group with the same number (see the earlier
+section about duplicate group numbers),
+the condition is true if any of them have matched. An alternative notation,
+which is a PCRE2 extension, not supported by Perl, is to precede the digits
+with a plus or minus sign. In this case, the group number is relative rather
+than absolute. The most recently opened capture group (which could be enclosing
+this condition) can be referenced by (?(-1), the next most recent by (?(-2),
+and so on. Inside loops it can also make sense to refer to subsequent groups.
+The next capture group to be opened can be referenced as (?(+1), and so on. The
+value zero in any of these forms is not used; it provokes a compile-time error.
+
+
+Consider the following pattern, which contains non-significant white space to
+make it more readable (assume the PCRE2_EXTENDED option) and to divide it into
+three parts for ease of discussion:
+
+ ( \( )? [^()]+ (?(1) \) )
+
+The first part matches an optional opening parenthesis, and if that
+character is present, sets it as the first captured substring. The second part
+matches one or more characters that are not parentheses. The third part is a
+conditional group that tests whether or not the first capture group
+matched. If it did, that is, if subject started with an opening parenthesis,
+the condition is true, and so the yes-pattern is executed and a closing
+parenthesis is required. Otherwise, since no-pattern is not present, the
+conditional group matches nothing. In other words, this pattern matches a
+sequence of non-parentheses, optionally enclosed in parentheses.
+
+
+If you were embedding this pattern in a larger one, you could use a relative
+reference:
+
+ ...other stuff... ( \( )? [^()]+ (?(-1) \) ) ...
+
+This makes the fragment independent of the parentheses in the larger pattern.
+
+
+Checking for a used capture group by name
+
+
+Perl uses the syntax (?(<name>)...) or (?('name')...) to test for a used
+capture group by name. For compatibility with earlier versions of PCRE1, which
+had this facility before Perl, the syntax (?(name)...) is also recognized.
+Note, however, that undelimited names consisting of the letter R followed by
+digits are ambiguous (see the following section). Rewriting the above example
+to use a named group gives this:
+
+ (?<OPEN> \( )? [^()]+ (?(<OPEN>) \) )
+
+If the name used in a condition of this kind is a duplicate, the test is
+applied to all groups of the same name, and is true if any one of them has
+matched.
+
+
+Checking for pattern recursion
+
+
+"Recursion" in this sense refers to any subroutine-like call from one part of
+the pattern to another, whether or not it is actually recursive. See the
+sections entitled
+"Recursive patterns"
+and
+"Groups as subroutines"
+below for details of recursion and subroutine calls.
+
+
+If a condition is the string (R), and there is no capture group with the name
+R, the condition is true if matching is currently in a recursion or subroutine
+call to the whole pattern or any capture group. If digits follow the letter R,
+and there is no group with that name, the condition is true if the most recent
+call is into a group with the given number, which must exist somewhere in the
+overall pattern. This is a contrived example that is equivalent to a+b:
+
+ ((?(R1)a+|(?1)b))
+
+However, in both cases, if there is a capture group with a matching name, the
+condition tests for its being set, as described in the section above, instead
+of testing for recursion. For example, creating a group with the name R1 by
+adding (?<R1>) to the above pattern completely changes its meaning.
+
+
+If a name preceded by ampersand follows the letter R, for example:
+
+ (?(R&name)...)
+
+the condition is true if the most recent recursion is into a group of that name
+(which must exist within the pattern).
+
+
+This condition does not check the entire recursion stack. It tests only the
+current level. If the name used in a condition of this kind is a duplicate, the
+test is applied to all groups of the same name, and is true if any one of
+them is the most recent recursion.
+
+
+At "top level", all these recursion test conditions are false.
+
+
+Defining capture groups for use by reference only
+
+
+If the condition is the string (DEFINE), the condition is always false, even if
+there is a group with the name DEFINE. In this case, there may be only one
+alternative in the rest of the conditional group. It is always skipped if
+control reaches this point in the pattern; the idea of DEFINE is that it can be
+used to define subroutines that can be referenced from elsewhere. (The use of
+subroutines
+is described below.) For example, a pattern to match an IPv4 address such as
+"192.168.23.245" could be written like this (ignore white space and line
+breaks):
+
+ (?(DEFINE) (?<byte> 2[0-4]\d | 25[0-5] | 1\d\d | [1-9]?\d) )
+ \b (?&byte) (\.(?&byte)){3} \b
+
+The first part of the pattern is a DEFINE group inside which another group
+named "byte" is defined. This matches an individual component of an IPv4
+address (a number less than 256). When matching takes place, this part of the
+pattern is skipped because DEFINE acts like a false condition. The rest of the
+pattern uses references to the named group to match the four dot-separated
+components of an IPv4 address, insisting on a word boundary at each end.
+
+
+Checking the PCRE2 version
+
+
+Programs that link with a PCRE2 library can check the version by calling
+pcre2_config() with appropriate arguments. Users of applications that do
+not have access to the underlying code cannot do this. A special "condition"
+called VERSION exists to allow such users to discover which version of PCRE2
+they are dealing with by using this condition to match a string such as
+"yesno". VERSION must be followed either by "=" or ">=" and a version number.
+For example:
+
+ (?(VERSION>=10.4)yes|no)
+
+This pattern matches "yes" if the PCRE2 version is greater or equal to 10.4, or
+"no" otherwise. The fractional part of the version number could be ommited.
+
+
+Assertion conditions
+
+
+If the condition is not in any of the above formats, it must be a parenthesized
+assertion. This may be a positive or negative lookahead or lookbehind
+assertion. However, it must be a traditional atomic assertion, not one of the
+non-atomic assertions.
+
+
+Consider this pattern, again containing non-significant white space, and with
+the two alternatives on the second line:
+
+ (?(?=[^a-z]*[a-z])
+ \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} )
+
+The condition is a positive lookahead assertion that matches an optional
+sequence of non-letters followed by a letter. In other words, it tests for the
+presence of at least one letter in the subject. If a letter is found, the
+subject is matched against the first alternative; otherwise it is matched
+against the second. This pattern matches strings in one of the two forms
+dd-aaa-dd or dd-dd-dd, where aaa are letters and dd are digits.
+
+
+When an assertion that is a condition contains capture groups, any
+capturing that occurs in a matching branch is retained afterwards, for both
+positive and negative assertions, because matching always continues after the
+assertion, whether it succeeds or fails. (Compare non-conditional assertions,
+for which captures are retained only for positive assertions that succeed.)
+
+
+
+There are two ways of including comments in patterns that are processed by
+PCRE2. In both cases, the start of the comment must not be in a character
+class, nor in the middle of any other sequence of related characters such as
+(?: or a group name or number or a Unicode property name. The characters that
+make up a comment play no part in the pattern matching.
+
+
+The sequence (?# marks the start of a comment that continues up to the next
+closing parenthesis. Nested parentheses are not permitted. If the
+PCRE2_EXTENDED or PCRE2_EXTENDED_MORE option is set, an unescaped # character
+also introduces a comment, which in this case continues to immediately after
+the next newline character or character sequence in the pattern. Which
+characters are interpreted as newlines is controlled by an option passed to the
+compiling function or by a special sequence at the start of the pattern, as
+described in the section entitled
+"Newline conventions"
+above. Note that the end of this type of comment is a literal newline sequence
+in the pattern; escape sequences that happen to represent a newline do not
+count. For example, consider this pattern when PCRE2_EXTENDED is set, and the
+default newline convention (a single linefeed character) is in force:
+
+ abc #comment \n still comment
+
+On encountering the # character, pcre2_compile() skips along, looking for
+a newline in the pattern. The sequence \n is still literal at this stage, so
+it does not terminate the comment. Only an actual character with the code value
+0x0a (the default newline) does so.
+
+
+
+Consider the problem of matching a string in parentheses, allowing for
+unlimited nested parentheses. Without the use of recursion, the best that can
+be done is to use a pattern that matches up to some fixed depth of nesting. It
+is not possible to handle an arbitrary nesting depth.
+
+
+For some time, Perl has provided a facility that allows regular expressions to
+recurse (amongst other things). It does this by interpolating Perl code in the
+expression at run time, and the code can refer to the expression itself. A Perl
+pattern using code interpolation to solve the parentheses problem can be
+created like this:
+
+ $re = qr{\( (?: (?>[^()]+) | (?p{$re}) )* \)}x;
+
+The (?p{...}) item interpolates Perl code at run time, and in this case refers
+recursively to the pattern in which it appears.
+
+
+Obviously, PCRE2 cannot support the interpolation of Perl code. Instead, it
+supports special syntax for recursion of the entire pattern, and also for
+individual capture group recursion. After its introduction in PCRE1 and Python,
+this kind of recursion was subsequently introduced into Perl at release 5.10.
+
+
+A special item that consists of (? followed by a number greater than zero and a
+closing parenthesis is a recursive subroutine call of the capture group of the
+given number, provided that it occurs inside that group. (If not, it is a
+non-recursive subroutine
+call, which is described in the next section.) The special item (?R) or (?0) is
+a recursive call of the entire regular expression.
+
+
+This PCRE2 pattern solves the nested parentheses problem (assume the
+PCRE2_EXTENDED option is set so that white space is ignored):
+
+ \( ( [^()]++ | (?R) )* \)
+
+First it matches an opening parenthesis. Then it matches any number of
+substrings which can either be a sequence of non-parentheses, or a recursive
+match of the pattern itself (that is, a correctly parenthesized substring).
+Finally there is a closing parenthesis. Note the use of a possessive quantifier
+to avoid backtracking into sequences of non-parentheses.
+
+
+If this were part of a larger pattern, you would not want to recurse the entire
+pattern, so instead you could use this:
+
+ ( \( ( [^()]++ | (?1) )* \) )
+
+We have put the pattern into parentheses, and caused the recursion to refer to
+them instead of the whole pattern.
+
+
+In a larger pattern, keeping track of parenthesis numbers can be tricky. This
+is made easier by the use of relative references. Instead of (?1) in the
+pattern above you can write (?-2) to refer to the second most recently opened
+parentheses preceding the recursion. In other words, a negative number counts
+capturing parentheses leftwards from the point at which it is encountered.
+
+
+Be aware however, that if
+duplicate capture group numbers
+are in use, relative references refer to the earliest group with the
+appropriate number. Consider, for example:
+
+ (?|(a)|(b)) (c) (?-2)
+
+The first two capture groups (a) and (b) are both numbered 1, and group (c)
+is number 2. When the reference (?-2) is encountered, the second most recently
+opened parentheses has the number 1, but it is the first such group (the (a)
+group) to which the recursion refers. This would be the same if an absolute
+reference (?1) was used. In other words, relative references are just a
+shorthand for computing a group number.
+
+
+It is also possible to refer to subsequent capture groups, by writing
+references such as (?+2). However, these cannot be recursive because the
+reference is not inside the parentheses that are referenced. They are always
+non-recursive subroutine
+calls, as described in the next section.
+
+
+An alternative approach is to use named parentheses. The Perl syntax for this
+is (?&name); PCRE1's earlier syntax (?P>name) is also supported. We could
+rewrite the above example as follows:
+
+ (?<pn> \( ( [^()]++ | (?&pn) )* \) )
+
+If there is more than one group with the same name, the earliest one is
+used.
+
+
+The example pattern that we have been looking at contains nested unlimited
+repeats, and so the use of a possessive quantifier for matching strings of
+non-parentheses is important when applying the pattern to strings that do not
+match. For example, when this pattern is applied to
+
+ (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
+
+it yields "no match" quickly. However, if a possessive quantifier is not used,
+the match runs for a very long time indeed because there are so many different
+ways the + and * repeats can carve up the subject, and all have to be tested
+before failure can be reported.
+
+
+At the end of a match, the values of capturing parentheses are those from
+the outermost level. If you want to obtain intermediate values, a callout
+function can be used (see below and the
+pcre2callout
+documentation). If the pattern above is matched against
+
+ (ab(cd)ef)
+
+the value for the inner capturing parentheses (numbered 2) is "ef", which is
+the last value taken on at the top level. If a capture group is not matched at
+the top level, its final captured value is unset, even if it was (temporarily)
+set at a deeper level during the matching process.
+
+
+Do not confuse the (?R) item with the condition (R), which tests for recursion.
+Consider this pattern, which matches text in angle brackets, allowing for
+arbitrary nesting. Only digits are allowed in nested brackets (that is, when
+recursing), whereas any characters are permitted at the outer level.
+
+ < (?: (?(R) \d++ | [^<>]*+) | (?R)) * >
+
+In this pattern, (?(R) is the start of a conditional group, with two different
+alternatives for the recursive and non-recursive cases. The (?R) item is the
+actual recursive call.
+
+
+Differences in recursion processing between PCRE2 and Perl
+
+
+Some former differences between PCRE2 and Perl no longer exist.
+
+
+Before release 10.30, recursion processing in PCRE2 differed from Perl in that
+a recursive subroutine call was always treated as an atomic group. That is,
+once it had matched some of the subject string, it was never re-entered, even
+if it contained untried alternatives and there was a subsequent matching
+failure. (Historical note: PCRE implemented recursion before Perl did.)
+
+
+Starting with release 10.30, recursive subroutine calls are no longer treated
+as atomic. That is, they can be re-entered to try unused alternatives if there
+is a matching failure later in the pattern. This is now compatible with the way
+Perl works. If you want a subroutine call to be atomic, you must explicitly
+enclose it in an atomic group.
+
+
+Supporting backtracking into recursions simplifies certain types of recursive
+pattern. For example, this pattern matches palindromic strings:
+
+ ^((.)(?1)\2|.?)$
+
+The second branch in the group matches a single central character in the
+palindrome when there are an odd number of characters, or nothing when there
+are an even number of characters, but in order to work it has to be able to try
+the second case when the rest of the pattern match fails. If you want to match
+typical palindromic phrases, the pattern has to ignore all non-word characters,
+which can be done like this:
+
+ ^\W*+((.)\W*+(?1)\W*+\2|\W*+.?)\W*+$
+
+If run with the PCRE2_CASELESS option, this pattern matches phrases such as "A
+man, a plan, a canal: Panama!". Note the use of the possessive quantifier *+ to
+avoid backtracking into sequences of non-word characters. Without this, PCRE2
+takes a great deal longer (ten times or more) to match typical phrases, and
+Perl takes so long that you think it has gone into a loop.
+
+
+Another way in which PCRE2 and Perl used to differ in their recursion
+processing is in the handling of captured values. Formerly in Perl, when a
+group was called recursively or as a subroutine (see the next section), it
+had no access to any values that were captured outside the recursion, whereas
+in PCRE2 these values can be referenced. Consider this pattern:
+
+ ^(.)(\1|a(?2))
+
+This pattern matches "bab". The first capturing parentheses match "b", then in
+the second group, when the backreference \1 fails to match "b", the second
+alternative matches "a" and then recurses. In the recursion, \1 does now match
+"b" and so the whole match succeeds. This match used to fail in Perl, but in
+later versions (I tried 5.024) it now works.
+
+
+Groups as subroutines
+
+
+If the syntax for a recursive group call (either by number or by name) is used
+outside the parentheses to which it refers, it operates a bit like a subroutine
+in a programming language. More accurately, PCRE2 treats the referenced group
+as an independent subpattern which it tries to match at the current matching
+position. The called group may be defined before or after the reference. A
+numbered reference can be absolute or relative, as in these examples:
+
+ (...(absolute)...)...(?2)...
+ (...(relative)...)...(?-1)...
+ (...(?+1)...(relative)...
+
+An earlier example pointed out that the pattern
+
+ (sens|respons)e and \1ibility
+
+matches "sense and sensibility" and "response and responsibility", but not
+"sense and responsibility". If instead the pattern
+
+ (sens|respons)e and (?1)ibility
+
+is used, it does match "sense and responsibility" as well as the other two
+strings. Another example is given in the discussion of DEFINE above.
+
+
+Like recursions, subroutine calls used to be treated as atomic, but this
+changed at PCRE2 release 10.30, so backtracking into subroutine calls can now
+occur. However, any capturing parentheses that are set during the subroutine
+call revert to their previous values afterwards.
+
+
+Processing options such as case-independence are fixed when a group is
+defined, so if it is used as a subroutine, such options cannot be changed for
+different calls. For example, consider this pattern:
+
+ (abc)(?i:(?-1))
+
+It matches "abcabc". It does not match "abcABC" because the change of
+processing option does not affect the called group.
+
+
+The behaviour of
+backtracking control verbs
+in groups when called as subroutines is described in the section entitled
+"Backtracking verbs in subroutines"
+below.
+
+
+Recursion and subroutines with returned capture groups
+
+
+Since PCRE2 10.47, recursion and subroutine calls may also specify a list of
+capture groups to return. This is a PCRE2 syntax extension not supported by
+Perl. The pattern matching recurses into the referenced expression as described
+above, however, when the recursion returns to the calling expression the
+subgroups captured during the recursion can be retained when the calling
+expression's context is restored.
+
+
+When used as a subroutine, this allows the subroutine's capture groups to
+be used as return values.
+
+
+Only the specific capture groups listed by the caller will be retained, using
+the following syntax:
+
+ (?R(grouplist)) recurse whole pattern, returning capture groups
+ (?n(grouplist)) )
+ (?+n(grouplist)) )
+ (?-n(grouplist)) ) call subroutine, returning capture groups
+ (?&name(grouplist)) )
+ (?P>name(grouplist)) )
+
+
+
+The list of capture groups "grouplist" is a comma-separated list of (absolute
+or relative) group numbers, and group names enclosed in single quotes or angle
+brackets.
+
+
+Here is an example which first uses the DEFINE condition to create a re-usable
+routine for matching a weekday, then calls that subroutine and retains the
+groups it captures for use later:
+
+ (?x: # ignore whitespace for clarity
+ # Define the routine "weekendday" which matches Saturday or
+ # Sunday, and returns the Sat/Sun prefix as \k<short>.
+ (?(DEFINE) (?<weekendday>
+ (?|(?<short>Sat)urday|(?<short>Sun)day) ) )
+ # Call the routine. Matches "Saturday,Sat" or "Sunday,Sun".
+ (?&weekendday(<short>)),\k<short> )
+
+
+
+This feature is not available using the Oniguruma syntax \g<...> or \g'...'
+below.
+
+
+Oniguruma subroutine syntax
+
+
+For compatibility with Oniguruma, the non-Perl syntax \g followed by a name or
+a number enclosed either in angle brackets or single quotes, is an alternative
+syntax for calling a group as a subroutine, possibly recursively. Here are two
+of the examples used above, rewritten using this syntax:
+
+ (?<pn> \( ( (?>[^()]+) | \g<pn> )* \) )
+ (sens|respons)e and \g'1'ibility
+
+PCRE2 supports an extension to Oniguruma: if a number is preceded by a
+plus or a minus sign it is taken as a relative reference. For example:
+
+ (abc)(?i:\g<-1>)
+
+Note that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are not
+synonymous. The former is a backreference; the latter is a subroutine call.
+
+
+
+Perl has a feature whereby using the sequence (?{...}) causes arbitrary Perl
+code to be obeyed in the middle of matching a regular expression. This makes it
+possible, amongst other things, to extract different substrings that match the
+same pair of parentheses when there is a repetition.
+
+
+PCRE2 provides a similar feature, but of course it cannot obey arbitrary Perl
+code. The feature is called "callout". The caller of PCRE2 provides an external
+function by putting its entry point in a match context using the function
+pcre2_set_callout(), and then passing that context to pcre2_match()
+or pcre2_dfa_match(). If no match context is passed, or if the callout
+entry point is set to NULL, callout points will be passed over silently during
+matching. To disallow callouts in the pattern syntax, you may use the
+PCRE2_EXTRA_NEVER_CALLOUT option.
+
+
+Within a regular expression, (?C<arg>) indicates a point at which the external
+function is to be called. There are two kinds of callout: those with a
+numerical argument and those with a string argument. (?C) on its own with no
+argument is treated as (?C0). A numerical argument allows the application to
+distinguish between different callouts. String arguments were added for release
+10.20 to make it possible for script languages that use PCRE2 to embed short
+scripts within patterns in a similar way to Perl.
+
+
+During matching, when PCRE2 reaches a callout point, the external function is
+called. It is provided with the number or string argument of the callout, the
+position in the pattern, and one item of data that is also set in the match
+block. The callout function may cause matching to proceed, to backtrack, or to
+fail.
+
+
+By default, PCRE2 implements a number of optimizations at matching time, and
+one side-effect is that sometimes callouts are skipped. If you need all
+possible callouts to happen, you need to set options that disable the relevant
+optimizations. More details, including a complete description of the
+programming interface to the callout function, are given in the
+pcre2callout
+documentation.
+
+
+Callouts with numerical arguments
+
+
+If you just want to have a means of identifying different callout points, put a
+number less than 256 after the letter C. For example, this pattern has two
+callout points:
+
+ (?C1)abc(?C2)def
+
+If the PCRE2_AUTO_CALLOUT flag is passed to pcre2_compile(), numerical
+callouts are automatically installed before each item in the pattern. They are
+all numbered 255. If there is a conditional group in the pattern whose
+condition is an assertion, an additional callout is inserted just before the
+condition. An explicit callout may also be set at this position, as in this
+example:
+
+ (?(?C9)(?=a)abc|def)
+
+Note that this applies only to assertion conditions, not to other types of
+condition.
+
+
+Callouts with string arguments
+
+
+A delimited string may be used instead of a number as a callout argument. The
+starting delimiter must be one of ` ' " ^ % # $ { and the ending delimiter is
+the same as the start, except for {, where the ending delimiter is }. If the
+ending delimiter is needed within the string, it must be doubled. For
+example:
+
+ (?C'ab ''c'' d')xyz(?C{any text})pqr
+
+The doubling is removed before the string is passed to the callout function.
+
+
+
+There are a number of special "Backtracking Control Verbs" (to use Perl's
+terminology) that modify the behaviour of backtracking during matching. They
+are generally of the form (*VERB) or (*VERB:NAME). Some verbs take either form,
+and may behave differently depending on whether or not a name argument is
+present. The names are not required to be unique within the pattern.
+
+
+By default, for compatibility with Perl, a name is any sequence of characters
+that does not include a closing parenthesis. The name is not processed in
+any way, and it is not possible to include a closing parenthesis in the name.
+This can be changed by setting the PCRE2_ALT_VERBNAMES option, but the result
+is no longer Perl-compatible.
+
+
+When PCRE2_ALT_VERBNAMES is set, backslash processing is applied to verb names
+and only an unescaped closing parenthesis terminates the name. However, the
+only backslash items that are permitted are \Q, \E, and sequences such as
+\x{100} that define character code points. Character type escapes such as \d
+are faulted.
+
+
+A closing parenthesis can be included in a name either as \) or between \Q
+and \E. In addition to backslash processing, if the PCRE2_EXTENDED or
+PCRE2_EXTENDED_MORE option is also set, unescaped white space in verb names is
+skipped, and #-comments are recognized, exactly as in the rest of the pattern.
+PCRE2_EXTENDED and PCRE2_EXTENDED_MORE do not affect verb names unless
+PCRE2_ALT_VERBNAMES is also set.
+
+
+The maximum length of a name is 255 in the 8-bit library and 65535 in the
+16-bit and 32-bit libraries. If the name is empty, that is, if the closing
+parenthesis immediately follows the colon, the effect is as if the colon were
+not there. Any number of these verbs may occur in a pattern. Except for
+(*ACCEPT), they may not be quantified.
+
+
+Since these verbs are specifically related to backtracking, most of them can be
+used only when the pattern is to be matched using the traditional matching
+function or JIT, because they use backtracking algorithms. With the exception
+of (*FAIL), which behaves like a failing negative assertion, the backtracking
+control verbs cause an error if encountered by the DFA matching function.
+
+
+The behaviour of these verbs in
+repeated groups,
+assertions,
+and in
+capture groups called as subroutines
+(whether or not recursively) is documented below.
+
+
+Optimizations that affect backtracking verbs
+
+
+PCRE2 contains some optimizations that are used to speed up matching by running
+some checks at the start of each match attempt. For example, it may know the
+minimum length of matching subject, or that a particular character must be
+present. When one of these optimizations bypasses the running of a match, any
+included backtracking verbs will not, of course, be processed. You can suppress
+the start-of-match optimizations by setting the PCRE2_NO_START_OPTIMIZE option
+when calling pcre2_compile(), by calling pcre2_set_optimize() with a
+PCRE2_START_OPTIMIZE_OFF directive, or by starting the pattern with
+(*NO_START_OPT). There is more discussion of this option in the section
+entitled
+"Compiling a pattern"
+in the
+pcre2api
+documentation.
+
+
+Experiments with Perl suggest that it too has similar optimizations, and like
+PCRE2, turning them off can change the result of a match.
+
+
+Verbs that act immediately
+
+
+The following verbs act as soon as they are encountered.
+
+ (*ACCEPT) or (*ACCEPT:NAME)
+
+This verb causes the match to end successfully, skipping the remainder of the
+pattern. However, when it is inside a capture group that is called as a
+subroutine, only that group is ended successfully. Matching then continues
+at the outer level. If (*ACCEPT) in triggered in a positive assertion, the
+assertion succeeds; in a negative assertion, the assertion fails.
+
+
+If (*ACCEPT) is inside capturing parentheses, the data so far is captured. For
+example:
+
+ A((?:A|B(*ACCEPT)|C)D)
+
+This matches "AB", "AAD", or "ACD"; when it matches "AB", "B" is captured by
+the outer parentheses.
+
+
+(*ACCEPT) is the only backtracking verb that is allowed to be quantified
+because an ungreedy quantification with a minimum of zero acts only when a
+backtrack happens. Consider, for example,
+
+ (A(*ACCEPT)??B)C
+
+where A, B, and C may be complex expressions. After matching "A", the matcher
+processes "BC"; if that fails, causing a backtrack, (*ACCEPT) is triggered and
+the match succeeds. In both cases, all but C is captured. Whereas (*COMMIT)
+(see below) means "fail on backtrack", a repeated (*ACCEPT) of this type means
+"succeed on backtrack".
+
+
+Warning: (*ACCEPT) should not be used within a script run group, because
+it causes an immediate exit from the group, bypassing the script run checking.
+
+ (*FAIL) or (*FAIL:NAME)
+
+This verb causes a matching failure, forcing backtracking to occur. It may be
+abbreviated to (*F). It is equivalent to (?!) but easier to read. The Perl
+documentation notes that it is probably useful only when combined with (?{}) or
+(??{}). Those are, of course, Perl features that are not present in PCRE2. The
+nearest equivalent is the callout feature, as for example in this pattern:
+
+ a+(?C)(*FAIL)
+
+A match with the string "aaaa" always fails, but the callout is taken before
+each backtrack happens (in this example, 10 times).
+
+
+(*ACCEPT:NAME) and (*FAIL:NAME) behave the same as (*MARK:NAME)(*ACCEPT) and
+(*MARK:NAME)(*FAIL), respectively, that is, a (*MARK) is recorded just before
+the verb acts.
+
+
+Recording which path was taken
+
+
+There is one verb whose main purpose is to track how a match was arrived at,
+though it also has a secondary use in conjunction with advancing the match
+starting point (see (*SKIP) below).
+
+ (*MARK:NAME) or (*:NAME)
+
+A name is always required with this verb. For all the other backtracking
+control verbs, a NAME argument is optional.
+
+
+When a match succeeds, the name of the last-encountered mark name on the
+matching path is passed back to the caller as described in the section entitled
+"Other information about the match"
+in the
+pcre2api
+documentation. This applies to all instances of (*MARK) and other verbs,
+including those inside assertions and atomic groups. However, there are
+differences in those cases when (*MARK) is used in conjunction with (*SKIP) as
+described below.
+
+
+The mark name that was last encountered on the matching path is passed back. A
+verb without a NAME argument is ignored for this purpose. Here is an example of
+pcre2test output, where the "mark" modifier requests the retrieval and
+outputting of (*MARK) data:
+
+ re> /X(*MARK:A)Y|X(*MARK:B)Z/mark
+ data> XY
+ 0: XY
+ MK: A
+ XZ
+ 0: XZ
+ MK: B
+
+The (*MARK) name is tagged with "MK:" in this output, and in this example it
+indicates which of the two alternatives matched. This is a more efficient way
+of obtaining this information than putting each alternative in its own
+capturing parentheses.
+
+
+If a verb with a name is encountered in a positive assertion that is true, the
+name is recorded and passed back if it is the last-encountered. This does not
+happen for negative assertions or failing positive assertions.
+
+
+After a partial match or a failed match, the last encountered name in the
+entire match process is returned. For example:
+
+ re> /X(*MARK:A)Y|X(*MARK:B)Z/mark
+ data> XP
+ No match, mark = B
+
+Note that in this unanchored example the mark is retained from the match
+attempt that started at the letter "X" in the subject. Subsequent match
+attempts starting at "P" and then with an empty string do not get as far as the
+(*MARK) item, but nevertheless do not reset it.
+
+
+If you are interested in (*MARK) values after failed matches, you should
+probably either set the PCRE2_NO_START_OPTIMIZE option or call
+pcre2_set_optimize() with a PCRE2_START_OPTIMIZE_OFF directive
+(see above)
+to ensure that the match is always attempted.
+
+
+Verbs that act after backtracking
+
+
+The following verbs do nothing when they are encountered. Matching continues
+with what follows, but if there is a subsequent match failure, causing a
+backtrack to the verb, a failure is forced. That is, backtracking cannot pass
+to the left of the verb. However, when one of these verbs appears inside an
+atomic group or in an atomic lookaround assertion that is true, its effect is
+confined to that group, because once the group has been matched, there is never
+any backtracking into it. Backtracking from beyond an atomic assertion or group
+ignores the entire group, and seeks a preceding backtracking point.
+
+
+These verbs differ in exactly what kind of failure occurs when backtracking
+reaches them. The behaviour described below is what happens when the verb is
+not in a subroutine or an assertion. Subsequent sections cover these special
+cases.
+
+ (*COMMIT) or (*COMMIT:NAME)
+
+This verb causes the whole match to fail outright if there is a later matching
+failure that causes backtracking to reach it. Even if the pattern is
+unanchored, no further attempts to find a match by advancing the starting point
+take place. If (*COMMIT) is the only backtracking verb that is encountered,
+once it has been passed pcre2_match() is committed to finding a match at
+the current starting point, or not at all. For example:
+
+ a+(*COMMIT)b
+
+This matches "xxaab" but not "aacaab". It can be thought of as a kind of
+dynamic anchor, or "I've started, so I must finish."
+
+
+The behaviour of (*COMMIT:NAME) is not the same as (*MARK:NAME)(*COMMIT). It is
+like (*MARK:NAME) in that the name is remembered for passing back to the
+caller. However, (*SKIP:NAME) searches only for names that are set with
+(*MARK), ignoring those set by any of the other backtracking verbs.
+
+
+If there is more than one backtracking verb in a pattern, a different one that
+follows (*COMMIT) may be triggered first, so merely passing (*COMMIT) during a
+match does not always guarantee that a match must be at this starting point.
+
+
+Note that (*COMMIT) at the start of a pattern is not the same as an anchor,
+unless PCRE2's start-of-match optimizations are turned off, as shown in this
+output from pcre2test:
+
+ re> /(*COMMIT)abc/
+ data> xyzabc
+ 0: abc
+ data>
+ re> /(*COMMIT)abc/no_start_optimize
+ data> xyzabc
+ No match
+
+For the first pattern, PCRE2 knows that any match must start with "a", so the
+optimization skips along the subject to "a" before applying the pattern to the
+first set of data. The match attempt then succeeds. The second pattern disables
+the optimization that skips along to the first character. The pattern is now
+applied starting at "x", and so the (*COMMIT) causes the match to fail without
+trying any other starting points.
+
+ (*PRUNE) or (*PRUNE:NAME)
+
+This verb causes the match to fail at the current starting position in the
+subject if there is a later matching failure that causes backtracking to reach
+it. If the pattern is unanchored, the normal "bumpalong" advance to the next
+starting character then happens. Backtracking can occur as usual to the left of
+(*PRUNE), before it is reached, or when matching to the right of (*PRUNE), but
+if there is no match to the right, backtracking cannot cross (*PRUNE). In
+simple cases, the use of (*PRUNE) is just an alternative to an atomic group or
+possessive quantifier, but there are some uses of (*PRUNE) that cannot be
+expressed in any other way. In an anchored pattern (*PRUNE) has the same effect
+as (*COMMIT).
+
+
+The behaviour of (*PRUNE:NAME) is not the same as (*MARK:NAME)(*PRUNE). It is
+like (*MARK:NAME) in that the name is remembered for passing back to the
+caller. However, (*SKIP:NAME) searches only for names set with (*MARK),
+ignoring those set by other backtracking verbs.
+
+ (*SKIP)
+
+This verb, when given without a name, is like (*PRUNE), except that if the
+pattern is unanchored, the "bumpalong" advance is not to the next character,
+but to the position in the subject where (*SKIP) was encountered. (*SKIP)
+signifies that whatever text was matched leading up to it cannot be part of a
+successful match if there is a later mismatch. Consider:
+
+ a+(*SKIP)b
+
+If the subject is "aaaac...", after the first match attempt fails (starting at
+the first character in the string), the starting point skips on to start the
+next attempt at "c". Note that a possessive quantifier does not have the same
+effect as this example; although it would suppress backtracking during the
+first match attempt, the second attempt would start at the second character
+instead of skipping on to "c".
+
+
+If (*SKIP) is used to specify a new starting position that is the same as the
+starting position of the current match, or (by being inside a lookbehind)
+earlier, the position specified by (*SKIP) is ignored, and instead the normal
+"bumpalong" occurs.
+
+ (*SKIP:NAME)
+
+When (*SKIP) has an associated name, its behaviour is modified. When such a
+(*SKIP) is triggered, the previous path through the pattern is searched for the
+most recent (*MARK) that has the same name. If one is found, the "bumpalong"
+advance is to the subject position that corresponds to that (*MARK) instead of
+to where (*SKIP) was encountered. If no (*MARK) with a matching name is found,
+the (*SKIP) is ignored.
+
+
+The search for a (*MARK) name uses the normal backtracking mechanism, which
+means that it does not see (*MARK) settings that are inside atomic groups or
+assertions, because they are never re-entered by backtracking. Compare the
+following pcre2test examples:
+
+ re> /a(?>(*MARK:X))(*SKIP:X)(*F)|(.)/
+ data: abc
+ 0: a
+ 1: a
+ data:
+ re> /a(?:(*MARK:X))(*SKIP:X)(*F)|(.)/
+ data: abc
+ 0: b
+ 1: b
+
+In the first example, the (*MARK) setting is in an atomic group, so it is not
+seen when (*SKIP:X) triggers, causing the (*SKIP) to be ignored. This allows
+the second branch of the pattern to be tried at the first character position.
+In the second example, the (*MARK) setting is not in an atomic group. This
+allows (*SKIP:X) to find the (*MARK) when it backtracks, and this causes a new
+matching attempt to start at the second character. This time, the (*MARK) is
+never seen because "a" does not match "b", so the matcher immediately jumps to
+the second branch of the pattern.
+
+
+Note that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It ignores
+names that are set by other backtracking verbs.
+
+ (*THEN) or (*THEN:NAME)
+
+This verb causes a skip to the next innermost alternative when backtracking
+reaches it. That is, it cancels any further backtracking within the current
+alternative. Its name comes from the observation that it can be used for a
+pattern-based if-then-else block:
+
+ ( COND1 (*THEN) FOO | COND2 (*THEN) BAR | COND3 (*THEN) BAZ ) ...
+
+If the COND1 pattern matches, FOO is tried (and possibly further items after
+the end of the group if FOO succeeds); on failure, the matcher skips to the
+second alternative and tries COND2, without backtracking into COND1. If that
+succeeds and BAR fails, COND3 is tried. If subsequently BAZ fails, there are no
+more alternatives, so there is a backtrack to whatever came before the entire
+group. If (*THEN) is not inside an alternation, it acts like (*PRUNE).
+
+
+The behaviour of (*THEN:NAME) is not the same as (*MARK:NAME)(*THEN). It is
+like (*MARK:NAME) in that the name is remembered for passing back to the
+caller. However, (*SKIP:NAME) searches only for names set with (*MARK),
+ignoring those set by other backtracking verbs.
+
+
+A group that does not contain a | character is just a part of the enclosing
+alternative; it is not a nested alternation with only one alternative. The
+effect of (*THEN) extends beyond such a group to the enclosing alternative.
+Consider this pattern, where A, B, etc. are complex pattern fragments that do
+not contain any | characters at this level:
+
+ A (B(*THEN)C) | D
+
+If A and B are matched, but there is a failure in C, matching does not
+backtrack into A; instead it moves to the next alternative, that is, D.
+However, if the group containing (*THEN) is given an alternative, it
+behaves differently:
+
+ A (B(*THEN)C | (*FAIL)) | D
+
+The effect of (*THEN) is now confined to the inner group. After a failure in C,
+matching moves to (*FAIL), which causes the whole group to fail because there
+are no more alternatives to try. In this case, matching does backtrack into A.
+
+
+Note that a conditional group is not considered as having two alternatives,
+because only one is ever used. In other words, the | character in a conditional
+group has a different meaning. Ignoring white space, consider:
+
+ ^.*? (?(?=a) a | b(*THEN)c )
+
+If the subject is "ba", this pattern does not match. Because .*? is ungreedy,
+it initially matches zero characters. The condition (?=a) then fails, the
+character "b" is matched, but "c" is not. At this point, matching does not
+backtrack to .*? as might perhaps be expected from the presence of the |
+character. The conditional group is part of the single alternative that
+comprises the whole pattern, and so the match fails. (If there was a backtrack
+into .*?, allowing it to match "b", the match would succeed.)
+
+
+The verbs just described provide four different "strengths" of control when
+subsequent matching fails. (*THEN) is the weakest, carrying on the match at the
+next alternative. (*PRUNE) comes next, failing the match at the current
+starting position, but allowing an advance to the next character (for an
+unanchored pattern). (*SKIP) is similar, except that the advance may be more
+than one character. (*COMMIT) is the strongest, causing the entire match to
+fail.
+
+
+More than one backtracking verb
+
+
+If more than one backtracking verb is present in a pattern, the one that is
+backtracked onto first acts. For example, consider this pattern, where A, B,
+etc. are complex pattern fragments:
+
+ (A(*COMMIT)B(*THEN)C|ABD)
+
+If A matches but B fails, the backtrack to (*COMMIT) causes the entire match to
+fail. However, if A and B match, but C fails, the backtrack to (*THEN) causes
+the next alternative (ABD) to be tried. This behaviour is consistent, but is
+not always the same as Perl's. It means that if two or more backtracking verbs
+appear in succession, all but the last of them has no effect. Consider this
+example:
+
+ ...(*COMMIT)(*PRUNE)...
+
+If there is a matching failure to the right, backtracking onto (*PRUNE) causes
+it to be triggered, and its action is taken. There can never be a backtrack
+onto (*COMMIT).
+
+
+Backtracking verbs in repeated groups
+
+
+PCRE2 sometimes differs from Perl in its handling of backtracking verbs in
+repeated groups. For example, consider:
+
+ /(a(*COMMIT)b)+ac/
+
+If the subject is "abac", Perl matches unless its optimizations are disabled,
+but PCRE2 always fails because the (*COMMIT) in the second repeat of the group
+acts.
+
+
+Backtracking verbs in assertions
+
+
+(*FAIL) in any assertion has its normal effect: it forces an immediate
+backtrack. The behaviour of the other backtracking verbs depends on whether or
+not the assertion is standalone or acting as the condition in a conditional
+group.
+
+
+(*ACCEPT) in a standalone positive assertion causes the assertion to succeed
+without any further processing; captured strings and a mark name (if set) are
+retained. In a standalone negative assertion, (*ACCEPT) causes the assertion to
+fail without any further processing; captured substrings and any mark name are
+discarded.
+
+
+If the assertion is a condition, (*ACCEPT) causes the condition to be true for
+a positive assertion and false for a negative one; captured substrings are
+retained in both cases.
+
+
+The remaining verbs act only when a later failure causes a backtrack to
+reach them. This means that, for the Perl-compatible assertions, their effect
+is confined to the assertion, because Perl lookaround assertions are atomic. A
+backtrack that occurs after such an assertion is complete does not jump back
+into the assertion. Note in particular that a (*MARK) name that is set in an
+assertion is not "seen" by an instance of (*SKIP:NAME) later in the pattern.
+
+
+PCRE2 now supports non-atomic positive assertions and also "scan substring"
+assertions, as described in the sections entitled
+"Non-atomic assertions"
+and
+"Scan substring assertions"
+above. These assertions must be standalone (not used as conditions). They are
+not Perl-compatible. For these assertions, a later backtrack does jump back
+into the assertion, and therefore verbs such as (*COMMIT) can be triggered by
+backtracks from later in the pattern.
+
+
+The effect of (*THEN) is not allowed to escape beyond an assertion. If there
+are no more branches to try, (*THEN) causes a positive assertion to be false,
+and a negative assertion to be true. This behaviour differs from Perl when the
+assertion has only one branch.
+
+
+The other backtracking verbs are not treated specially if they appear in a
+standalone positive assertion. In a conditional positive assertion,
+backtracking (from within the assertion) into (*COMMIT), (*SKIP), or (*PRUNE)
+causes the condition to be false. However, for both standalone and conditional
+negative assertions, backtracking into (*COMMIT), (*SKIP), or (*PRUNE) causes
+the assertion to be true, without considering any further alternative branches.
+
+
+Backtracking verbs in subroutines
+
+
+These behaviours occur whether or not the group is called recursively.
+
+
+(*ACCEPT) in a group called as a subroutine causes the subroutine match to
+succeed without any further processing. Matching then continues after the
+subroutine call. Perl documents this behaviour. Perl's treatment of the other
+verbs in subroutines is different in some cases.
+
+
+(*FAIL) in a group called as a subroutine has its normal effect: it forces
+an immediate backtrack.
+
+
+(*COMMIT), (*SKIP), and (*PRUNE) cause the subroutine match to fail when
+triggered by being backtracked to in a group called as a subroutine. There is
+then a backtrack at the outer level.
+
+
+(*THEN), when triggered, skips to the next alternative in the innermost
+enclosing group that has alternatives (its normal behaviour). However, if there
+is no such group within the subroutine's group, the subroutine match fails and
+there is a backtrack at the outer level.
+
+
+
+Differences in the way PCRE behaves when it is running in an EBCDIC environment
+are covered in this section.
+
+
+Escape sequences
+
+
+When PCRE2 is compiled in EBCDIC mode, \N{U+hhh..} is not supported. \a, \e,
+\f, \n, \r, and \t generate the appropriate EBCDIC code values. The \c
+escape is processed as specified for Perl in the perlebcdic document. The
+only characters that are allowed after \c are A-Z, a-z, or one of @, [, \, ],
+^, _, or ?. Any other character provokes a compile-time error. The sequence
+\c@ encodes character code 0; after \c the letters (in either case) encode
+characters 1-26 (hex 01 to hex 1A); [, \, ], ^, and _ encode characters 27-31
+(hex 1B to hex 1F), and \c? becomes either 255 (hex FF) or 95 (hex 5F).
+
+
+Thus, apart from \c?, these escapes generate the same character code values as
+they do in an ASCII or Unicode environment, though the meanings of the values
+mostly differ. For example, \cG always generates code value 7, which is BEL in
+ASCII but DEL in EBCDIC.
+
+
+The sequence \c? generates DEL (127, hex 7F) in an ASCII environment, but
+because 127 is not a control character in EBCDIC, Perl makes it generate the
+APC character. Unfortunately, there are several variants of EBCDIC. In most of
+them the APC character has the value 255 (hex FF), but in the one Perl calls
+POSIX-BC its value is 95 (hex 5F). If certain other characters have POSIX-BC
+values, PCRE2 makes \c? generate 95; otherwise it generates 255.
+
+
+Character classes
+
+
+In character classes there is a special case in EBCDIC environments for ranges
+whose end points are both specified as literal letters in the same case. For
+compatibility with Perl, EBCDIC code points within the range that are not
+letters are omitted. For example, [h-k] matches only four characters, even
+though the EBCDIC codes for h and k are 0x88 and 0x92, a range of 11 code
+points. However, if the range is specified numerically, for example,
+[\x88-\x92] or [h-\x92], all code points are included.
+
+
+
+pcre2api(3), pcre2callout(3), pcre2matching(3),
+pcre2syntax(3), pcre2(3).
+
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+
+Last updated: 25 October 2025
+
+Copyright © 1997-2024 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2perform.html b/doc/html/pcre2perform.html
new file mode 100644
index 0000000..772e9f0
--- /dev/null
+++ b/doc/html/pcre2perform.html
@@ -0,0 +1,280 @@
+
+
+pcre2perform specification
+
+
+pcre2perform man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+Two aspects of performance are discussed below: memory usage and processing
+time. The way you express your pattern as a regular expression can affect both
+of them.
+
+
+
+Patterns are compiled by PCRE2 into a reasonably efficient interpretive code,
+so that most simple patterns do not use much memory for storing the compiled
+version. However, there is one case where the memory usage of a compiled
+pattern can be unexpectedly large. If a parenthesized group has a quantifier
+with a minimum greater than 1 and/or a limited maximum, the whole group is
+repeated in the compiled code. For example, the pattern
+
+ (abc|def){2,4}
+
+is compiled as if it were
+
+ (abc|def)(abc|def)((abc|def)(abc|def)?)?
+
+(Technical aside: It is done this way so that backtrack points within each of
+the repetitions can be independently maintained.)
+
+
+For regular expressions whose quantifiers use only small numbers, this is not
+usually a problem. However, if the numbers are large, and particularly if such
+repetitions are nested, the memory usage can become an embarrassment. For
+example, the very simple pattern
+
+ ((ab){1,1000}c){1,3}
+
+uses over 50KiB when compiled using the 8-bit library. When PCRE2 is
+compiled with its default internal pointer size of two bytes, the size limit on
+a compiled pattern is 65535 code units in the 8-bit and 16-bit libraries, and
+this is reached with the above pattern if the outer repetition is increased
+from 3 to 4. PCRE2 can be compiled to use larger internal pointers and thus
+handle larger compiled patterns, but it is better to try to rewrite your
+pattern to use less memory if you can.
+
+
+One way of reducing the memory usage for such patterns is to make use of
+PCRE2's
+"subroutine"
+facility. Re-writing the above pattern as
+
+ ((ab)(?2){0,999}c)(?1){0,2}
+
+reduces the memory requirements to around 16KiB, and indeed it remains under
+20KiB even with the outer repetition increased to 100. However, this kind of
+pattern is not always exactly equivalent, because any captures within
+subroutine calls are lost when the subroutine completes. If this is not a
+problem, this kind of rewriting will allow you to process patterns that PCRE2
+cannot otherwise handle. The matching performance of the two different versions
+of the pattern are roughly the same. (This applies from release 10.30 - things
+were different in earlier releases.)
+
+
+
+From release 10.30, the interpretive (non-JIT) version of pcre2_match()
+uses very little system stack at run time. In earlier releases recursive
+function calls could use a great deal of stack, and this could cause problems,
+but this usage has been eliminated. Backtracking positions are now explicitly
+remembered in memory frames controlled by the code.
+
+
+The size of each frame depends on the size of pointer variables and the number
+of capturing parenthesized groups in the pattern being matched. On a 64-bit
+system the frame size for a pattern with no captures is 128 bytes. For each
+capturing group the size increases by 16 bytes.
+
+
+Until release 10.41, an initial 20KiB frames vector was allocated on the system
+stack, but this still caused some issues for multi-thread applications where
+each thread has a very small stack. From release 10.41 backtracking memory
+frames are always held in heap memory. An initial heap allocation is obtained
+the first time any match data block is passed to pcre2_match(). This is
+remembered with the match data block and re-used if that block is used for
+another match. It is freed when the match data block itself is freed.
+
+
+The size of the initial block is the larger of 20KiB or ten times the pattern's
+frame size, unless the heap limit is less than this, in which case the heap
+limit is used. If the initial block proves to be too small during matching, it
+is replaced by a larger block, subject to the heap limit. The heap limit is
+checked only when a new block is to be allocated. Reducing the heap limit
+between calls to pcre2_match() with the same match data block does not
+affect the saved block.
+
+
+In contrast to pcre2_match(), pcre2_dfa_match() does use recursive
+function calls, but only for processing atomic groups, lookaround assertions,
+and recursion within the pattern. The original version of the code used to
+allocate quite large internal workspace vectors on the stack, which caused some
+problems for some patterns in environments with small stacks. From release
+10.32 the code for pcre2_dfa_match() has been re-factored to use heap
+memory when necessary for internal workspace when recursing, though recursive
+function calls are still used.
+
+
+The "match depth" parameter can be used to limit the depth of function
+recursion, and the "match heap" parameter to limit heap memory in
+pcre2_dfa_match().
+
+
+
+Certain items in regular expression patterns are processed more efficiently
+than others. It is more efficient to use a character class like [aeiou] than a
+set of single-character alternatives such as (a|e|i|o|u). In general, the
+simplest construction that provides the required behaviour is usually the most
+efficient. Jeffrey Friedl's book contains a lot of useful general discussion
+about optimizing regular expressions for efficient performance. This document
+contains a few observations about PCRE2.
+
+
+Using Unicode character properties (the \p, \P, and \X escapes) is slow,
+because PCRE2 has to use a multi-stage table lookup whenever it needs a
+character's property. If you can find an alternative pattern that does not use
+character properties, it will probably be faster.
+
+
+By default, the escape sequences \b, \d, \s, and \w, and the POSIX
+character classes such as [:alpha:] do not use Unicode properties, partly for
+backwards compatibility, and partly for performance reasons. However, you can
+set the PCRE2_UCP option or start the pattern with (*UCP) if you want Unicode
+character properties to be used. This can double the matching time for items
+such as \d, when matched with pcre2_match(); the performance loss is
+less with a DFA matching function, and in both cases there is not much
+difference for \b.
+
+
+When a pattern begins with .* not in atomic parentheses, nor in parentheses
+that are the subject of a backreference, and the PCRE2_DOTALL option is set,
+the pattern is implicitly anchored by PCRE2, since it can match only at the
+start of a subject string. If the pattern has multiple top-level branches, they
+must all be anchorable. The optimization can be disabled by the
+PCRE2_NO_DOTSTAR_ANCHOR option, and is automatically disabled if the pattern
+contains (*PRUNE) or (*SKIP).
+
+
+If PCRE2_DOTALL is not set, PCRE2 cannot make this optimization, because the
+dot metacharacter does not then match a newline, and if the subject string
+contains newlines, the pattern may match from the character immediately
+following one of them instead of from the very start. For example, the pattern
+
+ .*second
+
+matches the subject "first\nand second" (where \n stands for a newline
+character), with the match starting at the seventh character. In order to do
+this, PCRE2 has to retry the match starting after every newline in the subject.
+
+
+If you are using such a pattern with subject strings that do not contain
+newlines, the best performance is obtained by setting PCRE2_DOTALL, or starting
+the pattern with ^.* or ^.*? to indicate explicit anchoring. That saves PCRE2
+from having to scan along the subject looking for a newline to restart at.
+
+
+Beware of patterns that contain nested indefinite repeats. These can take a
+long time to run when applied to a string that does not match. Consider the
+pattern fragment
+
+ ^(a+)*
+
+This can match "aaaa" in 16 different ways, and this number increases very
+rapidly as the string gets longer. (The * repeat can match 0, 1, 2, 3, or 4
+times, and for each of those cases other than 0 or 4, the + repeats can match
+different numbers of times.) When the remainder of the pattern is such that the
+entire match is going to fail, PCRE2 has in principle to try every possible
+variation, and this can take an extremely long time, even for relatively short
+strings.
+
+
+An optimization catches some of the more simple cases such as
+
+ (a+)*b
+
+where a literal character follows. Before embarking on the standard matching
+procedure, PCRE2 checks that there is a "b" later in the subject string, and if
+there is not, it fails the match immediately. However, when there is no
+following literal this optimization cannot be used. You can see the difference
+by comparing the behaviour of
+
+ (a+)*\d
+
+with the pattern above. The former gives a failure almost instantly when
+applied to a whole line of "a" characters, whereas the latter takes an
+appreciable time with strings longer than about 20 characters.
+
+
+In many cases, the solution to this kind of performance issue is to use an
+atomic group or a possessive quantifier. This can often reduce memory
+requirements as well. As another example, consider this pattern:
+
+ ([^<]|<(?!inet))+
+
+It matches from wherever it starts until it encounters "<inet" or the end of
+the data, and is the kind of pattern that might be used when processing an XML
+file. Each iteration of the outer parentheses matches either one character that
+is not "<" or a "<" that is not followed by "inet". However, each time a
+parenthesis is processed, a backtracking position is passed, so this
+formulation uses a memory frame for each matched character. For a long string,
+a lot of memory is required. Consider now this rewritten pattern, which matches
+exactly the same strings:
+
+ ([^<]++|<(?!inet))+
+
+This runs much faster, because sequences of characters that do not contain "<"
+are "swallowed" in one item inside the parentheses, and a possessive quantifier
+is used to stop any backtracking into the runs of non-"<" characters. This
+version also uses a lot less memory because entry to a new set of parentheses
+happens only when a "<" character that is not followed by "inet" is encountered
+(and we assume this is relatively rare).
+
+
+This example shows that one way of optimizing performance when matching long
+subject strings is to write repeated parenthesized subpatterns to match more
+than one character whenever possible.
+
+
+SETTING RESOURCE LIMITS
+
+
+You can set limits on the amount of processing that takes place when matching,
+and on the amount of heap memory that is used. The default values of the limits
+are very large, and unlikely ever to operate. They can be changed when PCRE2 is
+built, and they can also be set when pcre2_match() or
+pcre2_dfa_match() is called. For details of these interfaces, see the
+pcre2build
+documentation and the section entitled
+"The match context"
+in the
+pcre2api
+documentation.
+
+
+The pcre2test test program has a modifier called "find_limits" which, if
+applied to a subject line, causes it to find the smallest limits that allow a
+pattern to match. This is done by repeatedly matching with different limits.
+
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+
+Last updated: 06 December 2022
+
+Copyright © 1997-2022 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2posix.html b/doc/html/pcre2posix.html
new file mode 100644
index 0000000..b07d73b
--- /dev/null
+++ b/doc/html/pcre2posix.html
@@ -0,0 +1,379 @@
+
+
+pcre2posix specification
+
+
+pcre2posix man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+#include <pcre2posix.h>
+
+
+int pcre2_regcomp(regex_t *preg, const char *pattern,
+ int cflags);
+
+
+int pcre2_regexec(const regex_t *preg, const char *string,
+ size_t nmatch, regmatch_t pmatch[], int eflags);
+
+
+size_t pcre2_regerror(int errcode, const regex_t *preg,
+ char *errbuf, size_t errbuf_size);
+
+
+void pcre2_regfree(regex_t *preg);
+
+
+
+This set of functions provides a POSIX-style API for the PCRE2 regular
+expression 8-bit library. There are no POSIX-style wrappers for PCRE2's 16-bit
+and 32-bit libraries. See the
+pcre2api
+documentation for a description of PCRE2's native API, which contains much
+additional functionality.
+
+
+IMPORTANT NOTE: The functions described here are NOT thread-safe, and
+should not be used in multi-threaded applications. They are also limited to
+processing subjects that are not bigger than 2GB. Use the native API instead.
+
+
+These functions are wrapper functions that ultimately call the PCRE2 native
+API. Their prototypes are defined in the pcre2posix.h header file, and
+they all have unique names starting with pcre2_. However, the
+pcre2posix.h header also contains macro definitions that convert the
+standard POSIX names such regcomp() into pcre2_regcomp() etc. This
+means that a program can use the usual POSIX names without running the risk of
+accidentally linking with POSIX functions from a different library.
+
+
+On Unix-like systems the PCRE2 POSIX library is called libpcre2-posix, so
+can be accessed by adding -lpcre2-posix to the command for linking an
+application. Because the POSIX functions call the native ones, it is also
+necessary to add -lpcre2-8.
+
+
+On Windows systems, if you are linking to a DLL version of the library, it is
+recommended that PCRE2POSIX_SHARED is defined before including the
+pcre2posix.h header, as it will allow for a more efficient way to
+invoke the functions by adding the __declspec(dllimport) decorator.
+
+
+Although they were not defined as prototypes in pcre2posix.h, releases
+10.33 to 10.36 of the library contained functions with the POSIX names
+regcomp() etc. These simply passed their arguments to the PCRE2
+functions. These functions were provided for backwards compatibility with
+earlier versions of PCRE2, which had only POSIX names. However, this has proved
+troublesome in situations where a program links with several libraries, some of
+which use PCRE2's POSIX interface while others use the real POSIX functions.
+For this reason, the POSIX names have been removed since release 10.37.
+
+
+Calling the header file pcre2posix.h avoids any conflict with other POSIX
+libraries. It can, of course, be renamed or aliased as regex.h, which is
+the "correct" name, if there is no clash. It provides two structure types,
+regex_t for compiled internal forms, and regmatch_t for returning
+captured substrings. It also defines some constants whose names start with
+"REG_"; these are used for setting options and identifying error codes.
+
+
+
+Note that these functions are just POSIX-style wrappers for PCRE2's native API.
+They do not give POSIX regular expression behaviour, and they are not
+thread-safe or even POSIX compatible.
+
+
+Those POSIX option bits that can reasonably be mapped to PCRE2 native options
+have been implemented. In addition, the option REG_EXTENDED is defined with the
+value zero. This has no effect, but since programs that are written to the
+POSIX interface often use it, this makes it easier to slot in PCRE2 as a
+replacement library. Other POSIX options are not even defined.
+
+
+There are also some options that are not defined by POSIX. These have been
+added at the request of users who want to make use of certain PCRE2-specific
+features via the POSIX calling interface or to add BSD or GNU functionality.
+
+
+When PCRE2 is called via these functions, it is only the API that is POSIX-like
+in style. The syntax and semantics of the regular expressions themselves are
+still those of Perl, subject to the setting of various PCRE2 options, as
+described below. "POSIX-like in style" means that the API approximates to the
+POSIX definition; it is not fully POSIX-compatible, and in multi-unit encoding
+domains it is probably even less compatible.
+
+
+The descriptions below use the actual names of the functions, but, as described
+above, the standard POSIX names (without the pcre2_ prefix) may also be
+used.
+
+
+
+The function pcre2_regcomp() is called to compile a pattern into an
+internal form. By default, the pattern is a C string terminated by a binary
+zero (but see REG_PEND below). The preg argument is a pointer to a
+regex_t structure that is used as a base for storing information about
+the compiled regular expression. It is also used for input when REG_PEND is
+set. The regex_t structure used by pcre2_regcomp() is defined in
+pcre2posix.h and is not the same as the structure used by other libraries
+that provide POSIX-style matching.
+
+
+The argument cflags is either zero, or contains one or more of the bits
+defined by the following macros:
+
+ REG_DOTALL
+
+The PCRE2_DOTALL option is set when the regular expression is passed for
+compilation to the native function. Note that REG_DOTALL is not part of the
+POSIX standard.
+
+ REG_ICASE
+
+The PCRE2_CASELESS option is set when the regular expression is passed for
+compilation to the native function.
+
+ REG_NEWLINE
+
+The PCRE2_MULTILINE option is set when the regular expression is passed for
+compilation to the native function. Note that this does not mimic the
+defined POSIX behaviour for REG_NEWLINE (see the following section).
+
+ REG_NOSPEC
+
+The PCRE2_LITERAL option is set when the regular expression is passed for
+compilation to the native function. This disables all meta characters in the
+pattern, causing it to be treated as a literal string. The only other options
+that are allowed with REG_NOSPEC are REG_ICASE, REG_NOSUB, REG_PEND, and
+REG_UTF. Note that REG_NOSPEC is not part of the POSIX standard.
+
+ REG_NOSUB
+
+When a pattern that is compiled with this flag is passed to
+pcre2_regexec() for matching, the nmatch and pmatch arguments
+are ignored, and no captured strings are returned. Versions of the PCRE2 library
+prior to 10.22 used to set the PCRE2_NO_AUTO_CAPTURE compile option, but this
+no longer happens because it disables the use of backreferences.
+
+ REG_PEND
+
+If this option is set, the reg_endp field in the preg structure
+(which has the type const char *) must be set to point to the character beyond
+the end of the pattern before calling pcre2_regcomp(). The pattern itself
+may now contain binary zeros, which are treated as data characters. Without
+REG_PEND, a binary zero terminates the pattern and the re_endp field is
+ignored. This is a GNU extension to the POSIX standard and should be used with
+caution in software intended to be portable to other systems.
+
+ REG_UCP
+
+The PCRE2_UCP option is set when the regular expression is passed for
+compilation to the native function. This causes PCRE2 to use Unicode properties
+when matching \d, \w, etc., instead of just recognizing ASCII values. Note
+that REG_UCP is not part of the POSIX standard.
+
+ REG_UNGREEDY
+
+The PCRE2_UNGREEDY option is set when the regular expression is passed for
+compilation to the native function. Note that REG_UNGREEDY is not part of the
+POSIX standard.
+
+ REG_UTF
+
+The PCRE2_UTF option is set when the regular expression is passed for
+compilation to the native function. This causes the pattern itself and all data
+strings used for matching it to be treated as UTF-8 strings. Note that REG_UTF
+is not part of the POSIX standard.
+
+
+In the absence of these flags, no options are passed to the native function.
+This means that the regex is compiled with PCRE2 default semantics. In
+particular, the way it handles newline characters in the subject string is the
+Perl way, not the POSIX way. Note that setting PCRE2_MULTILINE has only
+some of the effects specified for REG_NEWLINE. It does not affect the way
+newlines are matched by the dot metacharacter (they are not) or by a negative
+class such as [^a] (they are).
+
+
+The yield of pcre2_regcomp() is zero on success, and non-zero otherwise.
+The preg structure is filled in on success, and one other member of the
+structure (as well as re_endp) is public: re_nsub contains the
+number of capturing subpatterns in the regular expression. Various error codes
+are defined in the header file.
+
+
+NOTE: If the yield of pcre2_regcomp() is non-zero, you must not attempt
+to use the contents of the preg structure. If, for example, you pass it
+to pcre2_regexec(), the result is undefined and your program is likely to
+crash.
+
+
+
+This area is not simple, because POSIX and Perl take different views of things.
+It is not possible to get PCRE2 to obey POSIX semantics, but then PCRE2 was
+never intended to be a POSIX engine. The following table lists the different
+possibilities for matching newline characters in Perl and PCRE2:
+
+ Default Change with
+
+ . matches newline no PCRE2_DOTALL
+ newline matches [^a] yes not changeable
+ $ matches \n at end yes PCRE2_DOLLAR_ENDONLY
+ $ matches \n in middle no PCRE2_MULTILINE
+ ^ matches \n in middle no PCRE2_MULTILINE
+
+This is the equivalent table for a POSIX-compatible pattern matcher:
+
+ Default Change with
+
+ . matches newline yes REG_NEWLINE
+ newline matches [^a] yes REG_NEWLINE
+ $ matches \n at end no REG_NEWLINE
+ $ matches \n in middle no REG_NEWLINE
+ ^ matches \n in middle no REG_NEWLINE
+
+This behaviour is not what happens when PCRE2 is called via its POSIX
+API. By default, PCRE2's behaviour is the same as Perl's, except that there is
+no equivalent for PCRE2_DOLLAR_ENDONLY in Perl. In both PCRE2 and Perl, there
+is no way to stop newline from matching [^a].
+
+
+Default POSIX newline handling can be obtained by setting PCRE2_DOTALL and
+PCRE2_DOLLAR_ENDONLY when calling pcre2_compile() directly, but there is
+no way to make PCRE2 behave exactly as for the REG_NEWLINE action. When using
+the POSIX API, passing REG_NEWLINE to PCRE2's pcre2_regcomp() function
+causes PCRE2_MULTILINE to be passed to pcre2_compile(), and REG_DOTALL
+passes PCRE2_DOTALL. There is no way to pass PCRE2_DOLLAR_ENDONLY.
+
+
+
+The function pcre2_regexec() is called to match a compiled pattern
+preg against a given string, which is by default terminated by a
+zero byte (but see REG_STARTEND below), subject to the options in eflags.
+These can be:
+
+ REG_NOTBOL
+
+The PCRE2_NOTBOL option is set when calling the underlying PCRE2 matching
+function.
+
+ REG_NOTEMPTY
+
+The PCRE2_NOTEMPTY option is set when calling the underlying PCRE2 matching
+function. Note that REG_NOTEMPTY is not part of the POSIX standard. However,
+setting this option can give more POSIX-like behaviour in some situations.
+
+ REG_NOTEOL
+
+The PCRE2_NOTEOL option is set when calling the underlying PCRE2 matching
+function.
+
+ REG_STARTEND
+
+When this option is set, the subject string starts at string +
+pmatch[0].rm_so and ends at string + pmatch[0].rm_eo, which
+should point to the first character beyond the string. There may be binary
+zeros within the subject string, and indeed, using REG_STARTEND is the only
+way to pass a subject string that contains a binary zero.
+
+
+Whatever the value of pmatch[0].rm_so, the offsets of the matched string
+and any captured substrings are still given relative to the start of
+string itself. (Before PCRE2 release 10.30 these were given relative to
+string + pmatch[0].rm_so, but this differs from other
+implementations.)
+
+
+This is a BSD extension, compatible with but not specified by IEEE Standard
+1003.2 (POSIX.2), and should be used with caution in software intended to be
+portable to other systems. Note that a non-zero rm_so does not imply
+REG_NOTBOL; REG_STARTEND affects only the location and length of the string,
+not how it is matched. Setting REG_STARTEND and passing pmatch as NULL
+are mutually exclusive; the error REG_INVARG is returned.
+
+
+If the pattern was compiled with the REG_NOSUB flag, no data about any matched
+strings is returned. The nmatch and pmatch arguments of
+pcre2_regexec() are ignored (except possibly as input for REG_STARTEND).
+
+
+The value of nmatch may be zero, and the value pmatch may be NULL
+(unless REG_STARTEND is set); in both these cases no data about any matched
+strings is returned.
+
+
+Otherwise, the portion of the string that was matched, and also any captured
+substrings, are returned via the pmatch argument, which points to an
+array of nmatch structures of type regmatch_t, containing the
+members rm_so and rm_eo. These contain the byte offset to the first
+character of each substring and the offset to the first character after the end
+of each substring, respectively. The 0th element of the vector relates to the
+entire portion of string that was matched; subsequent elements relate to
+the capturing subpatterns of the regular expression. Unused entries in the
+array have both structure members set to -1.
+
+
+regmatch_t as well as the regoff_t typedef it uses are defined in
+pcre2posix.h and are not warranted to have the same size or layout as other
+similarly named types from other libraries that provide POSIX-style matching.
+
+
+A successful match yields a zero return; various error codes are defined in the
+header file, of which REG_NOMATCH is the "expected" failure code.
+
+
+
+The pcre2_regerror() function maps a non-zero errorcode from either
+pcre2_regcomp() or pcre2_regexec() to a printable message. If
+preg is not NULL, the error should have arisen from the use of that
+structure. A message terminated by a binary zero is placed in errbuf. If
+the buffer is too short, only the first errbuf_size - 1 characters of the
+error message are used. The yield of the function is the size of buffer needed
+to hold the whole message, including the terminating zero. This value is
+greater than errbuf_size if the message was truncated.
+
+
+
+Compiling a regular expression causes memory to be allocated and associated
+with the preg structure. The function pcre2_regfree() frees all
+such memory, after which preg may no longer be used as a compiled
+expression.
+
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+
+Last updated: 27 November 2024
+
+Copyright © 1997-2024 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2sample.html b/doc/html/pcre2sample.html
new file mode 100644
index 0000000..4984ebb
--- /dev/null
+++ b/doc/html/pcre2sample.html
@@ -0,0 +1,111 @@
+
+
+pcre2sample specification
+
+
+pcre2sample man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+PCRE2 SAMPLE PROGRAM
+
+
+A simple, complete demonstration program to get you started with using PCRE2 is
+supplied in the file pcre2demo.c in the src directory in the PCRE2
+distribution. A listing of this program is given in the
+pcre2demo
+documentation. If you do not have a copy of the PCRE2 distribution, you can
+save this listing to recreate the contents of pcre2demo.c.
+
+
+The demonstration program compiles the regular expression that is its
+first argument, and matches it against the subject string in its second
+argument. No PCRE2 options are set, and default character tables are used. If
+matching succeeds, the program outputs the portion of the subject that matched,
+together with the contents of any captured substrings.
+
+
+If the -g option is given on the command line, the program then goes on to
+check for further matches of the same regular expression in the same subject
+string. The logic is a little bit tricky because of the possibility of matching
+an empty string. Comments in the code explain what is going on.
+
+
+The code in pcre2demo.c is an 8-bit program that uses the PCRE2 8-bit
+library. It handles strings and characters that are stored in 8-bit code units.
+By default, one character corresponds to one code unit, but if the pattern
+starts with "(*UTF)", both it and the subject are treated as UTF-8 strings,
+where characters may occupy multiple code units.
+
+
+If PCRE2 is installed in the standard include and library directories for your
+operating system, you should be able to compile the demonstration program using
+a command like this:
+
+ cc -o pcre2demo pcre2demo.c -lpcre2-8
+
+If PCRE2 is installed elsewhere, you may need to add additional options to the
+command line. For example, on a Unix-like system that has PCRE2 installed in
+/usr/local, you can compile the demonstration program using a command
+like this:
+
+ cc -o pcre2demo -I/usr/local/include pcre2demo.c -L/usr/local/lib -lpcre2-8
+
+Once you have built the demonstration program, you can run simple tests like
+this:
+
+ ./pcre2demo 'cat|dog' 'the cat sat on the mat'
+ ./pcre2demo -g 'cat|dog' 'the dog sat on the cat'
+ ./pcre2demo -i 'cat' 'the dog sat on the CAT'
+
+Note that there is a much more comprehensive test program, called
+pcre2test,
+which supports many more facilities for testing regular expressions using all
+three PCRE2 libraries (8-bit, 16-bit, and 32-bit, though not all three need be
+installed). The
+pcre2demo
+program is provided as a relatively simple coding example.
+
+
+If you try to run
+pcre2demo
+when PCRE2 is not installed in the standard library directory, you may get an
+error like this on some operating systems (e.g. Solaris):
+
+ ld.so.1: pcre2demo: fatal: libpcre2-8.so.0: open failed: No such file or directory
+
+This is caused by the way shared library support works on those systems. You
+need to add
+
+ -R/usr/local/lib
+
+(for example) to the compile command to get round this problem.
+
+
+AUTHOR
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+REVISION
+
+
+Last updated: 28 February 2025
+
+Copyright © 1997-2016 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2serialize.html b/doc/html/pcre2serialize.html
new file mode 100644
index 0000000..16c2be7
--- /dev/null
+++ b/doc/html/pcre2serialize.html
@@ -0,0 +1,212 @@
+
+
+pcre2serialize specification
+
+
+pcre2serialize man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+int32_t pcre2_serialize_decode(pcre2_code **codes,
+ int32_t number_of_codes, const uint8_t *bytes,
+ pcre2_general_context *gcontext);
+
+
+int32_t pcre2_serialize_encode(const pcre2_code **codes,
+ int32_t number_of_codes, uint8_t **serialized_bytes,
+ PCRE2_SIZE *serialized_size, pcre2_general_context *gcontext);
+
+
+void pcre2_serialize_free(uint8_t *bytes);
+
+
+int32_t pcre2_serialize_get_number_of_codes(const uint8_t *bytes);
+
+
+If you are running an application that uses a large number of regular
+expression patterns, it may be useful to store them in a precompiled form
+instead of having to compile them every time the application is run. However,
+if you are using the just-in-time optimization feature, it is not possible to
+save and reload the JIT data, because it is position-dependent. The host on
+which the patterns are reloaded must be running the same version of PCRE2, with
+the same code unit width, and must also have the same endianness, pointer width
+and PCRE2_SIZE type. For example, patterns compiled on a 32-bit system using
+PCRE2's 16-bit library cannot be reloaded on a 64-bit system, nor can they be
+reloaded using the 8-bit library.
+
+
+Note that "serialization" in PCRE2 does not convert compiled patterns to an
+abstract format like Java or .NET serialization. The serialized output is
+really just a bytecode dump, which is why it can only be reloaded in the same
+environment as the one that created it. Hence the restrictions mentioned above.
+Applications that are not statically linked with a fixed version of PCRE2 must
+be prepared to recompile patterns from their sources, in order to be immune to
+PCRE2 upgrades.
+
+
+
+The facility for saving and restoring compiled patterns is intended for use
+within individual applications. As such, the data supplied to
+pcre2_serialize_decode() is expected to be trusted data, not data from
+arbitrary external sources. There is only some simple consistency checking, not
+complete validation of what is being re-loaded. Corrupted data may cause
+undefined results. For example, if the length field of a pattern in the
+serialized data is corrupted, the deserializing code may read beyond the end of
+the byte stream that is passed to it.
+
+
+
+Before compiled patterns can be saved they must be serialized, which in PCRE2
+means converting the pattern to a stream of bytes. A single byte stream may
+contain any number of compiled patterns, but they must all use the same
+character tables. A single copy of the tables is included in the byte stream
+(its size is 1088 bytes). For more details of character tables, see the
+section on locale support
+in the
+pcre2api
+documentation.
+
+
+The function pcre2_serialize_encode() creates a serialized byte stream
+from a list of compiled patterns. Its first two arguments specify the list,
+being a pointer to a vector of pointers to compiled patterns, and the length of
+the vector. The third and fourth arguments point to variables which are set to
+point to the created byte stream and its length, respectively. The final
+argument is a pointer to a general context, which can be used to specify custom
+memory management functions. If this argument is NULL, malloc() is used
+to obtain memory for the byte stream. The yield of the function is the number
+of serialized patterns, or one of the following negative error codes:
+
+ PCRE2_ERROR_BADDATA the number of patterns is zero or less
+ PCRE2_ERROR_BADMAGIC mismatch of id bytes in one of the patterns
+ PCRE2_ERROR_NOMEMORY memory allocation failed
+ PCRE2_ERROR_MIXEDTABLES the patterns do not all use the same tables
+ PCRE2_ERROR_NULL the 1st, 3rd, or 4th argument is NULL
+
+PCRE2_ERROR_BADMAGIC means either that a pattern's code has been corrupted, or
+that a slot in the vector does not point to a compiled pattern.
+
+
+Once a set of patterns has been serialized you can save the data in any
+appropriate manner. Here is sample code that compiles two patterns and writes
+them to a file. It assumes that the variable fd refers to a file that is
+open for output. The error checking that should be present in a real
+application has been omitted for simplicity.
+
+ int errorcode;
+ uint8_t *bytes;
+ PCRE2_SIZE erroroffset;
+ PCRE2_SIZE bytescount;
+ pcre2_code *list_of_codes[2];
+ list_of_codes[0] = pcre2_compile("first pattern",
+ PCRE2_ZERO_TERMINATED, 0, &errorcode, &erroroffset, NULL);
+ list_of_codes[1] = pcre2_compile("second pattern",
+ PCRE2_ZERO_TERMINATED, 0, &errorcode, &erroroffset, NULL);
+ errorcode = pcre2_serialize_encode(list_of_codes, 2, &bytes,
+ &bytescount, NULL);
+ errorcode = fwrite(bytes, 1, bytescount, fd);
+
+Note that the serialized data is binary data that may contain any of the 256
+possible byte values. On systems that make a distinction between binary and
+non-binary data, be sure that the file is opened for binary output.
+
+
+Serializing a set of patterns leaves the original data untouched, so they can
+still be used for matching. Their memory must eventually be freed in the usual
+way by calling pcre2_code_free(). When you have finished with the byte
+stream, it too must be freed by calling pcre2_serialize_free(). If this
+function is called with a NULL argument, it returns immediately without doing
+anything.
+
+
+
+In order to re-use a set of saved patterns you must first make the serialized
+byte stream available in main memory (for example, by reading from a file). The
+management of this memory block is up to the application. You can use the
+pcre2_serialize_get_number_of_codes() function to find out how many
+compiled patterns are in the serialized data without actually decoding the
+patterns:
+
+ uint8_t *bytes = <serialized data>;
+ int32_t number_of_codes = pcre2_serialize_get_number_of_codes(bytes);
+
+The pcre2_serialize_decode() function reads a byte stream and recreates
+the compiled patterns in new memory blocks, setting pointers to them in a
+vector. The first two arguments are a pointer to a suitable vector and its
+length, and the third argument points to a byte stream. The final argument is a
+pointer to a general context, which can be used to specify custom memory
+management functions for the decoded patterns. If this argument is NULL,
+malloc() and free() are used. After deserialization, the byte
+stream is no longer needed and can be discarded.
+
+ pcre2_code *list_of_codes[2];
+ uint8_t *bytes = <serialized data>;
+ int32_t number_of_codes =
+ pcre2_serialize_decode(list_of_codes, 2, bytes, NULL);
+
+If the vector is not large enough for all the patterns in the byte stream, it
+is filled with those that fit, and the remainder are ignored. The yield of the
+function is the number of decoded patterns, or one of the following negative
+error codes:
+
+ PCRE2_ERROR_BADDATA second argument is zero or less
+ PCRE2_ERROR_BADMAGIC mismatch of id bytes in the data
+ PCRE2_ERROR_BADMODE mismatch of code unit size or PCRE2 version
+ PCRE2_ERROR_BADSERIALIZEDDATA other sanity check failure
+ PCRE2_ERROR_MEMORY memory allocation failed
+ PCRE2_ERROR_NULL first or third argument is NULL
+
+PCRE2_ERROR_BADMAGIC may mean that the data is corrupt, or that it was compiled
+on a system with different endianness.
+
+
+Decoded patterns can be used for matching in the usual way, and must be freed
+by calling pcre2_code_free(). However, be aware that there is a potential
+race issue if you are using multiple patterns that were decoded from a single
+byte stream in a multithreaded application. A single copy of the character
+tables is used by all the decoded patterns and a reference count is used to
+arrange for its memory to be automatically freed when the last pattern is
+freed, but there is no locking on this reference count. Therefore, if you want
+to call pcre2_code_free() for these patterns in different threads, you
+must arrange your own locking, and ensure that pcre2_code_free() cannot
+be called by two threads at the same time.
+
+
+If a pattern was processed by pcre2_jit_compile() before being
+serialized, the JIT data is discarded and so is no longer available after a
+save/restore cycle. You can, however, process a restored pattern with
+pcre2_jit_compile() if you wish.
+
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+
+Last updated: 19 January 2024
+
+Copyright © 1997-2018 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2syntax.html b/doc/html/pcre2syntax.html
new file mode 100644
index 0000000..bd5bc01
--- /dev/null
+++ b/doc/html/pcre2syntax.html
@@ -0,0 +1,781 @@
+
+
+pcre2syntax specification
+
+
+pcre2syntax man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+The full syntax and semantics of the regular expression patterns that are
+supported by PCRE2 are described in the
+pcre2pattern
+documentation. This document contains a quick-reference summary of the pattern
+syntax followed by the syntax of replacement strings in substitution function.
+The full description of the latter is in the
+pcre2api
+documentation.
+
+
+
+
+ \x where x is non-alphanumeric is a literal x
+ \Q...\E treat enclosed characters as literal
+
+Note that white space inside \Q...\E is always treated as literal, even if
+PCRE2_EXTENDED is set, causing most other white space to be ignored. Note also
+that PCRE2's handling of \Q...\E has some differences from Perl's. See the
+pcre2pattern
+documentation for details.
+
+
+
+With one exception, wherever brace characters { and } are required to enclose
+data for constructions such as \g{2} or \k{name}, space and/or horizontal tab
+characters that follow { or precede } are allowed and are ignored. In the case
+of quantifiers, they may also appear before or after the comma. The exception
+is \u{...} which is not Perl-compatible and is recognized only when
+PCRE2_EXTRA_ALT_BSUX is set. This is an ECMAScript compatibility feature, and
+follows ECMAScript's behaviour.
+
+
+
+This table applies to ASCII and Unicode environments. An unrecognized escape
+sequence causes an error.
+
+ \a alarm, that is, the BEL character (hex 07)
+ \cx "control-x", where x is a non-control ASCII character
+ \e escape (hex 1B)
+ \f form feed (hex 0C)
+ \n newline (hex 0A)
+ \r carriage return (hex 0D)
+ \t tab (hex 09)
+ \0dd character with octal code 0dd
+ \ddd character with octal code ddd, or backreference
+ \o{ddd..} character with octal code ddd..
+ \N{U+hh..} character with Unicode code point hh.. (Unicode mode only)
+ \xhh character with hex code hh
+ \x{hh..} character with hex code hh..
+
+\N{U+hh..} is synonymous with \x{hh..} but is not supported in environments
+that use EBCDIC code (mainly IBM mainframes). Note that \N not followed by an
+opening curly bracket has a different meaning (see below).
+
+
+If PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX is set ("ALT_BSUX mode"), the
+following are also recognized:
+
+ \U the character "U"
+ \uhhhh character with hex code hhhh
+ \u{hh..} character with hex code hh.. but only for EXTRA_ALT_BSUX
+
+When \x is not followed by {, one or two hexadecimal digits are read,
+but in ALT_BSUX mode \x must be followed by two hexadecimal digits to be
+recognized as a hexadecimal escape; otherwise it matches a literal "x".
+Likewise, if \u (in ALT_BSUX mode) is not followed by four hexadecimal digits
+or (in EXTRA_ALT_BSUX mode) a sequence of hex digits in curly brackets, it
+matches a literal "u".
+
+
+Note that \0dd is always an octal code. The treatment of backslash followed by
+a non-zero digit is complicated; for details see the section
+"Non-printing characters"
+in the
+pcre2pattern
+documentation, where details of escape processing in EBCDIC environments are
+also given.
+
+
+
+
+ . any character except newline;
+ in dotall mode, any character whatsoever
+ \C one code unit, even in UTF mode (best avoided)
+ \d a decimal digit
+ \D a character that is not a decimal digit
+ \h a horizontal white space character
+ \H a character that is not a horizontal white space character
+ \N a character that is not a newline
+ \p{xx} a character with the xx property
+ \P{xx} a character without the xx property
+ \R a newline sequence
+ \s a white space character
+ \S a character that is not a white space character
+ \v a vertical white space character
+ \V a character that is not a vertical white space character
+ \w a "word" character
+ \W a "non-word" character
+ \X a Unicode extended grapheme cluster
+
+\C is dangerous because it may leave the current matching point in the middle
+of a UTF-8 or UTF-16 character. The application can lock out the use of \C by
+setting the PCRE2_NEVER_BACKSLASH_C option. It is also possible to build PCRE2
+with the use of \C permanently disabled.
+
+
+By default, \d, \s, and \w match only ASCII characters, even in UTF-8 mode
+or in the 16-bit and 32-bit libraries. However, if locale-specific matching is
+happening, \s and \w may also match characters with code points in the range
+128-255. If the PCRE2_UCP option is set, the behaviour of these escape
+sequences is changed to use Unicode properties and they match many more
+characters, but there are some option settings that can restrict individual
+sequences to matching only ASCII characters.
+
+
+Property descriptions in \p and \P are matched caselessly; hyphens,
+underscores, and ASCII white space characters are ignored, in accordance with
+Unicode's "loose matching" rules. For example, \p{Bidi_Class=al} is the same
+as \p{ bidi class = AL }.
+
+
+
+
+ C Other
+ Cc Control
+ Cf Format
+ Cn Unassigned
+ Co Private use
+ Cs Surrogate
+
+ L Letter
+ Lc Cased letter, the union of Ll, Lu, and Lt
+ L& Synonym of Lc
+ Ll Lower case letter
+ Lm Modifier letter
+ Lo Other letter
+ Lt Title case letter
+ Lu Upper case letter
+
+ M Mark
+ Mc Spacing mark
+ Me Enclosing mark
+ Mn Non-spacing mark
+
+ N Number
+ Nd Decimal number
+ Nl Letter number
+ No Other number
+
+ P Punctuation
+ Pc Connector punctuation
+ Pd Dash punctuation
+ Pe Close punctuation
+ Pf Final punctuation
+ Pi Initial punctuation
+ Po Other punctuation
+ Ps Open punctuation
+
+ S Symbol
+ Sc Currency symbol
+ Sk Modifier symbol
+ Sm Mathematical symbol
+ So Other symbol
+
+ Z Separator
+ Zl Line separator
+ Zp Paragraph separator
+ Zs Space separator
+
+From release 10.45, when caseless matching is set, Ll, Lu, and Lt are all
+equivalent to Lc.
+
+
+
+
+ Xan Alphanumeric: union of properties L and N
+ Xps POSIX space: property Z or tab, NL, VT, FF, CR
+ Xsp Perl space: property Z or tab, NL, VT, FF, CR
+ Xuc Universally-named character: one that can be
+ represented by a Universal Character Name
+ Xwd Perl word: property Xan or underscore
+
+Perl and POSIX space are now the same. Perl added VT to its space character set
+at release 5.18.
+
+
+
+Unicode defines a number of binary properties, that is, properties whose only
+values are true or false. You can obtain a list of those that are recognized by
+\p and \P, along with their abbreviations, by running this command:
+
+ pcre2test -LP
+
+
+
+
+Many script names and their 4-letter abbreviations are recognized in
+\p{sc:...} or \p{scx:...} items, or on their own with \p (and also \P of
+course). You can obtain a list of these scripts by running this command:
+
+ pcre2test -LS
+
+
+
+
+
+ \p{Bidi_Class:<class>} matches a character with the given class
+ \p{BC:<class>} matches a character with the given class
+
+The recognized classes are:
+
+ AL Arabic letter
+ AN Arabic number
+ B paragraph separator
+ BN boundary neutral
+ CS common separator
+ EN European number
+ ES European separator
+ ET European terminator
+ FSI first strong isolate
+ L left-to-right
+ LRE left-to-right embedding
+ LRI left-to-right isolate
+ LRO left-to-right override
+ NSM non-spacing mark
+ ON other neutral
+ PDF pop directional format
+ PDI pop directional isolate
+ R right-to-left
+ RLE right-to-left embedding
+ RLI right-to-left isolate
+ RLO right-to-left override
+ S segment separator
+ WS white space
+
+
+
+
+
+ [...] positive character class
+ [^...] negative character class
+ [x-y] range (can be used for hex characters)
+ [[:xxx:]] positive POSIX named set
+ [[:^xxx:]] negative POSIX named set
+
+ alnum alphanumeric
+ alpha alphabetic
+ ascii 0-127
+ blank space or tab
+ cntrl control character
+ digit decimal digit
+ graph printing, excluding space
+ lower lower case letter
+ print printing, including space
+ punct printing, excluding alphanumeric
+ space white space
+ upper upper case letter
+ word same as \w
+ xdigit hexadecimal digit
+
+In PCRE2, POSIX character set names recognize only ASCII characters by default,
+but some of them use Unicode properties if PCRE2_UCP is set. You can use
+\Q...\E inside a character class.
+
+
+When PCRE2_ALT_EXTENDED_CLASS is set, UTS#18 extended character classes may be
+used, allowing nested character classes, combined using set operators.
+
+ [x&&[^y]] UTS#18 extended character class
+
+ x||y set union (OR)
+ x&&y set intersection (AND)
+ x--y set difference (AND NOT)
+ x~~y set symmetric difference (XOR)
+
+
+
+
+
+
+ (?[...]) Perl extended character class
+ (?[\p{Thai} & \p{Nd}]) operators; white space ignored
+ (?[(x - y) & z]) parentheses for grouping
+
+ (?[ [^3] & \p{Nd} ]) [...] is a nested ordinary class
+ (?[ [:alpha:] - [z] ]) POSIX set is allowed outside [...]
+ (?[ \d - [3] ]) backslash-escaped set is allowed outside [...]
+ (?[ !\n & [:ascii:] ]) backslash-escaped character is allowed outside [...]
+ all other characters or ranges must be enclosed in [...]
+
+ x|y, x+y set union (OR)
+ x&y set intersection (AND)
+ x-y set difference (AND NOT)
+ x^y set symmetric difference (XOR)
+ !x set complement (NOT)
+
+Inside a Perl extended character class, [...] switches mode to be interpreted
+as an ordinary character class. Outside of a nested [...], the only items
+permitted are backslash-escapes, POSIX sets, operators, and parentheses. Inside
+a nested ordinary class, ^ has its usual meaning (inverts the class when used
+as the first character); outside of a nested class, ^ is the XOR operator.
+
+
+
+
+ ? 0 or 1, greedy
+ ?+ 0 or 1, possessive
+ ?? 0 or 1, lazy
+ * 0 or more, greedy
+ *+ 0 or more, possessive
+ *? 0 or more, lazy
+ + 1 or more, greedy
+ ++ 1 or more, possessive
+ +? 1 or more, lazy
+ {n} exactly n
+ {n,m} at least n, no more than m, greedy
+ {n,m}+ at least n, no more than m, possessive
+ {n,m}? at least n, no more than m, lazy
+ {n,} n or more, greedy
+ {n,}+ n or more, possessive
+ {n,}? n or more, lazy
+ {,m} zero up to m, greedy
+ {,m}+ zero up to m, possessive
+ {,m}? zero up to m, lazy
+
+
+
+
+
+ \b word boundary
+ \B not a word boundary
+ ^ start of subject
+ also after an internal newline in multiline mode
+ (after any newline if PCRE2_ALT_CIRCUMFLEX is set)
+ \A start of subject
+ $ end of subject
+ also before newline at end of subject
+ also before internal newline in multiline mode
+ \Z end of subject
+ also before newline at end of subject
+ \z end of subject
+ \G first matching position in subject
+
+
+
+
+
+ \K set reported start of match
+
+From release 10.38 \K is not permitted by default in lookaround assertions,
+for compatibility with Perl. However, if the PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK
+option is set, the previous behaviour is re-enabled. When this option is set,
+\K is honoured in positive assertions, but ignored in negative ones.
+
+
+
+
+ expr|expr|expr...
+
+
+
+
+
+ (...) capture group
+ (?<name>...) named capture group (Perl)
+ (?'name'...) named capture group (Perl)
+ (?P<name>...) named capture group (Python)
+ (?:...) non-capture group
+ (?|...) non-capture group; reset group numbers for
+ capture groups in each alternative
+
+In non-UTF modes, names may contain underscores and ASCII letters and digits;
+in UTF modes, any Unicode letters and Unicode decimal digits are permitted. In
+both cases, a name must not start with a digit.
+
+
+
+
+ (?>...) atomic non-capture group
+ (*atomic:...) atomic non-capture group
+
+
+
+
+
+ (?#....) comment (not nestable)
+
+
+
+
+Changes of these options within a group are automatically cancelled at the end
+of the group.
+
+ (?a) all ASCII options
+ (?aD) restrict \d to ASCII in UCP mode
+ (?aS) restrict \s to ASCII in UCP mode
+ (?aW) restrict \w to ASCII in UCP mode
+ (?aP) restrict all POSIX classes to ASCII in UCP mode
+ (?aT) restrict POSIX digit classes to ASCII in UCP mode
+ (?i) caseless
+ (?J) allow duplicate named groups
+ (?m) multiline
+ (?n) no auto capture
+ (?r) restrict caseless to either ASCII or non-ASCII
+ (?s) single line (dotall)
+ (?U) default ungreedy (lazy)
+ (?x) ignore white space except in classes or \Q...\E
+ (?xx) as (?x) but also ignore space and tab in classes
+ (?-...) unset the given option(s)
+ (?^) unset imnrsx options
+
+(?aP) implies (?aT) as well, though this has no additional effect. However, it
+means that (?-aP) also implies (?-aT) and disables all ASCII restrictions for
+POSIX classes.
+
+
+Unsetting x or xx unsets both. Several options may be set at once, and a
+mixture of setting and unsetting such as (?i-x) is allowed, but there may be
+only one hyphen. Setting (but no unsetting) is allowed after (?^ for example
+(?^in). An option setting may appear at the start of a non-capture group, for
+example (?i:...).
+
+
+The following are recognized only at the very start of a pattern or after one
+of the newline or \R sequences or options with similar syntax. More than one
+of them may appear. For the first three, d is a decimal number.
+
+ (*LIMIT_DEPTH=d) set the backtracking limit to d
+ (*LIMIT_HEAP=d) set the heap size limit to d * 1024 bytes
+ (*LIMIT_MATCH=d) set the match limit to d
+ (*CASELESS_RESTRICT) set PCRE2_EXTRA_CASELESS_RESTRICT when matching
+ (*NOTEMPTY) set PCRE2_NOTEMPTY when matching
+ (*NOTEMPTY_ATSTART) set PCRE2_NOTEMPTY_ATSTART when matching
+ (*NO_AUTO_POSSESS) no auto-possessification (PCRE2_NO_AUTO_POSSESS)
+ (*NO_DOTSTAR_ANCHOR) no .* anchoring (PCRE2_NO_DOTSTAR_ANCHOR)
+ (*NO_JIT) disable JIT optimization
+ (*NO_START_OPT) no start-match optimization (PCRE2_NO_START_OPTIMIZE)
+ (*TURKISH_CASING) set PCRE2_EXTRA_TURKISH_CASING when matching
+ (*UTF) set appropriate UTF mode for the library in use
+ (*UCP) set PCRE2_UCP (use Unicode properties for \d etc)
+
+Note that LIMIT_DEPTH, LIMIT_HEAP, and LIMIT_MATCH can only reduce the value of
+the limits set by the caller of pcre2_match() or pcre2_dfa_match(),
+not increase them. LIMIT_RECURSION is an obsolete synonym for LIMIT_DEPTH. The
+application can lock out the use of (*UTF) and (*UCP) by setting the
+PCRE2_NEVER_UTF or PCRE2_NEVER_UCP options, respectively, at compile time.
+
+
+
+These are recognized only at the very start of the pattern or after option
+settings with a similar syntax.
+
+ (*CR) carriage return only
+ (*LF) linefeed only
+ (*CRLF) carriage return followed by linefeed
+ (*ANYCRLF) all three of the above
+ (*ANY) any Unicode newline sequence
+ (*NUL) the NUL character (binary zero)
+
+
+
+
+These are recognized only at the very start of the pattern or after option
+setting with a similar syntax.
+
+ (*BSR_ANYCRLF) CR, LF, or CRLF
+ (*BSR_UNICODE) any Unicode newline sequence
+
+
+
+
+
+ (?=...) )
+ (*pla:...) ) positive lookahead
+ (*positive_lookahead:...) )
+
+ (?!...) )
+ (*nla:...) ) negative lookahead
+ (*negative_lookahead:...) )
+
+ (?<=...) )
+ (*plb:...) ) positive lookbehind
+ (*positive_lookbehind:...) )
+
+ (?<!...) )
+ (*nlb:...) ) negative lookbehind
+ (*negative_lookbehind:...) )
+
+Each top-level branch of a lookbehind must have a limit for the number of
+characters it matches. If any branch can match a variable number of characters,
+the maximum for each branch is limited to a value set by the caller of
+pcre2_compile() or defaulted. The default is set when PCRE2 is built
+(ultimate default 255). If every branch matches a fixed number of characters,
+the limit for each branch is 65535 characters.
+
+
+
+These assertions are specific to PCRE2 and are not Perl-compatible.
+
+ (?*...) )
+ (*napla:...) ) synonyms
+ (*non_atomic_positive_lookahead:...) )
+
+ (?<*...) )
+ (*naplb:...) ) synonyms
+ (*non_atomic_positive_lookbehind:...) )
+
+
+
+
+This feature is not Perl-compatible.
+
+ (*scan_substring:(grouplist)...) scan captured substring
+ (*scs:(grouplist)...) scan captured substring
+
+The comma-separated list "grouplist" may identify groups in any of the
+following ways:
+
+ n absolute reference
+ +n relative reference
+ -n relative reference
+ <name> name
+ 'name' name
+
+
+
+
+
+ (*script_run:...) ) script run, can be backtracked into
+ (*sr:...) )
+
+ (*atomic_script_run:...) ) atomic script run
+ (*asr:...) )
+
+
+
+
+
+ \n reference by number (can be ambiguous)
+ \gn reference by number
+ \g{n} reference by number
+ \g+n relative reference by number (PCRE2 extension)
+ \g-n relative reference by number
+ \g{+n} relative reference by number (PCRE2 extension)
+ \g{-n} relative reference by number
+ \k<name> reference by name (Perl)
+ \k'name' reference by name (Perl)
+ \g{name} reference by name (Perl)
+ \k{name} reference by name (.NET)
+ (?P=name) reference by name (Python)
+
+
+
+
+
+ (?R) recurse whole pattern
+ (?n) call subroutine by absolute number
+ (?+n) call subroutine by relative number
+ (?-n) call subroutine by relative number
+ (?&name) call subroutine by name (Perl)
+ (?P>name) call subroutine by name (Python)
+ \g<name> call subroutine by name (Oniguruma)
+ \g'name' call subroutine by name (Oniguruma)
+ \g<n> call subroutine by absolute number (Oniguruma)
+ \g'n' call subroutine by absolute number (Oniguruma)
+ \g<+n> call subroutine by relative number (PCRE2 extension)
+ \g'+n' call subroutine by relative number (PCRE2 extension)
+ \g<-n> call subroutine by relative number (PCRE2 extension)
+ \g'-n' call subroutine by relative number (PCRE2 extension)
+
+The variants using parentheses (?...) may also specify a list of capture groups
+to return, which shall be retained in the calling subexpression if set during
+the recursion (this feature is not supported by Perl).
+
+ (?R(grouplist)) recurse whole pattern, returning capture groups
+ (PCRE2 extension)
+ (?n(grouplist)) )
+ (?+n(grouplist)) ) call subroutine, returning capture groups
+ (?-n(grouplist)) ) (PCRE2 extension)
+ (?&name(grouplist)) )
+ (?P>name(grouplist)) )
+
+The comma-separated list "grouplist" uses the same syntax as
+(*scan_substring:(grouplist)...), and may identify groups in any of the
+following ways:
+
+ n absolute reference
+ +n relative reference
+ -n relative reference
+ <name> name
+ 'name' name
+
+
+
+
+
+ (?(condition)yes-pattern)
+ (?(condition)yes-pattern|no-pattern)
+
+ (?(n) absolute reference condition
+ (?(+n) relative reference condition (PCRE2 extension)
+ (?(-n) relative reference condition (PCRE2 extension)
+ (?(<name>) named reference condition (Perl)
+ (?('name') named reference condition (Perl)
+ (?(name) named reference condition (PCRE2, deprecated)
+ (?(R) overall recursion condition
+ (?(Rn) specific numbered group recursion condition
+ (?(R&name) specific named group recursion condition
+ (?(DEFINE) define groups for reference
+ (?(VERSION[>]=n[.m]) test PCRE2 version
+ (?(assert) assertion condition
+
+Note the ambiguity of (?(R) and (?(Rn) which might be named reference
+conditions or recursion tests. Such a condition is interpreted as a reference
+condition if the relevant named group exists.
+
+
+The parts within brackets for the VERSION conditional syntax could be ommited.
+The fractional part of the version number defaults to 0 in that case.
+
+
+
+All backtracking control verbs may be in the form (*VERB:NAME). For (*MARK) the
+name is mandatory, for the others it is optional. (*SKIP) changes its behaviour
+if :NAME is present. The others just set a name for passing back to the caller,
+but this is not a name that (*SKIP) can see. The following act immediately they
+are reached:
+
+ (*ACCEPT) force successful match
+ (*FAIL) force backtrack; synonym (*F)
+ (*MARK:NAME) set name to be passed back; synonym (*:NAME)
+
+The following act only when a subsequent match failure causes a backtrack to
+reach them. They all force a match failure, but they differ in what happens
+afterwards. Those that advance the start-of-match point do so only if the
+pattern is not anchored.
+
+ (*COMMIT) overall failure, no advance of starting point
+ (*PRUNE) advance to next starting character
+ (*SKIP) advance to current matching position
+ (*SKIP:NAME) advance to position corresponding to an earlier
+ (*MARK:NAME); if not found, the (*SKIP) is ignored
+ (*THEN) local failure, backtrack to next alternation
+
+The effect of one of these verbs in a group called as a subroutine is confined
+to the subroutine call.
+
+
+
+
+ (?C) callout (assumed number 0)
+ (?Cn) callout with numerical data n
+ (?C"text") callout with string data
+
+The allowed string delimiters are ` ' " ^ % # $ (which are the same for the
+start and the end), and the starting delimiter { matched with the ending
+delimiter }. To encode the ending delimiter within the string, double it.
+
+
+
+If the PCRE2_SUBSTITUTE_LITERAL option is set, a replacement string for
+pcre2_substitute() is not interpreted. Otherwise, by default, the only
+special character is the dollar character in one of the following forms:
+
+ $$ insert a dollar character
+ $n or ${n} insert the contents of group n
+ $<name> insert the contents of named group
+ $0 or $& insert the entire matched substring
+ $` insert the substring that precedes the match
+ $' insert the substring that follows the match
+ $_ insert the entire input string
+ $+ insert the highest-numbered capture group which matched
+ $*MARK or ${*MARK} insert a control verb name
+
+For ${n}, n can be a name or a number. If PCRE2_SUBSTITUTE_EXTENDED is set,
+there is additional interpretation:
+
+
+1. Backslash is an escape character, and the forms described in "ESCAPED
+CHARACTERS" above are recognized. Also:
+
+ \Q...\E can be used to suppress interpretation
+ \l force the next character to lower case
+ \u force the next character to upper case
+ \L force subsequent characters to lower case
+ \U force subsequent characters to upper case
+ \u\L force next character to upper case, then all lower
+ \l\U force next character to lower case, then all upper
+ \E end \L or \U case forcing
+ \b backspace character (note: as in character class in pattern)
+ \v vertical tab character (note: not the same as in a pattern)
+
+2. The Python form \g<n>, where the angle brackets are part of the syntax and
+n is either a group name or a number, is recognized as an alternative way
+of inserting the contents of a group, for example \g<3>.
+
+
+3. Capture substitution supports the following additional forms:
+
+ ${n:-string} default for unset group
+ ${n:+string1:string2} values for set/unset group
+
+The substitution strings themselves are expanded. Backslash can be used to
+escape colons and closing curly brackets.
+
+
+
+pcre2pattern(3), pcre2api(3), pcre2callout(3),
+pcre2matching(3), pcre2(3).
+
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+
+Last updated: 14 October 2025
+
+Copyright © 1997-2024 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2test.html b/doc/html/pcre2test.html
new file mode 100644
index 0000000..208d660
--- /dev/null
+++ b/doc/html/pcre2test.html
@@ -0,0 +1,2314 @@
+
+
+pcre2test specification
+
+
+pcre2test man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+
+
+pcre2test [options] [input file [output file]]
+
+
+pcre2test is a test program for the PCRE2 regular expression libraries,
+but it can also be used for experimenting with regular expressions. This
+document describes the features of the test program; for details of the regular
+expressions themselves, see the
+pcre2pattern
+documentation. For details of the PCRE2 library function calls and their
+options, see the
+pcre2api
+documentation.
+
+
+The input for pcre2test is a sequence of regular expression patterns and
+subject strings to be matched. There are also command lines for setting
+defaults and controlling some special actions. The output shows the result of
+each match attempt. Modifiers on external or internal command lines, the
+patterns, and the subject lines specify PCRE2 function options, control how the
+subject is processed, and what output is produced.
+
+
+There are many obscure modifiers, some of which are specifically designed for
+use in conjunction with the test script and data files that are distributed as
+part of PCRE2. All the modifiers are documented here, some without much
+justification, but many of them are unlikely to be of use except when testing
+the libraries.
+
+
+
+Different versions of the PCRE2 library can be built to support character
+strings that are encoded in 8-bit, 16-bit, or 32-bit code units. One, two, or
+all three of these libraries may be simultaneously installed. The
+pcre2test program can be used to test all the libraries. However, its own
+input and output are always in 8-bit format. When testing the 16-bit or 32-bit
+libraries, patterns and subject strings are converted to 16-bit or 32-bit
+format before being passed to the library functions. Results are converted back
+to 8-bit code units for output.
+
+
+In the rest of this document, the names of library functions and structures
+are given in generic form, for example, pcre2_compile(). The actual
+names used in the libraries have a suffix _8, _16, or _32, as appropriate.
+
+
+
+Input to pcre2test is processed line by line, either by calling the C
+library's fgets() function, or via the libreadline or libedit
+library. In some Windows environments character 26 (hex 1A) causes an immediate
+end of file, and no further data is read, so this character should be avoided
+unless you really want that action.
+
+
+The input is processed using C's string functions, so must not contain binary
+zeros, even though in Unix-like environments, fgets() treats any bytes
+other than newline as data characters. An error is generated if a binary zero
+is encountered. By default subject lines are processed for backslash escapes,
+which makes it possible to include any data value in strings that are passed to
+the library for matching. For patterns, there is a facility for specifying some
+or all of the 8-bit input characters as hexadecimal pairs, which makes it
+possible to include binary zeros.
+
+
+Input for the 16-bit and 32-bit libraries
+
+
+When testing the 16-bit or 32-bit libraries, there is a need to be able to
+generate character code points greater than 255 in the strings that are passed
+to the library. For subject lines and some patterns, backslash escapes can be
+used. In addition, when the utf modifier (see
+"Setting compilation options"
+below) is set, the pattern and any following subject lines are interpreted as
+UTF-8 strings and translated to UTF-16 or UTF-32 as appropriate.
+
+
+For non-UTF testing of wide characters, the utf8_input modifier can be
+used. This is mutually exclusive with utf, and is allowed only in 16-bit
+or 32-bit mode. It causes the pattern and following subject lines to be treated
+as UTF-8 according to the original definition (RFC 2279), which allows for
+character values up to 0x7fffffff. Each character is placed in one 16-bit or
+32-bit code unit (in the 16-bit case, values greater than 0xffff cause an error
+to occur).
+
+
+UTF-8 (in its original definition) is not capable of encoding values greater
+than 0x7fffffff, but such values can be handled by the 32-bit library. When
+testing this library in non-UTF mode with utf8_input set, if any
+character is preceded by the byte 0xff (which is an invalid byte in UTF-8)
+0x80000000 is added to the character's value. For subject strings, using an
+escape sequence is preferable.
+
+
+
+-8
+If the 8-bit library has been built, this option causes it to be used (this is
+the default). If the 8-bit library has not been built, this option causes an
+error.
+
+
+-16
+If the 16-bit library has been built, this option causes it to be used. If the
+8-bit library has not been built, this is the default. If the 16-bit library
+has not been built, this option causes an error.
+
+
+-32
+If the 32-bit library has been built, this option causes it to be used. If no
+other library has been built, this is the default. If the 32-bit library has
+not been built, this option causes an error.
+
+
+-ac
+Behave as if each pattern has the auto_callout modifier, that is, insert
+automatic callouts into every pattern that is compiled.
+
+
+-AC
+As for -ac, but in addition behave as if each subject line has the
+callout_extra modifier, that is, show additional information from
+callouts.
+
+
+-b
+Behave as if each pattern has the fullbincode modifier; the full
+internal binary form of the pattern is output after compilation.
+
+
+-C
+Output the version number of the PCRE2 library, and all available information
+about the optional features that are included, and then exit with zero exit
+code. All other options are ignored. If both -C and -LM are present, whichever
+is first is recognized.
+
+
+-C option
+Output information about a specific build-time option, then exit. This
+functionality is intended for use in scripts such as RunTest. The
+following options output the value and set the exit code as indicated:
+
+ linksize the configured internal link size (2, 3, or 4)
+ exit code is set to the link size
+ newline the default newline setting:
+ CR, LF, CRLF, ANYCRLF, ANY, or NUL
+ exit code is always 0
+ bsr the default setting for what \R matches:
+ ANYCRLF or ANY
+ exit code is always 0
+
+The following options output 1 for true or 0 for false, and set the exit code
+to the same value:
+
+ backslash-C \C is supported (not locked out)
+ ebcdic compiled for an EBCDIC environment
+ ebcdic-io if PCRE2 is compiled for EBCDIC, whether pcre2test's input and
+ output is EBCDIC or ASCII
+ ebcdic-nl25 if PCRE2 is compiled for EBCDIC, whether NL (= LF) is 0x25
+ (otherwise it is 0x15, the default)
+ jit just-in-time support is available
+ pcre2-16 the 16-bit library was built
+ pcre2-32 the 32-bit library was built
+ pcre2-8 the 8-bit library was built
+ unicode Unicode support is available
+
+Note that the availability of JIT support in the library does not guarantee
+that it can actually be used because in some environments it is unable to
+allocate executable memory. The option "jitusable" gives more detailed
+information. It returns one of the following values:
+
+ 0 JIT is available and usable
+ 1 JIT is available but cannot allocate executable memory
+ 2 JIT is not available
+ 3 Unexpected return from test call to pcre2_jit_compile()
+
+If an unknown option is given, an error message is output; the exit code is 0.
+
+
+--colo[u]r[=<always,auto,never>]
+With auto, the output is coloured if the output is to a terminal. Force or
+suppress output of ANSI colour escapes with always (or no specifier
+provided) and never respectively. If no colour option is provided, the
+default is auto, unless the NO_COLOR environment variable is defined and
+non-empty.
+
+
+-d
+Behave as if each pattern has the debug modifier; the internal
+form and information about the compiled pattern is output after compilation;
+-d is equivalent to -b -i.
+
+
+-dfa
+Behave as if each subject line has the dfa modifier; matching is done
+using the pcre2_dfa_match() function instead of the default
+pcre2_match().
+
+
+-E
+Run in "preprocess only" mode (similar to "gcc -E"). The "#if ... #endif"
+commands are processed, and all other lines are printed verbatim.
+
+
+-error number[,number,...]
+Call pcre2_get_error_message() for each of the error numbers in the
+comma-separated list, display the resulting messages on the standard output,
+then exit with zero exit code. The numbers may be positive or negative. This is
+a convenience facility for PCRE2 maintainers.
+
+
+-help
+Output a brief summary these options and then exit.
+
+
+-i
+Behave as if each pattern has the info modifier; information about the
+compiled pattern is given after compilation.
+
+
+-jit
+Behave as if each pattern line has the jit modifier; after successful
+compilation, each pattern is passed to the just-in-time compiler, if available.
+
+
+-jitfast
+Behave as if each pattern line has the jitfast modifier; after
+successful compilation, each pattern is passed to the just-in-time compiler, if
+available, and each subject line is passed directly to the JIT matcher via its
+"fast path".
+
+
+-jitverify
+Behave as if each pattern line has the jitverify modifier; after
+successful compilation, each pattern is passed to the just-in-time compiler, if
+available, and the use of JIT for matching is verified.
+
+
+-LM
+List modifiers: write a list of available pattern and subject modifiers to the
+standard output, then exit with zero exit code. All other options are ignored.
+If both -C and any -Lx options are present, whichever is first is recognized.
+
+
+-LP
+List properties: write a list of recognized Unicode properties to the standard
+output, then exit with zero exit code. All other options are ignored. If both
+-C and any -Lx options are present, whichever is first is recognized.
+
+
+-LS
+List scripts: write a list of recognized Unicode script names to the standard
+output, then exit with zero exit code. All other options are ignored. If both
+-C and any -Lx options are present, whichever is first is recognized.
+
+
+-malloc
+Exercise malloc() failures, by first counting the number of calls made to malloc
+during pattern compilation and matching, then re-running the compilation and
+matching that many times, exercising a failure of each malloc() call.
+
+
+-pattern modifier-list
+Behave as if each pattern line contains the given modifiers.
+
+
+-q
+Do not output the version number of pcre2test at the start of execution.
+
+
+-S size
+On Unix-like systems, set the size of the run-time stack to size
+mebibytes (units of 1024*1024 bytes).
+
+
+-subject modifier-list
+Behave as if each subject line contains the given modifiers.
+
+
+-t
+Run each compile and match many times with a timer, and output the resulting
+times per compile or match. When JIT is used, separate times are given for the
+initial compile and the JIT compile. You can control the number of iterations
+that are used for timing by following -t with a number (as a separate
+item on the command line). For example, "-t 1000" iterates 1000 times. The
+default is to iterate 500,000 times.
+
+
+-tm
+This is like -t except that it times only the matching phase, not the
+compile phase.
+
+
+-T -TM
+These behave like -t and -tm, but in addition, at the end of a run,
+the total times for all compiles and matches are output.
+
+
+-unittest
+Run a fixed set of additional tests of the PCRE2 API which are not driven by
+the test input files, and then exit.
+
+
+-version
+Output the PCRE2 version number and then exit.
+
+
+
+If pcre2test is given two filename arguments, it reads from the first and
+writes to the second. If the first name is "-", input is taken from the
+standard input. If pcre2test is given only one argument, it reads from
+that file and writes to stdout. Otherwise, it reads from stdin and writes to
+stdout.
+
+
+When pcre2test is built, a configuration option can specify that it
+should be linked with the libreadline or libedit library. When this
+is done, if the input is from a terminal, it is read using the readline()
+function. This provides line-editing and history facilities. The output from
+the -help option states whether or not readline() will be used.
+
+
+The program handles any number of tests, each of which consists of a set of
+input lines. Each set starts with a regular expression pattern, followed by any
+number of subject lines to be matched against that pattern. In between sets of
+test data, command lines that begin with # may appear. This file format, with
+some restrictions, can also be processed by the perltest.sh script that
+is distributed with PCRE2 as a means of checking that the behaviour of PCRE2
+and Perl is the same. For a specification of perltest.sh, see the
+comments near its beginning. See also the #perltest command below.
+
+
+When the input is a terminal, pcre2test prompts for each line of input,
+using "re>" to prompt for regular expression patterns, and "data>" to prompt
+for subject lines. Command lines starting with # can be entered only in
+response to the "re>" prompt.
+
+
+Each subject line is matched separately and independently. If you want to do
+multi-line matches, you have to use the \n escape sequence (or \r or \r\n,
+etc., depending on the newline setting) in a single line of input to encode the
+newline sequences. There is no limit on the length of subject lines; the input
+buffer is automatically extended if it is too small. There are replication
+features that makes it possible to generate long repetitive pattern or subject
+lines without having to supply them explicitly.
+
+
+An empty line or the end of the file signals the end of the subject lines for a
+test, at which point a new pattern or command line is expected if there is
+still input to be read.
+
+
+
+In between sets of test data, a line that begins with # is interpreted as a
+command line. If the first character is followed by white space or an
+exclamation mark, the line is treated as a comment, and ignored. Otherwise, the
+following commands are recognized:
+
+ #forbid_utf
+
+Subsequent patterns automatically have the PCRE2_NEVER_UTF and PCRE2_NEVER_UCP
+options set, which locks out the use of the PCRE2_UTF and PCRE2_UCP options and
+the use of (*UTF) and (*UCP) at the start of patterns. This command also forces
+an error if a subsequent pattern contains any occurrences of \P, \p, or \X,
+which are still supported when PCRE2_UTF is not set, but which require Unicode
+property support to be included in the library.
+
+
+This is a trigger guard that is used in test files to ensure that UTF or
+Unicode property tests are not accidentally added to files that are used when
+Unicode support is not included in the library. Setting PCRE2_NEVER_UTF and
+PCRE2_NEVER_UCP as a default can also be obtained by the use of #pattern;
+the difference is that #forbid_utf cannot be unset, and the automatic
+options are not displayed in pattern information, to avoid cluttering up test
+output.
+
+ #load <filename>
+
+This command is used to load a set of precompiled patterns from a file, as
+described in the section entitled "Saving and restoring compiled patterns"
+below.
+
+ #loadtables <filename>
+
+This command is used to load a set of binary character tables that can be
+accessed by the tables=3 qualifier. Such tables can be created by the
+pcre2_dftables program with the -b option.
+
+ #newline_default [<newline-list>]
+
+When PCRE2 is built, a default newline convention can be specified. This
+determines which characters and/or character pairs are recognized as indicating
+a newline in a pattern or subject string. The default can be overridden when a
+pattern is compiled. The standard test files contain tests of various newline
+conventions, but the majority of the tests expect a single linefeed to be
+recognized as a newline by default. Without special action the tests would fail
+when PCRE2 is compiled with either CR or CRLF as the default newline.
+
+
+The #newline_default command specifies a list of newline types that are
+acceptable as the default. The types must be one of CR, LF, CRLF, ANYCRLF,
+ANY, or NUL (in upper or lower case), for example:
+
+ #newline_default LF Any anyCRLF
+
+If the default newline is in the list, this command has no effect. Otherwise,
+except when testing the POSIX API, a newline modifier that specifies the
+first newline convention in the list (LF in the above example) is added to any
+pattern that does not already have a newline modifier. If the newline
+list is empty, the feature is turned off. This command is present in a number
+of the standard test input files.
+
+
+When the POSIX API is being tested there is no way to override the default
+newline convention, though it is possible to set the newline convention from
+within the pattern. A warning is given if the posix or posix_nosub
+modifier is used when #newline_default would set a default for the
+non-POSIX API.
+
+ #pattern <modifier-list>
+
+This command sets a default modifier list that applies to all subsequent
+patterns. Modifiers on a pattern can change these settings.
+
+ #perltest
+
+This line is used in test files that can also be processed by perltest.sh
+to confirm that Perl gives the same results as PCRE2. Subsequent tests are
+checked for the use of pcre2test features that are incompatible with the
+perltest.sh script.
+
+
+Patterns must use '/' as their delimiter, and only certain modifiers are
+supported. Comment lines, #pattern commands, and #subject commands that set or
+unset "mark" are recognized and acted on. The #perltest, #forbid_utf, and
+#newline_default commands, which are needed in the relevant pcre2test files,
+are silently ignored. All other command lines are ignored, but give a warning
+message. The #perltest command helps detect tests that are accidentally
+put in the wrong file or use the wrong delimiter. For more details of the
+perltest.sh script see the comments it contains.
+
+ #pop [<modifiers>]
+ #popcopy [<modifiers>]
+
+These commands are used to manipulate the stack of compiled patterns, as
+described in the section entitled "Saving and restoring compiled patterns"
+below.
+
+ #save <filename>
+
+This command is used to save a set of compiled patterns to a file, as described
+in the section entitled "Saving and restoring compiled patterns"
+below.
+
+ #subject <modifier-list>
+
+This command sets a default modifier list that applies to all subsequent
+subject lines. Modifiers on a subject line can change these settings.
+
+ #if CONDITION
+ ...
+ #endif
+
+If CONDITION is true, then the command is printed, and its contents are
+processed as normal, including printing the commandlines to the output. If
+CONDITION is false, then all lines between the "#if" and "#endif" are skipped
+and not printed. The CONDITION can be any of the conditions which are tested by
+the "-C" commandline option and which set pcre2test's exit code to a boolean
+value. The CONDITION may also be preceded by "!".
+
+
+
+Modifier lists are used with both pattern and subject lines. Items in a list
+are separated by commas followed by optional white space. Trailing white space
+in a modifier list is ignored. Some modifiers may be given for both patterns
+and subject lines, whereas others are valid only for one or the other. Each
+modifier has a long name, for example "anchored", and some of them must be
+followed by an equals sign and a value, for example, "offset=12". Values cannot
+contain comma characters, but may contain spaces. Modifiers that do not take
+values may be preceded by a minus sign to turn off a previous setting.
+
+
+A few of the more common modifiers can also be specified as single letters, for
+example "i" for "caseless". In documentation, following the Perl convention,
+these are written with a slash ("the /i modifier") for clarity. Abbreviated
+modifiers must all be concatenated in the first item of a modifier list. If the
+first item is not recognized as a long modifier name, it is interpreted as a
+sequence of these abbreviations. For example:
+
+ /abc/ig,newline=cr,jit=3
+
+This is a pattern line whose modifier list starts with two one-letter modifiers
+(/i and /g). The lower-case abbreviated modifiers are the same as used in Perl.
+
+
+
+A pattern line must start with one of the following characters (common symbols,
+excluding pattern meta-characters):
+
+ / ! " ' ` - = _ : ; , % & @ ~
+
+This is interpreted as the pattern's delimiter. A regular expression may be
+continued over several input lines, in which case the newline characters are
+included within it. It is possible to include the delimiter as a literal within
+the pattern by escaping it with a backslash, for example
+
+ /abc\/def/
+
+If you do this, the escape and the delimiter form part of the pattern, but
+since the delimiters are all non-alphanumeric, the inclusion of the backslash
+does not affect the pattern's interpretation. Note, however, that this trick
+does not work within \Q...\E literal bracketing because the backslash will
+itself be interpreted as a literal. If the terminating delimiter is immediately
+followed by a backslash, for example,
+
+ /abc/\
+
+a backslash is added to the end of the pattern. This is done to provide a way
+of testing the error condition that arises if a pattern finishes with a
+backslash, because
+
+ /abc\/
+
+is interpreted as the first line of a pattern that starts with "abc/", causing
+pcre2test to read the next line as a continuation of the regular expression.
+
+
+A pattern can be followed by a modifier list (details below).
+
+
+
+Before each subject line is passed to pcre2_match(),
+pcre2_dfa_match(), or pcre2_jit_match(), leading and trailing white
+space is removed, and the line is scanned for backslash escapes, unless the
+subject_literal modifier was set for the pattern. The following provide a
+means of encoding non-printing characters in a visible way:
+
+ \a alarm (BEL, \x07)
+ \b backspace (\x08)
+ \e escape (\x27)
+ \f form feed (\x0c)
+ \n newline (\x0a)
+ \N{U+hh...} unicode character (any number of hex digits)
+ \r carriage return (\x0d)
+ \t tab (\x09)
+ \v vertical tab (\x0b)
+ \ddd octal number (up to 3 octal digits); represent a single
+ code point unless larger than 255 with the 8-bit library
+ \o{dd...} octal number (any number of octal digits} representing a
+ character in UTF mode or a code point
+ \xhh hexadecimal byte (up to 2 hex digits)
+ \x{hh...} hexadecimal number (up to 8 hex digits) representing a
+ character in UTF mode or a code point
+
+Invoking \N{U+hh...} or \x{hh...} doesn't require the use of the utf
+modifier on the pattern. It is always recognized. There may be any number of
+hexadecimal digits inside the braces; invalid values provoke error messages
+but when using \N{U+hh...} with some invalid unicode characters they will
+be accepted with a warning instead.
+
+
+Note that even in UTF-8 mode, \xhh (and depending of how large, \ddd)
+describe one byte rather than one character; this makes it possible to
+construct invalid UTF-8 sequences for testing purposes. On the other hand,
+\x{hh...} is interpreted as a UTF-8 character in UTF-8 mode, only generating
+more than one byte if the value is greater than 127. To avoid the ambiguity
+it is preferred to use \N{U+hh...} when describing characters. When testing
+the 8-bit library not in UTF-8 mode, \x{hh} generates one byte for values
+that could fit on it, and causes an error for greater values.
+
+
+When testing the 16-bit library, not in UTF-16 mode, all 4-digit \x{hhhh}
+values are accepted. This makes it possible to construct invalid UTF-16
+sequences for testing purposes.
+
+
+When testing the 32-bit library, not in UTF-32 mode, all 4 to 8-digit \x{...}
+values are accepted. This makes it possible to construct invalid UTF-32
+sequences for testing purposes.
+
+
+There is a special backslash sequence that specifies replication of one or more
+characters:
+
+ \[<characters>]{<count>}
+
+This makes it possible to test long strings without having to provide them as
+part of the file. For example:
+
+ \[abc]{4}
+
+is converted to "abcabcabcabc". This feature does not support nesting. To
+include a closing square bracket in the characters, code it as \x5D.
+
+
+A backslash followed by an equals sign marks the end of the subject string and
+the start of a modifier list. For example:
+
+ abc\=notbol,notempty
+
+If the subject string is empty and \= is followed by white space, the line is
+treated as a comment line, and is not used for matching. For example:
+
+ \= This is a comment.
+ abc\= This is an invalid modifier list.
+
+A backslash followed by any other non-alphanumeric character just escapes that
+character. A backslash followed by anything else causes an error. However, if
+the very last character in the line is a backslash (and there is no modifier
+list), it is ignored. This gives a way of passing an empty line as data, since
+a real empty line terminates the data input.
+
+
+If the subject_literal modifier is set for a pattern, all subject lines
+that follow are treated as literals, with no special treatment of backslashes.
+No replication is possible, and any subject modifiers must be set as defaults
+by a #subject command.
+
+
+
+There are several types of modifier that can appear in pattern lines. Except
+where noted below, they may also be used in #pattern commands. A
+pattern's modifier list can add to or override default modifiers that were set
+by a previous #pattern command.
+
+
+Setting compilation options
+
+
+The following modifiers set options for pcre2_compile(). Most of them set
+bits in the options argument of that function, but those whose names start with
+PCRE2_EXTRA are additional options that are set in the compile context.
+Some of these options have single-letter abbreviations. There is special
+handling for /x: if a second x is present, PCRE2_EXTENDED is converted into
+PCRE2_EXTENDED_MORE as in Perl. A third appearance adds PCRE2_EXTENDED as well,
+though this makes no difference to the way pcre2_compile() behaves. See
+pcre2api
+for a description of the effects of these options.
+
+ allow_empty_class set PCRE2_ALLOW_EMPTY_CLASS
+ allow_lookaround_bsk set PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK
+ allow_surrogate_escapes set PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES
+ alt_bsux set PCRE2_ALT_BSUX
+ alt_circumflex set PCRE2_ALT_CIRCUMFLEX
+ alt_extended_class set PCRE2_ALT_EXTENDED_CLASS
+ alt_verbnames set PCRE2_ALT_VERBNAMES
+ anchored set PCRE2_ANCHORED
+ /a ascii_all set all ASCII options
+ ascii_bsd set PCRE2_EXTRA_ASCII_BSD
+ ascii_bss set PCRE2_EXTRA_ASCII_BSS
+ ascii_bsw set PCRE2_EXTRA_ASCII_BSW
+ ascii_digit set PCRE2_EXTRA_ASCII_DIGIT
+ ascii_posix set PCRE2_EXTRA_ASCII_POSIX
+ auto_callout set PCRE2_AUTO_CALLOUT
+ bad_escape_is_literal set PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL
+ /i caseless set PCRE2_CASELESS
+ /r caseless_restrict set PCRE2_EXTRA_CASELESS_RESTRICT
+ dollar_endonly set PCRE2_DOLLAR_ENDONLY
+ /s dotall set PCRE2_DOTALL
+ dupnames set PCRE2_DUPNAMES
+ endanchored set PCRE2_ENDANCHORED
+ escaped_cr_is_lf set PCRE2_EXTRA_ESCAPED_CR_IS_LF
+ /x extended set PCRE2_EXTENDED
+ /xx extended_more set PCRE2_EXTENDED_MORE
+ extra_alt_bsux set PCRE2_EXTRA_ALT_BSUX
+ firstline set PCRE2_FIRSTLINE
+ literal set PCRE2_LITERAL
+ match_line set PCRE2_EXTRA_MATCH_LINE
+ match_invalid_utf set PCRE2_MATCH_INVALID_UTF
+ match_unset_backref set PCRE2_MATCH_UNSET_BACKREF
+ match_word set PCRE2_EXTRA_MATCH_WORD
+ /m multiline set PCRE2_MULTILINE
+ never_backslash_c set PCRE2_NEVER_BACKSLASH_C
+ never_callout set PCRE2_EXTRA_NEVER_CALLOUT
+ never_ucp set PCRE2_NEVER_UCP
+ never_utf set PCRE2_NEVER_UTF
+ /n no_auto_capture set PCRE2_NO_AUTO_CAPTURE
+ no_auto_possess set PCRE2_NO_AUTO_POSSESS
+ no_bs0 set PCRE2_EXTRA_NO_BS0
+ no_dotstar_anchor set PCRE2_NO_DOTSTAR_ANCHOR
+ no_start_optimize set PCRE2_NO_START_OPTIMIZE
+ no_utf_check set PCRE2_NO_UTF_CHECK
+ python_octal set PCRE2_EXTRA_PYTHON_OCTAL
+ turkish_casing set PCRE2_EXTRA_TURKISH_CASING
+ ucp set PCRE2_UCP
+ ungreedy set PCRE2_UNGREEDY
+ use_offset_limit set PCRE2_USE_OFFSET_LIMIT
+ utf set PCRE2_UTF
+
+As well as turning on the PCRE2_UTF option, the utf modifier causes all
+non-printing characters in output strings to be printed using the \x{hh...}
+notation. Otherwise, those less than 0x100 are output in hex without the curly
+brackets. Setting utf in 16-bit or 32-bit mode also causes pattern and
+subject strings to be translated to UTF-16 or UTF-32, respectively, before
+being passed to library functions.
+
+
+The following modifiers enable or disable performance optimizations by
+calling pcre2_set_optimize() before invoking the regex compiler.
+
+ optimization_full enable all optional optimizations
+ optimization_none disable all optional optimizations
+ auto_possess auto-possessify variable quantifiers
+ auto_possess_off don't auto-possessify variable quantifiers
+ dotstar_anchor anchor patterns starting with .*
+ dotstar_anchor_off don't anchor patterns starting with .*
+ start_optimize enable pre-scan of subject string
+ start_optimize_off disable pre-scan of subject string
+
+See the
+pcre2_set_optimize
+documentation for details on these optimizations.
+
+
+Setting compilation controls
+
+
+The following modifiers affect the compilation process or request information
+about the pattern. There are single-letter abbreviations for some that are
+heavily used in the test files.
+
+ /B bincode show binary code without lengths
+ bsr=[anycrlf|unicode] specify \R handling
+ callout_info show callout information
+ convert=<options> request foreign pattern conversion
+ convert_glob_escape=c set glob escape character
+ convert_glob_separator=c set glob separator character
+ convert_length set convert buffer length
+ debug same as info,fullbincode
+ expand expand repetition syntax in pattern
+ framesize show matching frame size
+ fullbincode show binary code with lengths
+ /I info show info about compiled pattern
+ hex unquoted characters are hexadecimal
+ jit[=<number>] use JIT
+ jitfast use JIT fast path
+ jitverify verify JIT use
+ locale=<name> use this locale
+ max_pattern_compiled ) set maximum compiled pattern
+ _length=<n> ) length (bytes)
+ max_pattern_length=<n> set maximum pattern length (code units)
+ max_varlookbehind=<n> set maximum variable lookbehind length
+ memory show memory used
+ newline=<type> set newline type
+ null_context compile with a NULL context
+ null_pattern pass pattern as NULL
+ parens_nest_limit=<n> set maximum parentheses depth
+ posix use the POSIX API
+ posix_nosub use the POSIX API with REG_NOSUB
+ push push compiled pattern onto the stack
+ pushcopy push a copy onto the stack
+ pushtablescopy push a copy with tables onto the stack
+ stackguard=<number> test the stackguard feature
+ subject_literal treat all subject lines as literal
+ tables=[0|1|2|3] select internal tables
+ use_length do not zero-terminate the pattern
+ utf8_input treat input as UTF-8
+
+The effects of these modifiers are described in the following sections.
+
+
+Newline and \R handling
+
+
+The bsr modifier specifies what \R in a pattern should match. If it is
+set to "anycrlf", \R matches CR, LF, or CRLF only. If it is set to "unicode",
+\R matches any Unicode newline sequence. The default can be specified when
+PCRE2 is built; if it is not, the default is set to Unicode.
+
+
+The newline modifier specifies which characters are to be interpreted as
+newlines, both in the pattern and in subject lines. The type must be one of CR,
+LF, CRLF, ANYCRLF, ANY, or NUL (in upper or lower case).
+
+
+Information about a pattern
+
+
+The debug modifier is a shorthand for info,fullbincode, requesting
+all available information.
+
+
+The bincode modifier causes a representation of the compiled code to be
+output after compilation. This information does not contain length and offset
+values, which ensures that the same output is generated for different internal
+link sizes and different code unit widths. By using bincode, the same
+regression tests can be used in different environments.
+
+
+The fullbincode modifier, by contrast, does include length and
+offset values. This is used in a few special tests that run only for specific
+code unit widths and link sizes, and is also useful for one-off tests.
+
+
+The info modifier requests information about the compiled pattern
+(whether it is anchored, has a fixed first character, and so on). The
+information is obtained from the pcre2_pattern_info() function. Here are
+some typical examples:
+
+ re> /(?i)(^a|^b)/m,info
+ Capture group count = 1
+ Compile options: multiline
+ Overall options: caseless multiline
+ First code unit at start or follows newline
+ Subject length lower bound = 1
+
+ re> /(?i)abc/info
+ Capture group count = 0
+ Compile options: <none>
+ Overall options: caseless
+ First code unit = 'a' (caseless)
+ Last code unit = 'c' (caseless)
+ Subject length lower bound = 3
+
+"Compile options" are those specified by modifiers; "overall options" have
+added options that are taken or deduced from the pattern. If both sets of
+options are the same, just a single "options" line is output; if there are no
+options, the line is omitted. "First code unit" is where any match must start;
+if there is more than one they are listed as "starting code units". "Last code
+unit" is the last literal code unit that must be present in any match. This is
+not necessarily the last character. These lines are omitted if no starting or
+ending code units are recorded. The subject length line is omitted when
+no_start_optimize is set because the minimum length is not calculated
+when it can never be used.
+
+
+The framesize modifier shows the size, in bytes, of each storage frame
+used by pcre2_match() for handling backtracking. The size depends on the
+number of capturing parentheses in the pattern. A vector of these frames is
+used at matching time; its overall size is shown when the heapframes_size
+subject modifier is set.
+
+
+The callout_info modifier requests information about all the callouts in
+the pattern. A list of them is output at the end of any other information that
+is requested. For each callout, either its number or string is given, followed
+by the item that follows it in the pattern.
+
+
+Passing a NULL context
+
+
+Normally, pcre2test passes a context block to pcre2_compile(). If
+the null_context modifier is set, however, NULL is passed. This is for
+testing that pcre2_compile() behaves correctly in this case (it uses
+default values).
+
+
+Passing a NULL pattern
+
+
+The null_pattern modifier is for testing the behaviour of
+pcre2_compile() when the pattern argument is NULL. The length value
+passed is the default PCRE2_ZERO_TERMINATED unless use_length is set.
+Any length other than zero causes an error.
+
+
+Specifying pattern characters in hexadecimal
+
+
+The hex modifier specifies that the characters of the pattern, except for
+substrings enclosed in single or double quotes, are to be interpreted as pairs
+of hexadecimal digits. This feature is provided as a way of creating patterns
+that contain binary zeros and other non-printing characters. White space is
+permitted between pairs of digits. For example, this pattern contains three
+characters:
+
+ /ab 32 59/hex
+
+Parts of such a pattern are taken literally if quoted. This pattern contains
+nine characters, only two of which are specified in hexadecimal:
+
+ /ab "literal" 32/hex
+
+Either single or double quotes may be used. There is no way of including
+the delimiter within a substring. The hex and expand modifiers are
+mutually exclusive.
+
+
+Specifying the pattern's length
+
+
+By default, patterns are passed to the compiling functions as zero-terminated
+strings but can be passed by length instead of being zero-terminated. The
+use_length modifier causes this to happen. Using a length happens
+automatically (whether or not use_length is set) when hex is set,
+because patterns specified in hexadecimal may contain binary zeros.
+
+
+If hex or use_length is used with the POSIX wrapper API (see
+"Using the POSIX wrapper API"
+below), the REG_PEND extension is used to pass the pattern's length.
+
+
+Specifying a maximum for variable lookbehinds
+
+
+Variable lookbehind assertions are supported only if, for each one, there is a
+maximum length (in characters) that it can match. There is a limit on this,
+whose default can be set at build time, with an ultimate default of 255. The
+max_varlookbehind modifier uses the pcre2_set_max_varlookbehind()
+function to change the limit. Lookbehinds whose branches each match a fixed
+length are limited to 65535 characters per branch.
+
+
+Specifying wide characters in 16-bit and 32-bit modes
+
+
+In 16-bit and 32-bit modes, all input is automatically treated as UTF-8 and
+translated to UTF-16 or UTF-32 when the utf modifier is set. For testing
+the 16-bit and 32-bit libraries in non-UTF mode, the utf8_input modifier
+can be used. It is mutually exclusive with utf. Input lines are
+interpreted as UTF-8 as a means of specifying wide characters. More details are
+given in
+"Input encoding"
+above.
+
+
+Generating long repetitive patterns
+
+
+Some tests use long patterns that are very repetitive. Instead of creating a
+very long input line for such a pattern, you can use a special repetition
+feature, similar to the one described for subject lines above. If the
+expand modifier is present on a pattern, parts of the pattern that have
+the form
+
+ \[<characters>]{<count>}
+
+are expanded before the pattern is passed to pcre2_compile(). For
+example, \[AB]{6000} is expanded to "ABAB..." 6000 times. This construction
+cannot be nested. An initial "\[" sequence is recognized only if "]{" followed
+by decimal digits and "}" is found later in the pattern. If not, the characters
+remain in the pattern unaltered. The expand and hex modifiers are
+mutually exclusive.
+
+
+If part of an expanded pattern looks like an expansion, but is really part of
+the actual pattern, unwanted expansion can be avoided by giving two values in
+the quantifier. For example, \[AB]{6000,6000} is not recognized as an
+expansion item.
+
+
+If the info modifier is set on an expanded pattern, the result of the
+expansion is included in the information that is output.
+
+
+JIT compilation
+
+
+Just-in-time (JIT) compiling is a heavyweight optimization that can greatly
+speed up pattern matching. See the
+pcre2jit
+documentation for details. JIT compiling happens, optionally, after a pattern
+has been successfully compiled into an internal form. The JIT compiler converts
+this to optimized machine code. It needs to know whether the match-time options
+PCRE2_PARTIAL_HARD and PCRE2_PARTIAL_SOFT are going to be used, because
+different code is generated for the different cases. See the partial
+modifier in "Subject Modifiers"
+below
+for details of how these options are specified for each match attempt.
+
+
+JIT compilation is requested by the jit pattern modifier, which may
+optionally be followed by an equals sign and a number in the range 0 to 7.
+The three bits that make up the number specify which of the three JIT operating
+modes are to be compiled:
+
+ 1 compile JIT code for non-partial matching
+ 2 compile JIT code for soft partial matching
+ 4 compile JIT code for hard partial matching
+
+The possible values for the jit modifier are therefore:
+
+ 0 disable JIT
+ 1 normal matching only
+ 2 soft partial matching only
+ 3 normal and soft partial matching
+ 4 hard partial matching only
+ 6 soft and hard partial matching only
+ 7 all three modes
+
+If no number is given, 7 is assumed. The phrase "partial matching" means a call
+to pcre2_match() with either the PCRE2_PARTIAL_SOFT or the
+PCRE2_PARTIAL_HARD option set. Note that such a call may return a complete
+match; the options enable the possibility of a partial match, but do not
+require it. Note also that if you request JIT compilation only for partial
+matching (for example, jit=2) but do not set the partial modifier on a
+subject line, that match will not use JIT code because none was compiled for
+non-partial matching.
+
+
+If JIT compilation is successful, the compiled JIT code will automatically be
+used when an appropriate type of match is run, except when incompatible
+run-time options are specified. For more details, see the
+pcre2jit
+documentation. See also the jitstack modifier below for a way of
+setting the size of the JIT stack.
+
+
+If the jitfast modifier is specified, matching is done using the JIT
+"fast path" interface, pcre2_jit_match(), which skips some of the sanity
+checks that are done by pcre2_match(), and of course does not work when
+JIT is not supported. If jitfast is specified without jit, jit=7 is
+assumed.
+
+
+If the jitverify modifier is specified, information about the compiled
+pattern shows whether JIT compilation was or was not successful. If
+jitverify is specified without jit, jit=7 is assumed. If JIT
+compilation is successful when jitverify is set, the text "(JIT)" is
+added to the first output line after a match or non match when JIT-compiled
+code was actually used in the match.
+
+
+Setting a locale
+
+
+The locale modifier must specify the name of a locale, for example:
+
+ /pattern/locale=fr_FR
+
+The given locale is set, pcre2_maketables() is called to build a set of
+character tables for the locale, and this is then passed to
+pcre2_compile() when compiling the regular expression. The same tables
+are used when matching the following subject lines. The locale modifier
+applies only to the pattern on which it appears, but can be given in a
+#pattern command if a default is needed. Setting a locale and alternate
+character tables are mutually exclusive.
+
+
+Showing pattern memory
+
+
+The memory modifier causes the size in bytes of the memory used to hold
+the compiled pattern to be output. This does not include the size of the
+pcre2_code block; it is just the actual compiled data. If the pattern is
+subsequently passed to the JIT compiler, the size of the JIT compiled code is
+also output. Here is an example:
+
+ re> /a(b)c/jit,memory
+ Memory allocation (code space): 21
+ Memory allocation (JIT code): 1910
+
+
+
+
+Limiting nested parentheses
+
+
+The parens_nest_limit modifier sets a limit on the depth of nested
+parentheses in a pattern. Breaching the limit causes a compilation error.
+The default for the library is set when PCRE2 is built, but pcre2test
+sets its own default of 220, which is required for running the standard test
+suite.
+
+
+Limiting the pattern length
+
+
+The max_pattern_length modifier sets a limit, in code units, to the
+length of pattern that pcre2_compile() will accept. Breaching the limit
+causes a compilation error. The default is the largest number a PCRE2_SIZE
+variable can hold (essentially unlimited).
+
+
+Limiting the size of a compiled pattern
+
+
+The max_pattern_compiled_length modifier sets a limit, in bytes, to the
+amount of memory used by a compiled pattern. Breaching the limit causes a
+compilation error. The default is the largest number a PCRE2_SIZE variable can
+hold (essentially unlimited).
+
+
+Using the POSIX wrapper API
+
+
+The posix and posix_nosub modifiers cause pcre2test to call
+PCRE2 via the POSIX wrapper API rather than its native API. When
+posix_nosub is used, the POSIX option REG_NOSUB is passed to
+regcomp(). The POSIX wrapper supports only the 8-bit library. Note that
+it does not imply POSIX matching semantics; for more detail see the
+pcre2posix
+documentation. The following pattern modifiers set options for the
+regcomp() function:
+
+ caseless REG_ICASE
+ multiline REG_NEWLINE
+ dotall REG_DOTALL )
+ ungreedy REG_UNGREEDY ) These options are not part of
+ ucp REG_UCP ) the POSIX standard
+ utf REG_UTF8 )
+
+The regerror_buffsize modifier specifies a size for the error buffer that
+is passed to regerror() in the event of a compilation error. For example:
+
+ /abc/posix,regerror_buffsize=20
+
+This provides a means of testing the behaviour of regerror() when the
+buffer is too small for the error message. If this modifier has not been set, a
+large buffer is used.
+
+
+The aftertext and allaftertext subject modifiers work as described
+below. All other modifiers are either ignored, with a warning message, or cause
+an error.
+
+
+The pattern is passed to regcomp() as a zero-terminated string by
+default, but if the use_length or hex modifiers are set, the
+REG_PEND extension is used to pass it by length.
+
+
+Testing the stack guard feature
+
+
+The stackguard modifier is used to test the use of
+pcre2_set_compile_recursion_guard(), a function that is provided to
+enable stack availability to be checked during compilation (see the
+pcre2api
+documentation for details). If the number specified by the modifier is greater
+than zero, pcre2_set_compile_recursion_guard() is called to set up
+callback from pcre2_compile() to a local function. The argument it
+receives is the current nesting parenthesis depth; if this is greater than the
+value given by the modifier, non-zero is returned, causing the compilation to
+be aborted.
+
+
+Using alternative character tables
+
+
+The value specified for the tables modifier must be one of the digits 0,
+1, 2, or 3. It causes a specific set of built-in character tables to be passed
+to pcre2_compile(). This is used in the PCRE2 tests to check behaviour
+with different character tables. The digit specifies the tables as follows:
+
+ 0 do not pass any special character tables
+ 1 the default ASCII tables, as distributed in
+ pcre2_chartables.c.dist
+ 2 a set of tables defining ISO 8859 characters
+ 3 a set of tables loaded by the #loadtables command
+
+In tables 2, some characters whose codes are greater than 128 are identified as
+letters, digits, spaces, etc. Tables 3 can be used only after a
+#loadtables command has loaded them from a binary file. Setting alternate
+character tables and a locale are mutually exclusive.
+
+
+Setting certain match controls
+
+
+The following modifiers are really subject modifiers, and are described under
+"Subject Modifiers" below. However, they may be included in a pattern's
+modifier list, in which case they are applied to every subject line that is
+processed with that pattern. These modifiers do not affect the compilation
+process.
+
+ aftertext show text after match
+ allaftertext show text after captures
+ allcaptures show all captures
+ allvector show the entire ovector
+ allusedtext show all consulted text
+ altglobal alternative global matching
+ /g global global matching
+ heapframes_size show match data heapframes size
+ jitstack=<n> set size of JIT stack
+ mark show mark values
+ null_substitute_match_data substitute with NULL match data
+ replace=<str> specify a replacement string
+ startchar show starting character when relevant
+ substitute_callout use substitution callouts
+ substitute_case_callout use substitution case callouts
+ substitute_extended use PCRE2_SUBSTITUTE_EXTENDED
+ substitute_literal use PCRE2_SUBSTITUTE_LITERAL
+ substitute_matched use PCRE2_SUBSTITUTE_MATCHED
+ substitute_overflow_length use PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_replacement_only use PCRE2_SUBSTITUTE_REPLACEMENT_ONLY
+ substitute_skip=<n> skip substitution <n>
+ substitute_stop=<n> skip substitution <n> and following
+ substitute_unknown_unset use PCRE2_SUBSTITUTE_UNKNOWN_UNSET
+ substitute_unset_empty use PCRE2_SUBSTITUTE_UNSET_EMPTY
+
+These modifiers may not appear in a #pattern command. If you want them as
+defaults, set them in a #subject command.
+
+
+Specifying literal subject lines
+
+
+If the subject_literal modifier is present on a pattern, all the subject
+lines that it matches are taken as literal strings, with no interpretation of
+backslashes. It is not possible to set subject modifiers on such lines, but any
+that are set as defaults by a #subject command are recognized.
+
+
+Saving a compiled pattern
+
+
+When a pattern with the push modifier is successfully compiled, it is
+pushed onto a stack of compiled patterns, and pcre2test expects the next
+line to contain a new pattern (or a command) instead of a subject line. This
+facility is used when saving compiled patterns to a file, as described in the
+section entitled "Saving and restoring compiled patterns"
+below.
+If pushcopy is used instead of push, a copy of the compiled
+pattern is stacked, leaving the original as current, ready to match the
+following input lines. This provides a way of testing the
+pcre2_code_copy() function.
+The push and pushcopy modifiers are incompatible with compilation
+modifiers such as global that act at match time. Any that are specified
+are ignored (for the stacked copy), with a warning message, except for
+replace, which causes an error. Note that jitverify, which is
+allowed, does not carry through to any subsequent matching that uses a stacked
+pattern.
+
+
+Testing foreign pattern conversion
+
+
+The experimental foreign pattern conversion functions in PCRE2 can be tested by
+setting the convert modifier. Its argument is a colon-separated list of
+options, which set the equivalent option for the pcre2_pattern_convert()
+function:
+
+ glob PCRE2_CONVERT_GLOB
+ glob_no_starstar PCRE2_CONVERT_GLOB_NO_STARSTAR
+ glob_no_wild_separator PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR
+ posix_basic PCRE2_CONVERT_POSIX_BASIC
+ posix_extended PCRE2_CONVERT_POSIX_EXTENDED
+ unset Unset all options
+
+The "unset" value is useful for turning off a default that has been set by a
+#pattern command. When one of these options is set, the input pattern is
+passed to pcre2_pattern_convert(). If the conversion is successful, the
+result is reflected in the output and then passed to pcre2_compile(). The
+normal utf and no_utf_check options, if set, cause the
+PCRE2_CONVERT_UTF and PCRE2_CONVERT_NO_UTF_CHECK options to be passed to
+pcre2_pattern_convert().
+
+
+By default, the conversion function is allowed to allocate a buffer for its
+output. However, if the convert_length modifier is set to a value greater
+than zero, pcre2test passes a buffer of the given length. This makes it
+possible to test the length check.
+
+
+The convert_glob_escape and convert_glob_separator modifiers can be
+used to specify the escape and separator characters for glob processing,
+overriding the defaults, which are operating-system dependent.
+
+
+
+The modifiers that can appear in subject lines and the #subject
+command are of two types.
+
+
+Setting match options
+
+
+The following modifiers set options for pcre2_match() or
+pcre2_dfa_match(). See
+pcre2api
+for a description of their effects.
+
+ anchored set PCRE2_ANCHORED
+ copy_matched_subject set PCRE2_COPY_MATCHED_SUBJECT
+ endanchored set PCRE2_ENDANCHORED
+ dfa_restart set PCRE2_DFA_RESTART
+ dfa_shortest set PCRE2_DFA_SHORTEST
+ disable_recurseloop_check set PCRE2_DISABLE_RECURSELOOP_CHECK
+ no_jit set PCRE2_NO_JIT
+ no_utf_check set PCRE2_NO_UTF_CHECK
+ notbol set PCRE2_NOTBOL
+ notempty set PCRE2_NOTEMPTY
+ notempty_atstart set PCRE2_NOTEMPTY_ATSTART
+ noteol set PCRE2_NOTEOL
+ partial_hard (or ph) set PCRE2_PARTIAL_HARD
+ partial_soft (or ps) set PCRE2_PARTIAL_SOFT
+
+The partial matching modifiers are provided with abbreviations because they
+appear frequently in tests.
+
+
+If the posix or posix_nosub modifier was present on the pattern,
+causing the POSIX wrapper API to be used, the only option-setting modifiers
+that have any effect are notbol, notempty, and noteol,
+causing REG_NOTBOL, REG_NOTEMPTY, and REG_NOTEOL, respectively, to be passed to
+regexec(). The other modifiers are ignored, with a warning message.
+
+
+There is one additional modifier that can be used with the POSIX wrapper. It is
+ignored (with a warning) if used for non-POSIX matching.
+
+ posix_startend=<n>[:<m>]
+
+This causes the subject string to be passed to regexec() using the
+REG_STARTEND option, which uses offsets to specify which part of the string is
+searched. If only one number is given, the end offset is passed as the end of
+the subject string. For more detail of REG_STARTEND, see the
+pcre2posix
+documentation. If the subject string contains binary zeros (coded as escapes
+such as \x{00} because pcre2test does not support actual binary zeros in
+its input), you must use posix_startend to specify its length.
+
+
+Setting match controls
+
+
+The following modifiers affect the matching process or request additional
+information. Some of them may also be specified on a pattern line (see above),
+in which case they apply to every subject line that is matched against that
+pattern, but can be overridden by modifiers on the subject.
+
+ aftertext show text after match
+ allaftertext show text after captures
+ allcaptures show all captures
+ allusedtext show all consulted text (non-JIT only)
+ allvector show the entire ovector
+ altglobal alternative global matching
+ callout_capture show captures at callout time
+ callout_data=<n> set a value to pass via callouts
+ callout_error=<n>[:<m>] control callout error
+ callout_extra show extra callout information
+ callout_fail=<n>[:<m>] control callout failure
+ callout_no_where do not show position of a callout
+ callout_none do not supply a callout function
+ copy=<number or name> copy captured substring
+ depth_limit=<n> set a depth limit
+ dfa use pcre2_dfa_match()
+ find_limits find heap, match and depth limits
+ find_limits_noheap find match and depth limits
+ get=<number or name> extract captured substring
+ getall extract all captured substrings
+ /g global global matching
+ heapframes_size show match data heapframes size
+ heap_limit=<n> set a limit on heap memory (Kbytes)
+ jitstack=<n> set size of JIT stack
+ mark show mark values
+ match_limit=<n> set a match limit
+ memory show heap memory usage
+ null_context match with a NULL context
+ null_replacement substitute with NULL replacement
+ null_subject match with NULL subject
+ null_substitute_match_data substitute with NULL match data
+ offset=<n> set starting offset
+ offset_limit=<n> set offset limit
+ ovector=<n> set size of output vector
+ recursion_limit=<n> obsolete synonym for depth_limit
+ replace=<str> specify a replacement string
+ startchar show startchar when relevant
+ startoffset=<n> same as offset=<n>
+ substitute_callout use substitution callouts
+ substitute_case_callout use substitution case callouts
+ substitute_extended use PCRE2_SUBSTITUTE_EXTENDED
+ substitute_literal use PCRE2_SUBSTITUTE_LITERAL
+ substitute_matched use PCRE2_SUBSTITUTE_MATCHED
+ substitute_overflow_length use PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_replacement_only use PCRE2_SUBSTITUTE_REPLACEMENT_ONLY
+ substitute_skip=<n> skip substitution number n
+ substitute_stop=<n> skip substitution number n and greater
+ substitute_subject=<str> specify a different subject for substitution
+ substitute_unknown_unset use PCRE2_SUBSTITUTE_UNKNOWN_UNSET
+ substitute_unset_empty use PCRE2_SUBSTITUTE_UNSET_EMPTY
+ zero_terminate pass the subject as zero-terminated
+
+The effects of these modifiers are described in the following sections. When
+matching via the POSIX wrapper API, the aftertext, allaftertext,
+and ovector subject modifiers work as described below. All other
+modifiers are either ignored, with a warning message, or cause an error.
+
+
+Showing more text
+
+
+The aftertext modifier requests that as well as outputting the part of
+the subject string that matched the entire pattern, pcre2test should in
+addition output the remainder of the subject string. This is useful for tests
+where the subject contains multiple copies of the same substring. The
+allaftertext modifier requests the same action for captured substrings as
+well as the main matched substring. In each case the remainder is output on the
+following line with a plus character following the capture number.
+
+
+The allusedtext modifier requests that all the text that was consulted
+during a successful pattern match by the interpreter should be shown, for both
+full and partial matches. This feature is not supported for JIT matching, and
+if requested with JIT it is ignored (with a warning message). Setting this
+modifier affects the output if there is a lookbehind at the start of a match,
+or, for a complete match, a lookahead at the end, or if \K is used in the
+pattern. Characters that precede or follow the start and end of the actual
+match are indicated in the output by '<' or '>' characters underneath them.
+Here is an example:
+
+ re> /(?<=pqr)abc(?=xyz)/
+ data> 123pqrabcxyz456\=allusedtext
+ 0: pqrabcxyz
+ <<< >>>
+ data> 123pqrabcxy\=ph,allusedtext
+ Partial match: pqrabcxy
+ <<<
+
+The first, complete match shows that the matched string is "abc", with the
+preceding and following strings "pqr" and "xyz" having been consulted during
+the match (when processing the assertions). The partial match can indicate only
+the preceding string.
+
+
+The startchar modifier requests that the starting character for the match
+be indicated, if it is different to the start of the matched string. The only
+time when this occurs is when \K has been processed as part of the match. In
+this situation, the output for the matched string is displayed from the
+starting character instead of from the match point, with circumflex characters
+under the earlier characters. For example:
+
+ re> /abc\Kxyz/
+ data> abcxyz\=startchar
+ 0: abcxyz
+ ^^^
+
+Unlike allusedtext, the startchar modifier can be used with JIT.
+However, these two modifiers are mutually exclusive.
+
+
+Showing the value of all capture groups
+
+
+The allcaptures modifier requests that the values of all potential
+captured parentheses be output after a match. By default, only those up to the
+highest one actually used in the match are output (corresponding to the return
+code from pcre2_match()). Groups that did not take part in the match
+are output as "<unset>". This modifier is not relevant for DFA matching (which
+does no capturing) and does not apply when replace is specified; it is
+ignored, with a warning message, if present.
+
+
+Showing the entire ovector, for all outcomes
+
+
+The allvector modifier requests that the entire ovector be shown,
+whatever the outcome of the match. Compare allcaptures, which shows only
+up to the maximum number of capture groups for the pattern, and then only for a
+successful complete non-DFA match. This modifier, which acts after any match
+result, and also for DFA matching, provides a means of checking that there are
+no unexpected modifications to ovector fields. Before each match attempt, the
+ovector is filled with a special value, and if this is found in both elements
+of a capturing pair, "<unchanged>" is output. After a successful match, this
+applies to all groups after the maximum capture group for the pattern. In other
+cases it applies to the entire ovector. After a partial match, the first two
+elements are the only ones that should be set. After a DFA match, the amount of
+ovector that is used depends on the number of matches that were found.
+
+
+Testing pattern callouts
+
+
+A callout function is supplied when pcre2test calls the library matching
+functions, unless callout_none is specified. Its behaviour can be
+controlled by various modifiers listed above whose names begin with
+callout_. Details are given in the section entitled "Callouts"
+below.
+Testing callouts from pcre2_substitute() is described separately in
+"Testing the substitution function"
+below.
+
+
+Finding all matches in a string
+
+
+Searching for all possible matches within a subject can be requested by the
+global or altglobal modifier. After finding a match, the matching
+function is called again to search the remainder of the subject. The difference
+between global and altglobal is that the former uses the
+start_offset argument to pcre2_match() or pcre2_dfa_match()
+to start searching at a new point within the entire string (which is what Perl
+does), whereas the latter passes over a shortened subject. This makes a
+difference to the matching process if the pattern begins with a lookbehind
+assertion (including \b or \B).
+
+
+If an empty string is matched, the next match is done with the
+PCRE2_NOTEMPTY_ATSTART flag set, in order to search for another, non-empty,
+match at the same point in the subject. This imitates the way Perl handles such
+cases when using the /g modifier or the split() function.
+
+
+Testing substring extraction functions
+
+
+The copy and get modifiers can be used to test the
+pcre2_substring_copy_xxx() and pcre2_substring_get_xxx() functions.
+They can be given more than once, and each can specify a capture group name or
+number, for example:
+
+ abcd\=copy=1,copy=3,get=G1
+
+If the #subject command is used to set default copy and/or get lists,
+these can be unset by specifying a negative number to cancel all numbered
+groups and an empty name to cancel all named groups.
+
+
+The getall modifier tests pcre2_substring_list_get(), which
+extracts all captured substrings.
+
+
+If the subject line is successfully matched, the substrings extracted by the
+convenience functions are output with C, G, or L after the string number
+instead of a colon. This is in addition to the normal full list. The string
+length (that is, the return from the extraction function) is given in
+parentheses after each substring, followed by the name when the extraction was
+by name.
+
+
+Testing the substitution function
+
+
+If the replace modifier is set, the pcre2_substitute() function is
+called instead of one of the matching functions (or after one call of
+pcre2_match() in the case of PCRE2_SUBSTITUTE_MATCHED). Note that
+replacement strings cannot contain commas, because a comma signifies the end of
+a modifier. This is not thought to be an issue in a test program.
+
+
+Specifying a completely empty replacement string disables this modifier.
+However, it is possible to specify an empty replacement by providing a buffer
+length, as described below, for an otherwise empty replacement.
+
+
+Unlike subject strings, pcre2test does not process replacement strings
+for escape sequences. In UTF mode, a replacement string is checked to see if it
+is a valid UTF-8 string. If so, it is correctly converted to a UTF string of
+the appropriate code unit width. If it is not a valid UTF-8 string, the
+individual code units are copied directly. This provides a means of passing an
+invalid UTF-8 string for testing purposes.
+
+
+The following modifiers set options (in additional to the normal match options)
+for pcre2_substitute():
+
+ global PCRE2_SUBSTITUTE_GLOBAL
+ substitute_extended PCRE2_SUBSTITUTE_EXTENDED
+ substitute_literal PCRE2_SUBSTITUTE_LITERAL
+ substitute_matched PCRE2_SUBSTITUTE_MATCHED
+ substitute_overflow_length PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_replacement_only PCRE2_SUBSTITUTE_REPLACEMENT_ONLY
+ substitute_unknown_unset PCRE2_SUBSTITUTE_UNKNOWN_UNSET
+ substitute_unset_empty PCRE2_SUBSTITUTE_UNSET_EMPTY
+
+See the
+pcre2api
+documentation for details of these options.
+
+
+After a successful substitution, the modified string is output, preceded by the
+number of replacements. This may be zero if there were no matches. Here is a
+simple example of a substitution test:
+
+ /abc/replace=xxx
+ =abc=abc=
+ 1: =xxx=abc=
+ =abc=abc=\=global
+ 2: =xxx=xxx=
+
+Subject and replacement strings should be kept relatively short (fewer than 256
+characters) for substitution tests, as fixed-size buffers are used. To make it
+easy to test for buffer overflow, if the replacement string starts with a
+number in square brackets, that number is passed to pcre2_substitute() as
+the size of the output buffer, with the replacement string starting at the next
+character. Here is an example that tests the edge case:
+
+ /abc/
+ 123abc123\=replace=[10]XYZ
+ 1: 123XYZ123
+ 123abc123\=replace=[9]XYZ
+ Failed: error -48: no more memory
+
+The default action of pcre2_substitute() is to return
+PCRE2_ERROR_NOMEMORY when the output buffer is too small. However, if the
+PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option is set (by using the
+substitute_overflow_length modifier), pcre2_substitute() continues
+to go through the motions of matching and substituting (but not doing any
+callouts), in order to compute the size of buffer that is required. When this
+happens, pcre2test shows the required buffer length (which includes space
+for the trailing zero) as part of the error message. For example:
+
+ /abc/substitute_overflow_length
+ 123abc123\=replace=[9]XYZ
+ Failed: error -48: no more memory: 10 code units are needed
+
+A replacement string is ignored with POSIX and DFA matching. Specifying partial
+matching provokes an error return ("bad option value") from
+pcre2_substitute().
+
+
+The substitute_subject modifier may be used to test the use of the PCRE2
+API, in which a client calls pcre2_match() followed by pcre2_substitute()
+with PCRE2_SUBSTITUTE_MATCHED, but the client performs an unexpected and
+unsupported modification of the subject buffer in-place, in between the match
+and substitution.
+
+
+Testing substitute callouts
+
+
+If the substitute_callout modifier is set, a substitution callout
+function is set up. The null_context modifier must not be set, because
+the address of the callout function is passed in a match context. When the
+callout function is called (after each substitution), details of the input
+and output strings are output. For example:
+
+ /abc/g,replace=<$0>,substitute_callout
+ abcdefabcpqr
+ 1(1) Old 0 3 "abc" New 0 5 "<abc>"
+ 2(1) Old 6 9 "abc" New 8 13 "<abc>"
+ 2: <abc>def<abc>pqr
+
+The first number on each callout line is the count of matches. The
+parenthesized number is the number of pairs that are set in the ovector (that
+is, one more than the number of capturing groups that were set). Then are
+listed the offsets of the old substring, its contents, and the same for the
+replacement.
+
+
+By default, the substitution callout function returns zero, which accepts the
+replacement and causes matching to continue if /g was used. Two further
+modifiers can be used to test other return values. If substitute_skip is
+set to a value greater than zero the callout function returns +1 for the match
+of that number, and similarly substitute_stop returns -1. These cause the
+replacement to be rejected, and -1 causes no further matching to take place. If
+either of them are set, substitute_callout is assumed. For example:
+
+ /abc/g,replace=<$0>,substitute_skip=1
+ abcdefabcpqr
+ 1(1) Old 0 3 "abc" New 0 5 "<abc> SKIPPED"
+ 2(1) Old 6 9 "abc" New 6 11 "<abc>"
+ 2: abcdef<abc>pqr
+ abcdefabcpqr\=substitute_stop=1
+ 1(1) Old 0 3 "abc" New 0 5 "<abc> STOPPED"
+ 1: abcdefabcpqr
+
+If both are set for the same number, stop takes precedence. Only a single skip
+or stop is supported, which is sufficient for testing that the feature works.
+
+
+Testing substitute case callouts
+
+
+If the substitute_case_callout modifier is set, a substitution
+case callout function is set up. The callout function is called for each
+substituted chunk which is to be case-transformed.
+
+
+The callout function passed is a fixed function with implementation for certain
+behaviours: inputs which shrink when case-transformed; inputs which grow; inputs
+with distinct upper/lower/titlecase forms. The characters which are not
+special-cased for testing purposes are left unmodified, as if they are caseless
+characters.
+
+
+Setting the JIT stack size
+
+
+The jitstack modifier provides a way of setting the maximum stack size
+that is used by the just-in-time optimization code. It is ignored if JIT
+optimization is not being used. The value is a number of kibibytes (units of
+1024 bytes). Setting zero reverts to the default of 32KiB. Providing a stack
+that is larger than the default is necessary only for very complicated
+patterns. If jitstack is set non-zero on a subject line it overrides any
+value that was set on the pattern.
+
+
+Setting heap, match, and depth limits
+
+
+The heap_limit, match_limit, and depth_limit modifiers set
+the appropriate limits in the match context. These values are ignored when the
+find_limits or find_limits_noheap modifier is specified.
+
+
+Finding minimum limits
+
+
+If the find_limits modifier is present on a subject line, pcre2test
+calls the relevant matching function several times, setting different values in
+the match context via pcre2_set_heap_limit(),
+pcre2_set_match_limit(), or pcre2_set_depth_limit() until it finds
+the smallest value for each parameter that allows the match to complete without
+a "limit exceeded" error. The match itself may succeed or fail. An alternative
+modifier, find_limits_noheap, omits the heap limit. This is used in the
+standard tests, because the minimum heap limit varies between systems. If JIT
+is being used, only the match limit is relevant, and the other two are
+automatically omitted.
+
+
+When using this modifier, the pattern should not contain any limit settings
+such as (*LIMIT_MATCH=...) within it. If such a setting is present and is
+lower than the minimum matching value, the minimum value cannot be found
+because pcre2_set_match_limit() etc. are only able to reduce the value of
+an in-pattern limit; they cannot increase it.
+
+
+For non-DFA matching, the minimum depth_limit number is a measure of how
+much nested backtracking happens (that is, how deeply the pattern's tree is
+searched). In the case of DFA matching, depth_limit controls the depth of
+recursive calls of the internal function that is used for handling pattern
+recursion, lookaround assertions, and atomic groups.
+
+
+For non-DFA matching, the match_limit number is a measure of the amount
+of backtracking that takes place, and learning the minimum value can be
+instructive. For most simple matches, the number is quite small, but for
+patterns with very large numbers of matching possibilities, it can become large
+very quickly with increasing length of subject string. In the case of DFA
+matching, match_limit controls the total number of calls, both recursive
+and non-recursive, to the internal matching function, thus controlling the
+overall amount of computing resource that is used.
+
+
+For both kinds of matching, the heap_limit number, which is in kibibytes
+(units of 1024 bytes), limits the amount of heap memory used for matching.
+
+
+Showing MARK names
+
+
+The mark modifier causes the names from backtracking control verbs that
+are returned from calls to pcre2_match() to be displayed. If a mark is
+returned for a match, non-match, or partial match, pcre2test shows it.
+For a match, it is on a line by itself, tagged with "MK:". Otherwise, it
+is added to the non-match message.
+
+
+Showing memory usage
+
+
+The memory modifier causes pcre2test to log the sizes of all heap
+memory allocation and freeing calls that occur during a call to
+pcre2_match() or pcre2_dfa_match(). In the latter case, heap memory
+is used only when a match requires more internal workspace that the default
+allocation on the stack, so in many cases there will be no output. No heap
+memory is allocated during matching with JIT. For this modifier to work, the
+null_context modifier must not be set on both the pattern and the
+subject, though it can be set on one or the other.
+
+
+Showing the heap frame overall vector size
+
+
+The heapframes_size modifier is relevant for matches using
+pcre2_match() without JIT. After a match has run (whether successful or
+not) the size, in bytes, of the allocated heap frames vector that is left
+attached to the match data block is shown. If the matching action involved
+several calls to pcre2_match() (for example, global matching or for
+timing) only the final value is shown.
+
+
+This modifier is ignored, with a warning, for POSIX or DFA matching. JIT
+matching does not use the heap frames vector, so the size is always zero,
+unless there was a previous non-JIT match. Note that specifing a size of zero
+for the output vector (see below) causes pcre2test to free its match data
+block (and associated heap frames vector) and allocate a new one.
+
+
+Setting a starting offset
+
+
+The offset modifier sets an offset in the subject string at which
+matching starts. Its value is a number of code units, not characters.
+
+
+Setting an offset limit
+
+
+The offset_limit modifier sets a limit for unanchored matches. If a match
+cannot be found starting at or before this offset in the subject, a "no match"
+return is given. The data value is a number of code units, not characters. When
+this modifier is used, the use_offset_limit modifier must have been set
+for the pattern; if not, an error is generated.
+
+
+Setting the size of the output vector
+
+
+The ovector modifier applies only to the subject line in which it
+appears, though of course it can also be used to set a default in a
+#subject command. It specifies the number of pairs of offsets that are
+available for storing matching information. The default is 15.
+
+
+A value of zero is useful when testing the POSIX API because it causes
+regexec() to be called with a NULL capture vector. When not testing the
+POSIX API, a value of zero is used to cause
+pcre2_match_data_create_from_pattern() to be called, in order to create a
+new match block of exactly the right size for the pattern. (It is not possible
+to create a match block with a zero-length ovector; there is always at least
+one pair of offsets.) The old match data block is freed.
+
+
+Passing the subject as zero-terminated
+
+
+By default, the subject string is passed to a native API matching function with
+its correct length. In order to test the facility for passing a zero-terminated
+string, the zero_terminate modifier is provided. It causes the length to
+be passed as PCRE2_ZERO_TERMINATED. When matching via the POSIX interface,
+this modifier is ignored, with a warning.
+
+
+When testing pcre2_substitute(), this modifier also has the effect of
+passing the replacement string as zero-terminated.
+
+
+Passing a NULL context, subject, or replacement
+
+
+Normally, pcre2test passes a context block to pcre2_match(),
+pcre2_dfa_match(), pcre2_jit_match() or pcre2_substitute().
+If the null_context modifier is set, however, NULL is passed. This is for
+testing that the matching and substitution functions behave correctly in this
+case (they use default values). This modifier cannot be used with the
+find_limits, find_limits_noheap, or substitute_callout
+modifiers.
+
+
+Similarly, for testing purposes, if the null_subject or
+null_replacement modifier is set, the subject or replacement string
+pointers are passed as NULL, respectively, to the relevant functions.
+
+
+
+By default, pcre2test uses the standard PCRE2 matching function,
+pcre2_match() to match each subject line. PCRE2 also supports an
+alternative matching function, pcre2_dfa_match(), which operates in a
+different way, and has some restrictions. The differences between the two
+functions are described in the
+pcre2matching
+documentation.
+
+
+If the dfa modifier is set, the alternative matching function is used.
+This function finds all possible matches at a given point in the subject. If,
+however, the dfa_shortest modifier is set, processing stops after the
+first match is found. This is always the shortest possible match.
+
+
+
+This section describes the output when the normal matching function,
+pcre2_match(), is being used.
+
+
+When a match succeeds, pcre2test outputs the list of captured substrings,
+starting with number 0 for the string that matched the whole pattern.
+Otherwise, it outputs "No match" when the return is PCRE2_ERROR_NOMATCH, or
+"Partial match:" followed by the partially matching substring when the
+return is PCRE2_ERROR_PARTIAL. (Note that this is the
+entire substring that was inspected during the partial match; it may include
+characters before the actual match start if a lookbehind assertion, \K, \b,
+or \B was involved.)
+
+
+For any other return, pcre2test outputs the PCRE2 negative error number
+and a short descriptive phrase. If the error is a failed UTF string check, the
+code unit offset of the start of the failing character is also output. Here is
+an example of an interactive pcre2test run.
+
+ $ pcre2test
+ PCRE2 version 10.22 2016-07-29
+
+ re> /^abc(\d+)/
+ data> abc123
+ 0: abc123
+ 1: 123
+ data> xyz
+ No match
+
+Unset capturing substrings that are not followed by one that is set are not
+shown by pcre2test unless the allcaptures modifier is specified. In
+the following example, there are two capturing substrings, but when the first
+data line is matched, the second, unset substring is not shown. An "internal"
+unset substring is shown as "<unset>", as for the second data line.
+
+ re> /(a)|(b)/
+ data> a
+ 0: a
+ 1: a
+ data> b
+ 0: b
+ 1: <unset>
+ 2: b
+
+If the strings contain any non-printing characters, they are output as \xhh
+escapes if the value is less than 256 and UTF mode is not set. Otherwise they
+are output as \x{hh...} escapes. See below for the definition of non-printing
+characters. If the aftertext modifier is set, the output for substring 0
+is followed by the rest of the subject string, identified by "0+" like this:
+
+ re> /cat/aftertext
+ data> cataract
+ 0: cat
+ 0+ aract
+
+If global matching is requested, the results of successive matching attempts
+are output in sequence, like this:
+
+ re> /\Bi(\w\w)/g
+ data> Mississippi
+ 0: iss
+ 1: ss
+ 0: iss
+ 1: ss
+ 0: ipp
+ 1: pp
+
+"No match" is output only if the first match attempt fails. Here is an example
+of a failure message (the offset 4 that is specified by the offset
+modifier is past the end of the subject string):
+
+ re> /xyz/
+ data> xyz\=offset=4
+ Error -24 (bad offset value)
+
+
+
+Note that whereas patterns can be continued over several lines (a plain ">"
+prompt is used for continuations), subject lines may not. However newlines can
+be included in a subject by means of the \n escape (or \r, \r\n, etc.,
+depending on the newline sequence setting).
+
+
+
+When the alternative matching function, pcre2_dfa_match(), is used, the
+output consists of a list of all the matches that start at the first point in
+the subject where there is at least one match. For example:
+
+ re> /(tang|tangerine|tan)/
+ data> yellow tangerine\=dfa
+ 0: tangerine
+ 1: tang
+ 2: tan
+
+Using the normal matching function on this data finds only "tang". The
+longest matching string is always given first (and numbered zero). After a
+PCRE2_ERROR_PARTIAL return, the output is "Partial match:", followed by the
+partially matching substring. Note that this is the entire substring that was
+inspected during the partial match; it may include characters before the actual
+match start if a lookbehind assertion, \b, or \B was involved. (\K is not
+supported for DFA matching.)
+
+
+If global matching is requested, the search for further matches resumes
+at the end of the longest match. For example:
+
+ re> /(tang|tangerine|tan)/g
+ data> yellow tangerine and tangy sultana\=dfa
+ 0: tangerine
+ 1: tang
+ 2: tan
+ 0: tang
+ 1: tan
+ 0: tan
+
+The alternative matching function does not support substring capture, so the
+modifiers that are concerned with captured substrings are not relevant.
+
+
+
+When the alternative matching function has given the PCRE2_ERROR_PARTIAL
+return, indicating that the subject partially matched the pattern, you can
+restart the match with additional subject data by means of the
+dfa_restart modifier. For example:
+
+ re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
+ data> 23ja\=ps,dfa
+ Partial match: 23ja
+ data> n05\=dfa,dfa_restart
+ 0: n05
+
+For further information about partial matching, see the
+pcre2partial
+documentation.
+
+
+
+If the pattern contains any callout requests, pcre2test's callout
+function is called during matching unless callout_none is specified. This
+works with both matching functions, and with JIT, though there are some
+differences in behaviour. The output for callouts with numerical arguments and
+those with string arguments is slightly different.
+
+
+Callouts with numerical arguments
+
+
+By default, the callout function displays the callout number, the start and
+current positions in the subject text at the callout time, and the next pattern
+item to be tested. For example:
+
+ --->pqrabcdef
+ 0 ^ ^ \d
+
+This output indicates that callout number 0 occurred for a match attempt
+starting at the fourth character of the subject string, when the pointer was at
+the seventh character, and when the next pattern item was \d. Just
+one circumflex is output if the start and current positions are the same, or if
+the current position precedes the start position, which can happen if the
+callout is in a lookbehind assertion.
+
+
+Callouts numbered 255 are assumed to be automatic callouts, inserted as a
+result of the auto_callout pattern modifier. In this case, instead of
+showing the callout number, the offset in the pattern, preceded by a plus, is
+output. For example:
+
+ re> /\d?[A-E]\*/auto_callout
+ data> E*
+ --->E*
+ +0 ^ \d?
+ +3 ^ [A-E]
+ +8 ^^ \*
+ +10 ^ ^
+ 0: E*
+
+If a pattern contains (*MARK) items, an additional line is output whenever
+a change of latest mark is passed to the callout function. For example:
+
+ re> /a(*MARK:X)bc/auto_callout
+ data> abc
+ --->abc
+ +0 ^ a
+ +1 ^^ (*MARK:X)
+ +10 ^^ b
+ Latest Mark: X
+ +11 ^ ^ c
+ +12 ^ ^
+ 0: abc
+
+The mark changes between matching "a" and "b", but stays the same for the rest
+of the match, so nothing more is output. If, as a result of backtracking, the
+mark reverts to being unset, the text "<unset>" is output.
+
+
+Callouts with string arguments
+
+
+The output for a callout with a string argument is similar, except that instead
+of outputting a callout number before the position indicators, the callout
+string and its offset in the pattern string are output before the reflection of
+the subject string, and the subject string is reflected for each callout. For
+example:
+
+ re> /^ab(?C'first')cd(?C"second")ef/
+ data> abcdefg
+ Callout (7): 'first'
+ --->abcdefg
+ ^ ^ c
+ Callout (20): "second"
+ --->abcdefg
+ ^ ^ e
+ 0: abcdef
+
+
+
+
+Callout modifiers
+
+
+The callout function in pcre2test returns zero (carry on matching) by
+default, but you can use a callout_fail modifier in a subject line to
+change this and other parameters of the callout (see below).
+
+
+If the callout_capture modifier is set, the current captured groups are
+output when a callout occurs. This is useful only for non-DFA matching, as
+pcre2_dfa_match() does not support capturing, so no captures are ever
+shown.
+
+
+The normal callout output, showing the callout number or pattern offset (as
+described above) is suppressed if the callout_no_where modifier is set.
+
+
+When using the interpretive matching function pcre2_match() without JIT,
+setting the callout_extra modifier causes additional output from
+pcre2test's callout function to be generated. For the first callout in a
+match attempt at a new starting position in the subject, "New match attempt" is
+output. If there has been a backtrack since the last callout (or start of
+matching if this is the first callout), "Backtrack" is output, followed by "No
+other matching paths" if the backtrack ended the previous match attempt. For
+example:
+
+ re> /(a+)b/auto_callout,no_start_optimize,no_auto_possess
+ data> aac\=callout_extra
+ New match attempt
+ --->aac
+ +0 ^ (
+ +1 ^ a+
+ +3 ^ ^ )
+ +4 ^ ^ b
+ Backtrack
+ --->aac
+ +3 ^^ )
+ +4 ^^ b
+ Backtrack
+ No other matching paths
+ New match attempt
+ --->aac
+ +0 ^ (
+ +1 ^ a+
+ +3 ^^ )
+ +4 ^^ b
+ Backtrack
+ No other matching paths
+ New match attempt
+ --->aac
+ +0 ^ (
+ +1 ^ a+
+ Backtrack
+ No other matching paths
+ New match attempt
+ --->aac
+ +0 ^ (
+ +1 ^ a+
+ No match
+
+Notice that various optimizations must be turned off if you want all possible
+matching paths to be scanned. If no_start_optimize is not used, there is
+an immediate "no match", without any callouts, because the starting
+optimization fails to find "b" in the subject, which it knows must be present
+for any match. If no_auto_possess is not used, the "a+" item is turned
+into "a++", which reduces the number of backtracks.
+
+
+The callout_extra modifier has no effect if used with the DFA matching
+function, or with JIT.
+
+
+Return values from callouts
+
+
+The default return from the callout function is zero, which allows matching to
+continue. The callout_fail modifier can be given one or two numbers. If
+there is only one number, 1 is returned instead of 0 (causing matching to
+backtrack) when a callout of that number is reached. If two numbers (<n>:<m>)
+are given, 1 is returned when callout <n> is reached and there have been at
+least <m> callouts. The callout_error modifier is similar, except that
+PCRE2_ERROR_CALLOUT is returned, causing the entire matching process to be
+aborted. If both these modifiers are set for the same callout number,
+callout_error takes precedence. Note that callouts with string arguments
+are always given the number zero.
+
+
+The callout_data modifier can be given an unsigned or a negative number.
+This is set as the "user data" that is passed to the matching function, and
+passed back when the callout function is invoked. Any value other than zero is
+used as a return from pcre2test's callout function.
+
+
+Inserting callouts can be helpful when using pcre2test to check
+complicated regular expressions. For further information about callouts, see
+the
+pcre2callout
+documentation.
+
+
+
+When pcre2test is outputting text in the compiled version of a pattern,
+bytes other than 32-126 are always treated as non-printing characters and are
+therefore shown as hex escapes.
+
+
+When pcre2test is outputting text that is a matched part of a subject
+string, it behaves in the same way, unless a different locale has been set for
+the pattern (using the locale modifier). In this case, the
+isprint() function is used to distinguish printing and non-printing
+characters.
+
+
+
+It is possible to save compiled patterns on disc or elsewhere, and reload them
+later, subject to a number of restrictions. JIT data cannot be saved. The host
+on which the patterns are reloaded must be running the same version of PCRE2,
+with the same code unit width, and must also have the same endianness, pointer
+width and PCRE2_SIZE type. Before compiled patterns can be saved they must be
+serialized, that is, converted to a stream of bytes. A single byte stream may
+contain any number of compiled patterns, but they must all use the same
+character tables. A single copy of the tables is included in the byte stream
+(its size is 1088 bytes).
+
+
+The functions whose names begin with pcre2_serialize_ are used
+for serializing and de-serializing. They are described in the
+pcre2serialize
+documentation. In this section we describe the features of pcre2test that
+can be used to test these functions.
+
+
+Note that "serialization" in PCRE2 does not convert compiled patterns to an
+abstract format like Java or .NET. It just makes a reloadable byte code stream.
+Hence the restrictions on reloading mentioned above.
+
+
+In pcre2test, when a pattern with push modifier is successfully
+compiled, it is pushed onto a stack of compiled patterns, and pcre2test
+expects the next line to contain a new pattern (or command) instead of a
+subject line. By contrast, the pushcopy modifier causes a copy of the
+compiled pattern to be stacked, leaving the original available for immediate
+matching. By using push and/or pushcopy, a number of patterns can
+be compiled and retained. These modifiers are incompatible with posix,
+and control modifiers that act at match time are ignored (with a message) for
+the stacked patterns. The jitverify modifier applies only at compile
+time.
+
+
+The command
+
+ #save <filename>
+
+causes all the stacked patterns to be serialized and the result written to the
+named file. Afterwards, all the stacked patterns are freed. The command
+
+ #load <filename>
+
+reads the data in the file, and then arranges for it to be de-serialized, with
+the resulting compiled patterns added to the pattern stack. The pattern on the
+top of the stack can be retrieved by the #pop command, which must be followed
+by lines of subjects that are to be matched with the pattern, terminated as
+usual by an empty line or end of file. This command may be followed by a
+modifier list containing only
+control modifiers
+that act after a pattern has been compiled. In particular, hex,
+posix, posix_nosub, push, and pushcopy are not allowed,
+nor are any
+option-setting modifiers.
+The JIT modifiers are, however permitted. Here is an example that saves and
+reloads two patterns.
+
+ /abc/push
+ /xyz/push
+ #save tempfile
+ #load tempfile
+ #pop info
+ xyz
+
+ #pop jit,bincode
+ abc
+
+If jitverify is used with #pop, it does not automatically imply
+jit, which is different behaviour from when it is used on a pattern.
+
+
+The #popcopy command is analogous to the pushcopy modifier in that it
+makes current a copy of the topmost stack pattern, leaving the original still
+on the stack.
+
+
+
+pcre2(3), pcre2api(3), pcre2callout(3),
+pcre2jit, pcre2matching(3), pcre2partial(d),
+pcre2pattern(3), pcre2serialize(3).
+
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+
+Last updated: 22 August 2026
+
+Copyright © 1997-2024 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/html/pcre2unicode.html b/doc/html/pcre2unicode.html
new file mode 100644
index 0000000..8c278ae
--- /dev/null
+++ b/doc/html/pcre2unicode.html
@@ -0,0 +1,556 @@
+
+
+pcre2unicode specification
+
+
+pcre2unicode man page
+
+Return to the PCRE2 index page.
+
+
+This page is part of the PCRE2 HTML documentation. It was generated
+automatically from the original man page. If there is any nonsense in it,
+please consult the man page, in case the conversion went wrong.
+
+
+UNICODE AND UTF SUPPORT
+
+
+PCRE2 is normally built with Unicode support, though if you do not need it, you
+can build it without, in which case the library will be smaller. With Unicode
+support, PCRE2 has knowledge of Unicode character properties and can process
+strings of text in UTF-8, UTF-16, and UTF-32 format (depending on the code unit
+width), but this is not the default. Unless specifically requested, PCRE2
+treats each code unit in a string as one character.
+
+
+There are two ways of telling PCRE2 to switch to UTF mode, where characters may
+consist of more than one code unit and the range of values is constrained. The
+program can call
+pcre2_compile()
+with the PCRE2_UTF option, or the pattern may start with the sequence (*UTF).
+However, the latter facility can be locked out by the PCRE2_NEVER_UTF option.
+That is, the programmer can prevent the supplier of the pattern from switching
+to UTF mode.
+
+
+Note that the PCRE2_MATCH_INVALID_UTF option (see
+below)
+forces PCRE2_UTF to be set.
+
+
+In UTF mode, both the pattern and any subject strings that are matched against
+it are treated as UTF strings instead of strings of individual one-code-unit
+characters. There are also some other changes to the way characters are
+handled, as documented below.
+
+
+UNICODE PROPERTY SUPPORT
+
+
+When PCRE2 is built with Unicode support, the escape sequences \p{..},
+\P{..}, and \X can be used. This is not dependent on the PCRE2_UTF setting.
+The Unicode properties that can be tested are a subset of those that Perl
+supports. Currently they are limited to the general category properties such as
+Lu for an upper case letter or Nd for a decimal number, the derived properties
+Any and Lc (synonym L&), the Unicode script names such as Arabic or Han,
+Bidi_Class, Bidi_Control, and a few binary properties.
+
+
+The full lists are given in the
+pcre2pattern
+and
+pcre2syntax
+documentation. In general, only the short names for properties are supported.
+For example, \p{L} matches a letter. Its longer synonym, \p{Letter}, is not
+supported. Furthermore, in Perl, many properties may optionally be prefixed by
+"Is", for compatibility with Perl 5.6. PCRE2 does not support this.
+
+
+WIDE CHARACTERS AND UTF MODES
+
+
+Code points less than 256 can be specified in patterns by either braced or
+unbraced hexadecimal escape sequences (for example, \x{b3} or \xb3). Larger
+values have to use braced sequences. Unbraced octal code points up to \777 are
+also recognized; larger ones can be coded using \o{...}.
+
+
+The escape sequence \N{U+<hex digits>} is recognized as another way of
+specifying a Unicode character by code point in a UTF mode. It is not allowed
+in non-UTF mode.
+
+
+In UTF mode, repeat quantifiers apply to complete UTF characters, not to
+individual code units.
+
+
+In UTF mode, the dot metacharacter matches one UTF character instead of a
+single code unit.
+
+
+In UTF mode, capture group names are not restricted to ASCII, and may contain
+any Unicode letters and decimal digits, as well as underscore.
+
+
+The escape sequence \C can be used to match a single code unit in UTF mode,
+but its use can lead to some strange effects because it breaks up multi-unit
+characters (see the description of \C in the
+pcre2pattern
+documentation). For this reason, there is a build-time option that disables
+support for \C completely. There is also a less draconian compile-time option
+for locking out the use of \C when a pattern is compiled.
+
+
+The use of \C is not supported by the alternative matching function
+pcre2_dfa_match() when in UTF-8 or UTF-16 mode, that is, when a character
+may consist of more than one code unit. The use of \C in these modes provokes
+a match-time error. Also, the JIT optimization does not support \C in these
+modes. If JIT optimization is requested for a UTF-8 or UTF-16 pattern that
+contains \C, it will not succeed, and so when pcre2_match() is called,
+the matching will be carried out by the interpretive function.
+
+
+The character escapes \b, \B, \d, \D, \s, \S, \w, and \W correctly test
+characters of any code value, but, by default, the characters that PCRE2
+recognizes as digits, spaces, or word characters remain the same set as in
+non-UTF mode, all with code points less than 256. This remains true even when
+PCRE2 is built to include Unicode support, because to do otherwise would slow
+down matching in many common cases. Note that this also applies to \b
+and \B, because they are defined in terms of \w and \W. If you want
+to test for a wider sense of, say, "digit", you can use explicit Unicode
+property tests such as \p{Nd}. Alternatively, if you set the PCRE2_UCP option,
+the way that the character escapes work is changed so that Unicode properties
+are used to determine which characters match, though there are some options
+that suppress this for individual escapes. For details see the section on
+generic character types
+in the
+pcre2pattern
+documentation.
+
+
+Like the escapes, characters that match the POSIX named character classes are
+all low-valued characters unless the PCRE2_UCP option is set, but there is an
+option to override this.
+
+
+In contrast to the character escapes and character classes, the special
+horizontal and vertical white space escapes (\h, \H, \v, and \V) do match
+all the appropriate Unicode characters, whether or not PCRE2_UCP is set.
+
+
+UNICODE CASE-EQUIVALENCE
+
+
+If either PCRE2_UTF or PCRE2_UCP is set, upper/lower case processing makes use
+of Unicode properties except for characters whose code points are less than 128
+and that have at most two case-equivalent values. For these, a direct table
+lookup is used for speed. A few Unicode characters such as Greek sigma have
+more than two code points that are case-equivalent, and these are treated
+specially. Setting PCRE2_UCP without PCRE2_UTF allows Unicode-style case
+processing for non-UTF character encodings such as UCS-2.
+
+
+There are two ASCII characters (S and K) that, in addition to their ASCII lower
+case equivalents, have a non-ASCII one as well (long S and Kelvin sign).
+Recognition of these non-ASCII characters as case-equivalent to their ASCII
+counterparts can be disabled by setting the PCRE2_EXTRA_CASELESS_RESTRICT
+option. When this is set, all characters in a case equivalence must either be
+ASCII or non-ASCII; there can be no mixing.
+
+ Without PCRE2_EXTRA_CASELESS_RESTRICT:
+ 'k' = 'K' = U+212A (Kelvin sign)
+ 's' = 'S' = U+017F (long S)
+ With PCRE2_EXTRA_CASELESS_RESTRICT:
+ 'k' = 'K'
+ U+212A (Kelvin sign) only case-equivalent to itself
+ 's' = 'S'
+ U+017F (long S) only case-equivalent to itself
+
+
+
+One language family, Turkish and Azeri, has its own case-insensitivity rules,
+which can be selected by setting PCRE2_EXTRA_TURKISH_CASING. This alters the
+behaviour of the 'i', 'I', U+0130 (capital I with dot above), and U+0131
+(small dotless i) characters.
+
+ Without PCRE2_EXTRA_TURKISH_CASING:
+ 'i' = 'I'
+ U+0130 (capital I with dot above) only case-equivalent to itself
+ U+0131 (small dotless i) only case-equivalent to itself
+ With PCRE2_EXTRA_TURKISH_CASING:
+ 'i' = U+0130 (capital I with dot above)
+ U+0131 (small dotless i) = 'I'
+
+
+
+It is not allowed to specify both PCRE2_EXTRA_CASELESS_RESTRICT and
+PCRE2_EXTRA_TURKISH_CASING together.
+
+
+From release 10.45 the Unicode letter properties Lu (upper case), Ll (lower
+case), and Lt (title case) are all treated as Lc (cased letter) when caseless
+matching is set by the PCRE2_CASELESS option or (?i) within the pattern.
+
+
+SCRIPT RUNS
+
+
+The pattern constructs (*script_run:...) and (*atomic_script_run:...), with
+synonyms (*sr:...) and (*asr:...), verify that the string matched within the
+parentheses is a script run. In concept, a script run is a sequence of
+characters that are all from the same Unicode script. However, because some
+scripts are commonly used together, and because some diacritical and other
+marks are used with multiple scripts, it is not that simple.
+
+
+Every Unicode character has a Script property, mostly with a value
+corresponding to the name of a script, such as Latin, Greek, or Cyrillic. There
+are also three special values:
+
+
+"Unknown" is used for code points that have not been assigned, and also for the
+surrogate code points. In the PCRE2 32-bit library, characters whose code
+points are greater than the Unicode maximum (U+10FFFF), which are accessible
+only in non-UTF mode, are assigned the Unknown script.
+
+
+"Common" is used for characters that are used with many scripts. These include
+punctuation, emoji, mathematical, musical, and currency symbols, and the ASCII
+digits 0 to 9.
+
+
+"Inherited" is used for characters such as diacritical marks that modify a
+previous character. These are considered to take on the script of the character
+that they modify.
+
+
+Some Inherited characters are used with many scripts, but many of them are only
+normally used with a small number of scripts. For example, U+102E0 (Coptic
+Epact thousands mark) is used only with Arabic and Coptic. In order to make it
+possible to check this, a Unicode property called Script Extension exists. Its
+value is a list of scripts that apply to the character. For the majority of
+characters, the list contains just one script, the same one as the Script
+property. However, for characters such as U+102E0 more than one Script is
+listed. There are also some Common characters that have a single, non-Common
+script in their Script Extension list.
+
+
+The next section describes the basic rules for deciding whether a given string
+of characters is a script run. Note, however, that there are some special cases
+involving the Chinese Han script, and an additional constraint for decimal
+digits. These are covered in subsequent sections.
+
+
+Basic script run rules
+
+
+A string that is less than two characters long is a script run. This is the
+only case in which an Unknown character can be part of a script run. Longer
+strings are checked using only the Script Extensions property, not the basic
+Script property.
+
+
+If a character's Script Extension property is the single value "Inherited", it
+is always accepted as part of a script run. This is also true for the property
+"Common", subject to the checking of decimal digits described below. All the
+remaining characters in a script run must have at least one script in common in
+their Script Extension lists. In set-theoretic terminology, the intersection of
+all the sets of scripts must not be empty.
+
+
+A simple example is an Internet name such as "google.com". The letters are all
+in the Latin script, and the dot is Common, so this string is a script run.
+However, the Cyrillic letter "o" looks exactly the same as the Latin "o"; a
+string that looks the same, but with Cyrillic "o"s is not a script run.
+
+
+More interesting examples involve characters with more than one script in their
+Script Extension. Consider the following characters:
+
+ U+060C Arabic comma
+ U+06D4 Arabic full stop
+
+The first has the Script Extension list Arabic, Hanifi Rohingya, Syriac, and
+Thaana; the second has just Arabic and Hanifi Rohingya. Both of them could
+appear in script runs of either Arabic or Hanifi Rohingya. The first could also
+appear in Syriac or Thaana script runs, but the second could not.
+
+
+The Chinese Han script
+
+
+The Chinese Han script is commonly used in conjunction with other scripts for
+writing certain languages. Japanese uses the Hiragana and Katakana scripts
+together with Han; Korean uses Hangul and Han; Taiwanese Mandarin uses Bopomofo
+and Han. These three combinations are treated as special cases when checking
+script runs and are, in effect, "virtual scripts". Thus, a script run may
+contain a mixture of Hiragana, Katakana, and Han, or a mixture of Hangul and
+Han, or a mixture of Bopomofo and Han, but not, for example, a mixture of
+Hangul and Bopomofo and Han. PCRE2 (like Perl) follows Unicode's Technical
+Standard 39 ("Unicode Security Mechanisms", http://unicode.org/reports/tr39/)
+in allowing such mixtures.
+
+
+Decimal digits
+
+
+Unicode contains many sets of 10 decimal digits in different scripts, and some
+scripts (including the Common script) contain more than one set. Some of these
+decimal digits them are visually indistinguishable from the common ASCII
+digits. In addition to the script checking described above, if a script run
+contains any decimal digits, they must all come from the same set of 10
+adjacent characters.
+
+
+VALIDITY OF UTF STRINGS
+
+
+When the PCRE2_UTF option is set, the strings passed as patterns and subjects
+are (by default) checked for validity on entry to the relevant functions. If an
+invalid UTF string is passed, a negative error code is returned. The code unit
+offset to the offending character can be extracted from the match data block by
+calling pcre2_get_startchar(), which is used for this purpose after a UTF
+error.
+
+
+In some situations, you may already know that your strings are valid, and
+therefore want to skip these checks in order to improve performance, for
+example in the case of a long subject string that is being scanned repeatedly.
+If you set the PCRE2_NO_UTF_CHECK option at compile time or at match time,
+PCRE2 assumes that the pattern or subject it is given (respectively) contains
+only valid UTF code unit sequences.
+
+
+If you pass an invalid UTF string when PCRE2_NO_UTF_CHECK is set, the result
+is undefined and your program may crash or loop indefinitely or give incorrect
+results. There is, however, one mode of matching that can handle invalid UTF
+subject strings. This is enabled by passing PCRE2_MATCH_INVALID_UTF to
+pcre2_compile() and is discussed below in the next section. The rest of
+this section covers the case when PCRE2_MATCH_INVALID_UTF is not set.
+
+
+Passing PCRE2_NO_UTF_CHECK to pcre2_compile() just disables the UTF check
+for the pattern; it does not also apply to subject strings. If you want to
+disable the check for a subject string you must pass this same option to
+pcre2_match() or pcre2_dfa_match().
+
+
+UTF-16 and UTF-32 strings can indicate their endianness by special code knows
+as a byte-order mark (BOM). The PCRE2 functions do not handle this, expecting
+strings to be in host byte order.
+
+
+Unless PCRE2_NO_UTF_CHECK is set, a UTF string is checked before any other
+processing takes place. In the case of pcre2_match() and
+pcre2_dfa_match() calls with a non-zero starting offset, the check is
+applied only to that part of the subject that could be inspected during
+matching, and there is a check that the starting offset points to the first
+code unit of a character or to the end of the subject. If there are no
+lookbehind assertions in the pattern, the check starts at the starting offset.
+Otherwise, it starts at the length of the longest lookbehind before the
+starting offset, or at the start of the subject if there are not that many
+characters before the starting offset. Note that the sequences \b and \B are
+one-character lookbehinds.
+
+
+In addition to checking the format of the string, there is a check to ensure
+that all code points lie in the range U+0 to U+10FFFF, excluding the surrogate
+area. The so-called "non-character" code points are not excluded because
+Unicode corrigendum #9 makes it clear that they should not be.
+
+
+Characters in the "Surrogate Area" of Unicode are reserved for use by UTF-16,
+where they are used in pairs to encode code points with values greater than
+0xFFFF. The code points that are encoded by UTF-16 pairs are available
+independently in the UTF-8 and UTF-32 encodings. (In other words, the whole
+surrogate thing is a fudge for UTF-16 which unfortunately messes up UTF-8 and
+UTF-32.)
+
+
+Setting PCRE2_NO_UTF_CHECK at compile time does not disable the error that is
+given if an escape sequence for an invalid Unicode code point is encountered in
+the pattern. If you want to allow escape sequences such as \x{d800} (a
+surrogate code point) you can set the PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES extra
+option. However, this is possible only in UTF-8 and UTF-32 modes, because these
+values are not representable in UTF-16.
+
+
+Errors in UTF-8 strings
+
+
+The following negative error codes are given for invalid UTF-8 strings:
+
+ PCRE2_ERROR_UTF8_ERR1
+ PCRE2_ERROR_UTF8_ERR2
+ PCRE2_ERROR_UTF8_ERR3
+ PCRE2_ERROR_UTF8_ERR4
+ PCRE2_ERROR_UTF8_ERR5
+
+The string ends with a truncated UTF-8 character; the code specifies how many
+bytes are missing (1 to 5). Although RFC 3629 restricts UTF-8 characters to be
+no longer than 4 bytes, the encoding scheme (originally defined by RFC 2279)
+allows for up to 6 bytes, and this is checked first; hence the possibility of
+4 or 5 missing bytes.
+
+ PCRE2_ERROR_UTF8_ERR6
+ PCRE2_ERROR_UTF8_ERR7
+ PCRE2_ERROR_UTF8_ERR8
+ PCRE2_ERROR_UTF8_ERR9
+ PCRE2_ERROR_UTF8_ERR10
+
+The two most significant bits of the 2nd, 3rd, 4th, 5th, or 6th byte of the
+character do not have the binary value 0b10 (that is, either the most
+significant bit is 0, or the next bit is 1).
+
+ PCRE2_ERROR_UTF8_ERR11
+ PCRE2_ERROR_UTF8_ERR12
+
+A character that is valid by the RFC 2279 rules is either 5 or 6 bytes long;
+these code points are excluded by RFC 3629.
+
+ PCRE2_ERROR_UTF8_ERR13
+
+A 4-byte character has a value greater than 0x10ffff; these code points are
+excluded by RFC 3629.
+
+ PCRE2_ERROR_UTF8_ERR14
+
+A 3-byte character has a value in the range 0xd800 to 0xdfff; this range of
+code points are reserved by RFC 3629 for use with UTF-16, and so are excluded
+from UTF-8.
+
+ PCRE2_ERROR_UTF8_ERR15
+ PCRE2_ERROR_UTF8_ERR16
+ PCRE2_ERROR_UTF8_ERR17
+ PCRE2_ERROR_UTF8_ERR18
+ PCRE2_ERROR_UTF8_ERR19
+
+A 2-, 3-, 4-, 5-, or 6-byte character is "overlong", that is, it codes for a
+value that can be represented by fewer bytes, which is invalid. For example,
+the two bytes 0xc0, 0xae give the value 0x2e, whose correct coding uses just
+one byte.
+
+ PCRE2_ERROR_UTF8_ERR20
+
+The two most significant bits of the first byte of a character have the binary
+value 0b10 (that is, the most significant bit is 1 and the second is 0). Such a
+byte can only validly occur as the second or subsequent byte of a multi-byte
+character.
+
+ PCRE2_ERROR_UTF8_ERR21
+
+The first byte of a character has the value 0xfe or 0xff. These values can
+never occur in a valid UTF-8 string.
+
+
+Errors in UTF-16 strings
+
+
+The following negative error codes are given for invalid UTF-16 strings:
+
+ PCRE2_ERROR_UTF16_ERR1 Missing low surrogate at end of string
+ PCRE2_ERROR_UTF16_ERR2 Invalid low surrogate follows high surrogate
+ PCRE2_ERROR_UTF16_ERR3 Isolated low surrogate
+
+
+
+
+Errors in UTF-32 strings
+
+
+The following negative error codes are given for invalid UTF-32 strings:
+
+ PCRE2_ERROR_UTF32_ERR1 Surrogate character (0xd800 to 0xdfff)
+ PCRE2_ERROR_UTF32_ERR2 Code point is greater than 0x10ffff
+
+
+
+
+MATCHING IN INVALID UTF STRINGS
+
+
+You can run pattern matches on subject strings that may contain invalid UTF
+sequences if you call pcre2_compile() with the PCRE2_MATCH_INVALID_UTF
+option. This is supported by pcre2_match(), including JIT matching, but
+not by pcre2_dfa_match(). When PCRE2_MATCH_INVALID_UTF is set, it forces
+PCRE2_UTF to be set as well. Note, however, that the pattern itself must be a
+valid UTF string.
+
+
+If you do not set PCRE2_MATCH_INVALID_UTF when calling pcre2_compile, and
+you are not certain that your subject strings are valid UTF sequences, you
+should not make use of the JIT "fast path" function pcre2_jit_match()
+because it bypasses sanity checks, including the one for UTF validity. An
+invalid string may cause undefined behaviour, including looping, crashing, or
+giving the wrong answer.
+
+
+Setting PCRE2_MATCH_INVALID_UTF does not affect what pcre2_compile()
+generates, but if pcre2_jit_compile() is subsequently called, it does
+generate different code. If JIT is not used, the option affects the behaviour
+of the interpretive code in pcre2_match(). When PCRE2_MATCH_INVALID_UTF
+is set at compile time, PCRE2_NO_UTF_CHECK is ignored at match time.
+
+
+In this mode, an invalid code unit sequence in the subject never matches any
+pattern item. It does not match dot, it does not match \p{Any}, it does not
+even match negative items such as [^X]. A lookbehind assertion fails if it
+encounters an invalid sequence while moving the current point backwards. In
+other words, an invalid UTF code unit sequence acts as a barrier which no match
+can cross.
+
+
+You can also think of this as the subject being split up into fragments of
+valid UTF, delimited internally by invalid code unit sequences. The pattern is
+matched fragment by fragment. The result of a successful match, however, is
+given as code unit offsets in the entire subject string in the usual way. There
+are a few points to consider:
+
+
+The internal boundaries are not interpreted as the beginnings or ends of lines
+and so do not match circumflex or dollar characters in the pattern.
+
+
+If pcre2_match() is called with an offset that points to an invalid
+UTF-sequence, that sequence is skipped, and the match starts at the next valid
+UTF character, or the end of the subject.
+
+
+At internal fragment boundaries, \b and \B behave in the same way as at the
+beginning and end of the subject. For example, a sequence such as \bWORD\b
+would match an instance of WORD that is surrounded by invalid UTF code units.
+
+
+Using PCRE2_MATCH_INVALID_UTF, an application can run matches on arbitrary
+data, knowing that any matched strings that are returned are valid UTF. This
+can be useful when searching for UTF text in executable or other binary files.
+
+
+Note, however, that the 16-bit and 32-bit PCRE2 libraries process strings as
+sequences of uint16_t or uint32_t code points. They cannot find valid UTF
+sequences within an arbitrary string of bytes unless such sequences are
+suitably aligned.
+
+
+AUTHOR
+
+
+Philip Hazel
+
+Retired from University Computing Service
+
+Cambridge, England.
+
+
+
+REVISION
+
+
+Last updated: 27 November 2024
+
+Copyright © 1997-2024 University of Cambridge.
+
+
+Return to the PCRE2 index page.
+
diff --git a/doc/pcre2-config.1 b/doc/pcre2-config.1
new file mode 100644
index 0000000..4c99a15
--- /dev/null
+++ b/doc/pcre2-config.1
@@ -0,0 +1,87 @@
+.TH PCRE2-CONFIG 1 "22 February 2025" "PCRE2 10.48"
+.SH NAME
+pcre2-config - program to return PCRE2 configuration
+.SH SYNOPSIS
+.rs
+.sp
+.nf
+.B pcre2-config [--prefix] [--exec-prefix] [--version]
+.B " [--libs8] [--libs16] [--libs32] [--libs-posix]"
+.B " [--cflags] [--cflags-posix]"
+.fi
+.
+.
+.SH DESCRIPTION
+.rs
+.sp
+\fBpcre2-config\fP returns the configuration of the installed PCRE2 libraries
+and the options required to compile a program to use them. Some of the options
+apply only to the 8-bit, 16-bit, or 32-bit libraries, respectively, and are not
+available for libraries that have not been built. If an unavailable option is
+encountered, the "usage" information is output.
+.
+.
+.SH OPTIONS
+.rs
+.TP 10
+\fB--prefix\fP
+Writes the directory prefix used in the PCRE2 installation for
+architecture-independent files (\fI/usr\fP on many systems, \fI/usr/local\fP on
+some systems) to the standard output.
+.TP 10
+\fB--exec-prefix\fP
+Writes the directory prefix used in the PCRE2 installation for
+architecture-dependent files (normally the same as \fB--prefix\fP) to the
+standard output.
+.TP 10
+\fB--version\fP
+Writes the version number of the installed PCRE2 libraries to the standard
+output.
+.TP 10
+\fB--libs8\fP
+Writes to the standard output the command line options required to link
+with the 8-bit PCRE2 library (\fB-lpcre2-8\fP on many systems).
+.TP 10
+\fB--libs16\fP
+Writes to the standard output the command line options required to link
+with the 16-bit PCRE2 library (\fB-lpcre2-16\fP on many systems).
+.TP 10
+\fB--libs32\fP
+Writes to the standard output the command line options required to link
+with the 32-bit PCRE2 library (\fB-lpcre2-32\fP on many systems).
+.TP 10
+\fB--libs-posix\fP
+Writes to the standard output the command line options required to link with
+PCRE2's POSIX API wrapper library (\fB-lpcre2-posix\fP \fB-lpcre2-8\fP on many
+systems).
+.TP 10
+\fB--cflags\fP
+Writes to the standard output the command line options required to compile
+files that use PCRE2 (this may include some \fB-I\fP options, but is blank on
+many systems).
+.TP 10
+\fB--cflags-posix\fP
+Writes to the standard output the command line options required to compile
+files that use PCRE2's POSIX API wrapper library (this may include some
+\fB-I\fP options, but is blank on many systems).
+.
+.
+.SH "SEE ALSO"
+.rs
+.sp
+\fBpcre2(3)\fP
+.
+.
+.SH AUTHOR
+.rs
+.sp
+This manual page was originally written by Mark Baker for the Debian GNU/Linux
+system. It has been subsequently revised as a generic PCRE2 man page.
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 22 February 2025
+.fi
diff --git a/doc/pcre2-config.txt b/doc/pcre2-config.txt
new file mode 100644
index 0000000..b1a7070
--- /dev/null
+++ b/doc/pcre2-config.txt
@@ -0,0 +1,84 @@
+PCRE2-CONFIG(1) General Commands Manual PCRE2-CONFIG(1)
+
+
+NAME
+ pcre2-config - program to return PCRE2 configuration
+
+
+SYNOPSIS
+
+ pcre2-config [--prefix] [--exec-prefix] [--version]
+ [--libs8] [--libs16] [--libs32] [--libs-posix]
+ [--cflags] [--cflags-posix]
+
+
+DESCRIPTION
+
+ pcre2-config returns the configuration of the installed PCRE2 libraries
+ and the options required to compile a program to use them. Some of the
+ options apply only to the 8-bit, 16-bit, or 32-bit libraries, respec-
+ tively, and are not available for libraries that have not been built.
+ If an unavailable option is encountered, the "usage" information is
+ output.
+
+
+OPTIONS
+
+ --prefix Writes the directory prefix used in the PCRE2 installation
+ for architecture-independent files (/usr on many systems,
+ /usr/local on some systems) to the standard output.
+
+ --exec-prefix
+ Writes the directory prefix used in the PCRE2 installation
+ for architecture-dependent files (normally the same as --pre-
+ fix) to the standard output.
+
+ --version Writes the version number of the installed PCRE2 libraries to
+ the standard output.
+
+ --libs8 Writes to the standard output the command line options re-
+ quired to link with the 8-bit PCRE2 library (-lpcre2-8 on
+ many systems).
+
+ --libs16 Writes to the standard output the command line options re-
+ quired to link with the 16-bit PCRE2 library (-lpcre2-16 on
+ many systems).
+
+ --libs32 Writes to the standard output the command line options re-
+ quired to link with the 32-bit PCRE2 library (-lpcre2-32 on
+ many systems).
+
+ --libs-posix
+ Writes to the standard output the command line options re-
+ quired to link with PCRE2's POSIX API wrapper library
+ (-lpcre2-posix -lpcre2-8 on many systems).
+
+ --cflags Writes to the standard output the command line options re-
+ quired to compile files that use PCRE2 (this may include some
+ -I options, but is blank on many systems).
+
+ --cflags-posix
+ Writes to the standard output the command line options re-
+ quired to compile files that use PCRE2's POSIX API wrapper
+ library (this may include some -I options, but is blank on
+ many systems).
+
+
+SEE ALSO
+
+ pcre2(3)
+
+
+AUTHOR
+
+ This manual page was originally written by Mark Baker for the Debian
+ GNU/Linux system. It has been subsequently revised as a generic PCRE2
+ man page.
+
+
+REVISION
+
+ Last updated: 22 February 2025
+
+
+PCRE2 10.48 22 February 2025 PCRE2-CONFIG(1)
diff --git a/doc/pcre2.3 b/doc/pcre2.3
new file mode 100644
index 0000000..ce4b04c
--- /dev/null
+++ b/doc/pcre2.3
@@ -0,0 +1,211 @@
+.TH PCRE2 3 "22 February 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH INTRODUCTION
+.rs
+.sp
+PCRE2 is the name used for a revised API for the PCRE library, which is a set
+of functions, written in C, that implement regular expression pattern matching
+using the same syntax and semantics as Perl, with just a few differences. After
+nearly two decades, the limitations of the original API were making development
+increasingly difficult. The new API is more extensible, and it was simplified
+by abolishing the separate "study" optimizing function; in PCRE2, patterns are
+automatically optimized where possible. Since forking from PCRE1, the code has
+been extensively refactored and new features introduced. The old library is now
+obsolete and is no longer maintained.
+.P
+As well as Perl-style regular expression patterns, some features that appeared
+in Python and the original PCRE before they appeared in Perl are available
+using the Python syntax. There is also support for some .NET and Oniguruma
+syntax items, and there are options for requesting minor changes that give
+better ECMAScript (JavaScript) compatibility.
+.P
+The source code for PCRE2 can be compiled to support strings of 8-bit, 16-bit,
+or 32-bit code units, which means that up to three separate libraries may be
+installed, one for each code unit size. The size of a code unit is not related
+to the bit size of the underlying hardware. In a 64-bit environment that also
+supports 32-bit applications, versions of PCRE2 that are compiled in both
+64-bit and 32-bit modes may be needed.
+.P
+The original work to extend PCRE to 16-bit and 32-bit code units was done by
+Zoltan Herczeg and Christian Persch, respectively. In all three cases, strings
+can be interpreted either as one character per code unit, or as UTF-encoded
+Unicode, with support for Unicode general category properties. Unicode support
+is optional at build time (but is the default). However, processing strings as
+UTF code units must be enabled explicitly at run time. The version of Unicode
+in use can be discovered by running
+.sp
+ pcre2test -C
+.P
+The three libraries contain identical sets of functions, with names ending in
+_8, _16, or _32, respectively (for example, \fBpcre2_compile_8()\fP). However,
+by defining PCRE2_CODE_UNIT_WIDTH to be 8, 16, or 32, a program that uses just
+one code unit width can be written using generic names such as
+\fBpcre2_compile()\fP, and the documentation is written assuming that this is
+the case.
+.P
+In addition to the Perl-compatible matching function, PCRE2 contains an
+alternative function that matches the same compiled patterns in a different
+way. In certain circumstances, the alternative function has some advantages.
+For a discussion of the two matching algorithms, see the
+.\" HREF
+\fBpcre2matching\fP
+.\"
+page.
+.P
+Details of exactly which Perl regular expression features are and are not
+supported by PCRE2 are given in separate documents. See the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+and
+.\" HREF
+\fBpcre2compat\fP
+.\"
+pages. There is a syntax summary in the
+.\" HREF
+\fBpcre2syntax\fP
+.\"
+page.
+.P
+Some features of PCRE2 can be included, excluded, or changed when the library
+is built. The
+.\" HREF
+\fBpcre2_config()\fP
+.\"
+function makes it possible for a client to discover which features are
+available. The features themselves are described in the
+.\" HREF
+\fBpcre2build\fP
+.\"
+page. Documentation about building PCRE2 for various operating systems can be
+found in the
+.\" HTML
+.\"
+\fBREADME\fP
+.\"
+and
+.\" HTML
+.\"
+\fBNON-AUTOTOOLS-BUILD\fP
+.\"
+files in the source distribution.
+.P
+The libraries contains a number of undocumented internal functions and data
+tables that are used by more than one of the exported external functions, but
+which are not intended for use by external callers. Their names all begin with
+"_pcre2", which hopefully will not provoke any name clashes. In some
+environments, it is possible to control which external symbols are exported
+when a shared library is built, and in these cases the undocumented symbols are
+not exported.
+.
+.
+.SH "SECURITY CONSIDERATIONS"
+.rs
+.sp
+If you are using PCRE2 in a non-UTF application that permits users to supply
+arbitrary patterns for compilation, you should be aware of a feature that
+allows users to turn on UTF support from within a pattern. For example, an
+8-bit pattern that begins with "(*UTF)" turns on UTF-8 mode, which interprets
+patterns and subjects as strings of UTF-8 code units instead of individual
+8-bit characters. This causes both the pattern and any data against which it is
+matched to be checked for UTF-8 validity. If the data string is very long, such
+a check might use sufficiently many resources as to cause your application to
+lose performance.
+.P
+One way of guarding against this possibility is to use the
+\fBpcre2_pattern_info()\fP function to check the compiled pattern's options for
+PCRE2_UTF. Alternatively, you can set the PCRE2_NEVER_UTF option when calling
+\fBpcre2_compile()\fP. This causes a compile time error if the pattern contains
+a UTF-setting sequence.
+.P
+The use of Unicode properties for character types such as \ed can also be
+enabled from within the pattern, by specifying "(*UCP)". This feature can be
+disallowed by setting the PCRE2_NEVER_UCP option.
+.P
+If your application is one that supports UTF, be aware that validity checking
+can take time. If the same data string is to be matched many times, you can use
+the PCRE2_NO_UTF_CHECK option for the second and subsequent matches to avoid
+running redundant checks.
+.P
+The use of the \eC escape sequence in a UTF-8 or UTF-16 pattern can lead to
+problems, because it may leave the current matching point in the middle of a
+multi-code-unit character. The PCRE2_NEVER_BACKSLASH_C option can be used by an
+application to lock out the use of \eC, causing a compile-time error if it is
+encountered. It is also possible to build PCRE2 with the use of \eC permanently
+disabled.
+.P
+Another way that performance can be hit is by running a pattern that has a very
+large search tree against a string that will never match. Nested unlimited
+repeats in a pattern are a common example. PCRE2 provides some protection
+against this: see the \fBpcre2_set_match_limit()\fP function in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page. There is a similar function called \fBpcre2_set_depth_limit()\fP that can
+be used to restrict the amount of memory that is used.
+.
+.
+.SH "USER DOCUMENTATION"
+.rs
+.sp
+The user documentation for PCRE2 comprises a number of different sections. In
+the "man" format, each of these is a separate "man page". In the HTML format,
+each is a separate page, linked from the index page. In the plain text format,
+the descriptions of the \fBpcre2grep\fP and \fBpcre2test\fP programs are in
+files called \fBpcre2grep.txt\fP and \fBpcre2test.txt\fP, respectively. The
+remaining sections, except for the \fBpcre2demo\fP section (which is a program
+listing), and the short pages for individual functions, are concatenated in
+\fBpcre2.txt\fP, for ease of searching. The sections are as follows:
+.sp
+ pcre2 this document
+ pcre2-config show PCRE2 installation configuration information
+ pcre2api details of PCRE2's native C API
+ pcre2build building PCRE2
+ pcre2callout details of the pattern callout feature
+ pcre2compat discussion of Perl compatibility
+ pcre2convert details of pattern conversion functions
+ pcre2demo a demonstration C program that uses PCRE2
+ pcre2grep description of the \fBpcre2grep\fP command (8-bit only)
+ pcre2jit discussion of just-in-time optimization support
+ pcre2limits details of size and other limits
+ pcre2matching discussion of the two matching algorithms
+ pcre2partial details of the partial matching facility
+.\" JOIN
+ pcre2pattern syntax and semantics of supported regular
+ expression patterns
+ pcre2perform discussion of performance issues
+ pcre2posix the POSIX-compatible C API for the 8-bit library
+ pcre2sample discussion of the pcre2demo program
+ pcre2serialize details of pattern serialization
+ pcre2syntax quick syntax reference
+ pcre2test description of the \fBpcre2test\fP command
+ pcre2unicode discussion of Unicode and UTF support
+.sp
+In the "man" and HTML formats, there is also a short page for each C library
+function, listing its arguments and results.
+.
+.
+.SH AUTHORS
+.rs
+.sp
+The current maintainers of PCRE2 are Nicholas Wilson and Zoltan Herczeg.
+.P
+PCRE2 was written by Philip Hazel, of the University Computing Service,
+Cambridge, England. Many others have also contributed.
+.P
+To contact the maintainers, please use the GitHub issues tracker or PCRE2
+mailing list, as described at the project page:
+.\" HTML
+.\"
+https://github.com/PCRE2Project/pcre2
+.\"
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 22 February 2025
+Copyright (c) 1997-2021 University of Cambridge.
+.fi
diff --git a/doc/pcre2.txt b/doc/pcre2.txt
new file mode 100644
index 0000000..dc2cee1
--- /dev/null
+++ b/doc/pcre2.txt
@@ -0,0 +1,12949 @@
+-----------------------------------------------------------------------------
+This file contains a concatenation of the PCRE2 man pages, converted to plain
+text format for ease of searching with a text editor, or for use on systems
+that do not have a man page processor. The small individual files that give
+synopses of each function in the library have not been included. Neither has
+the pcre2demo program. There are separate text files for the pcre2grep and
+pcre2test commands.
+-----------------------------------------------------------------------------
+
+
+PCRE2(3) Library Functions Manual PCRE2(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+
+INTRODUCTION
+
+ PCRE2 is the name used for a revised API for the PCRE library, which is
+ a set of functions, written in C, that implement regular expression
+ pattern matching using the same syntax and semantics as Perl, with just
+ a few differences. After nearly two decades, the limitations of the
+ original API were making development increasingly difficult. The new
+ API is more extensible, and it was simplified by abolishing the sepa-
+ rate "study" optimizing function; in PCRE2, patterns are automatically
+ optimized where possible. Since forking from PCRE1, the code has been
+ extensively refactored and new features introduced. The old library is
+ now obsolete and is no longer maintained.
+
+ As well as Perl-style regular expression patterns, some features that
+ appeared in Python and the original PCRE before they appeared in Perl
+ are available using the Python syntax. There is also support for some
+ .NET and Oniguruma syntax items, and there are options for requesting
+ minor changes that give better ECMAScript (JavaScript) compatibility.
+
+ The source code for PCRE2 can be compiled to support strings of 8-bit,
+ 16-bit, or 32-bit code units, which means that up to three separate li-
+ braries may be installed, one for each code unit size. The size of a
+ code unit is not related to the bit size of the underlying hardware. In
+ a 64-bit environment that also supports 32-bit applications, versions
+ of PCRE2 that are compiled in both 64-bit and 32-bit modes may be
+ needed.
+
+ The original work to extend PCRE to 16-bit and 32-bit code units was
+ done by Zoltan Herczeg and Christian Persch, respectively. In all three
+ cases, strings can be interpreted either as one character per code
+ unit, or as UTF-encoded Unicode, with support for Unicode general cate-
+ gory properties. Unicode support is optional at build time (but is the
+ default). However, processing strings as UTF code units must be enabled
+ explicitly at run time. The version of Unicode in use can be discovered
+ by running
+
+ pcre2test -C
+
+ The three libraries contain identical sets of functions, with names
+ ending in _8, _16, or _32, respectively (for example, pcre2_com-
+ pile_8()). However, by defining PCRE2_CODE_UNIT_WIDTH to be 8, 16, or
+ 32, a program that uses just one code unit width can be written using
+ generic names such as pcre2_compile(), and the documentation is written
+ assuming that this is the case.
+
+ In addition to the Perl-compatible matching function, PCRE2 contains an
+ alternative function that matches the same compiled patterns in a dif-
+ ferent way. In certain circumstances, the alternative function has some
+ advantages. For a discussion of the two matching algorithms, see the
+ pcre2matching page.
+
+ Details of exactly which Perl regular expression features are and are
+ not supported by PCRE2 are given in separate documents. See the
+ pcre2pattern and pcre2compat pages. There is a syntax summary in the
+ pcre2syntax page.
+
+ Some features of PCRE2 can be included, excluded, or changed when the
+ library is built. The pcre2_config() function makes it possible for a
+ client to discover which features are available. The features them-
+ selves are described in the pcre2build page. Documentation about build-
+ ing PCRE2 for various operating systems can be found in the README and
+ NON-AUTOTOOLS-BUILD files in the source distribution.
+
+ The libraries contains a number of undocumented internal functions and
+ data tables that are used by more than one of the exported external
+ functions, but which are not intended for use by external callers.
+ Their names all begin with "_pcre2", which hopefully will not provoke
+ any name clashes. In some environments, it is possible to control which
+ external symbols are exported when a shared library is built, and in
+ these cases the undocumented symbols are not exported.
+
+
+SECURITY CONSIDERATIONS
+
+ If you are using PCRE2 in a non-UTF application that permits users to
+ supply arbitrary patterns for compilation, you should be aware of a
+ feature that allows users to turn on UTF support from within a pattern.
+ For example, an 8-bit pattern that begins with "(*UTF)" turns on UTF-8
+ mode, which interprets patterns and subjects as strings of UTF-8 code
+ units instead of individual 8-bit characters. This causes both the pat-
+ tern and any data against which it is matched to be checked for UTF-8
+ validity. If the data string is very long, such a check might use suf-
+ ficiently many resources as to cause your application to lose perfor-
+ mance.
+
+ One way of guarding against this possibility is to use the pcre2_pat-
+ tern_info() function to check the compiled pattern's options for
+ PCRE2_UTF. Alternatively, you can set the PCRE2_NEVER_UTF option when
+ calling pcre2_compile(). This causes a compile time error if the pat-
+ tern contains a UTF-setting sequence.
+
+ The use of Unicode properties for character types such as \d can also
+ be enabled from within the pattern, by specifying "(*UCP)". This fea-
+ ture can be disallowed by setting the PCRE2_NEVER_UCP option.
+
+ If your application is one that supports UTF, be aware that validity
+ checking can take time. If the same data string is to be matched many
+ times, you can use the PCRE2_NO_UTF_CHECK option for the second and
+ subsequent matches to avoid running redundant checks.
+
+ The use of the \C escape sequence in a UTF-8 or UTF-16 pattern can lead
+ to problems, because it may leave the current matching point in the
+ middle of a multi-code-unit character. The PCRE2_NEVER_BACKSLASH_C op-
+ tion can be used by an application to lock out the use of \C, causing a
+ compile-time error if it is encountered. It is also possible to build
+ PCRE2 with the use of \C permanently disabled.
+
+ Another way that performance can be hit is by running a pattern that
+ has a very large search tree against a string that will never match.
+ Nested unlimited repeats in a pattern are a common example. PCRE2 pro-
+ vides some protection against this: see the pcre2_set_match_limit()
+ function in the pcre2api page. There is a similar function called
+ pcre2_set_depth_limit() that can be used to restrict the amount of mem-
+ ory that is used.
+
+
+USER DOCUMENTATION
+
+ The user documentation for PCRE2 comprises a number of different sec-
+ tions. In the "man" format, each of these is a separate "man page". In
+ the HTML format, each is a separate page, linked from the index page.
+ In the plain text format, the descriptions of the pcre2grep and
+ pcre2test programs are in files called pcre2grep.txt and pcre2test.txt,
+ respectively. The remaining sections, except for the pcre2demo section
+ (which is a program listing), and the short pages for individual func-
+ tions, are concatenated in pcre2.txt, for ease of searching. The sec-
+ tions are as follows:
+
+ pcre2 this document
+ pcre2-config show PCRE2 installation configuration information
+ pcre2api details of PCRE2's native C API
+ pcre2build building PCRE2
+ pcre2callout details of the pattern callout feature
+ pcre2compat discussion of Perl compatibility
+ pcre2convert details of pattern conversion functions
+ pcre2demo a demonstration C program that uses PCRE2
+ pcre2grep description of the pcre2grep command (8-bit only)
+ pcre2jit discussion of just-in-time optimization support
+ pcre2limits details of size and other limits
+ pcre2matching discussion of the two matching algorithms
+ pcre2partial details of the partial matching facility
+ pcre2pattern syntax and semantics of supported regular
+ expression patterns
+ pcre2perform discussion of performance issues
+ pcre2posix the POSIX-compatible C API for the 8-bit library
+ pcre2sample discussion of the pcre2demo program
+ pcre2serialize details of pattern serialization
+ pcre2syntax quick syntax reference
+ pcre2test description of the pcre2test command
+ pcre2unicode discussion of Unicode and UTF support
+
+ In the "man" and HTML formats, there is also a short page for each C
+ library function, listing its arguments and results.
+
+
+AUTHORS
+
+ The current maintainers of PCRE2 are Nicholas Wilson and Zoltan Her-
+ czeg.
+
+ PCRE2 was written by Philip Hazel, of the University Computing Service,
+ Cambridge, England. Many others have also contributed.
+
+ To contact the maintainers, please use the GitHub issues tracker or
+ PCRE2 mailing list, as described at the project page:
+ https://github.com/PCRE2Project/pcre2
+
+
+REVISION
+
+ Last updated: 22 February 2025
+ Copyright (c) 1997-2021 University of Cambridge.
+
+
+PCRE2 10.48 22 February 2025 PCRE2(3)
+------------------------------------------------------------------------------
+
+
+PCRE2API(3) Library Functions Manual PCRE2API(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+ #include
+
+ PCRE2 is a new API for PCRE, starting at release 10.0. This document
+ contains a description of all its native functions. See the pcre2 docu-
+ ment for an overview of all the PCRE2 documentation.
+
+
+PCRE2 NATIVE API BASIC FUNCTIONS
+
+ pcre2_code *pcre2_compile(PCRE2_SPTR pattern, PCRE2_SIZE length,
+ uint32_t options, int *errorcode, PCRE2_SIZE *erroroffset,
+ pcre2_compile_context *ccontext);
+
+ void pcre2_code_free(pcre2_code *code);
+
+ pcre2_match_data *pcre2_match_data_create(uint32_t ovecsize,
+ pcre2_general_context *gcontext);
+
+ pcre2_match_data *pcre2_match_data_create_from_pattern(
+ const pcre2_code *code, pcre2_general_context *gcontext);
+
+ int pcre2_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext);
+
+ int pcre2_dfa_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext,
+ int *workspace, PCRE2_SIZE wscount);
+
+ void pcre2_match_data_free(pcre2_match_data *match_data);
+
+
+PCRE2 NATIVE API AUXILIARY MATCH FUNCTIONS
+
+ PCRE2_SPTR pcre2_get_mark(pcre2_match_data *match_data);
+
+ PCRE2_SIZE pcre2_get_match_data_size(pcre2_match_data *match_data);
+
+ PCRE2_SIZE pcre2_get_match_data_heapframes_size(
+ pcre2_match_data *match_data);
+
+ uint32_t pcre2_get_ovector_count(pcre2_match_data *match_data);
+
+ PCRE2_SIZE *pcre2_get_ovector_pointer(pcre2_match_data *match_data);
+
+ PCRE2_SIZE pcre2_get_startchar(pcre2_match_data *match_data);
+
+
+PCRE2 NATIVE API GENERAL CONTEXT FUNCTIONS
+
+ pcre2_general_context *pcre2_general_context_create(
+ void *(*private_malloc)(PCRE2_SIZE, void *),
+ void (*private_free)(void *, void *), void *memory_data);
+
+ pcre2_general_context *pcre2_general_context_copy(
+ pcre2_general_context *gcontext);
+
+ void pcre2_general_context_free(pcre2_general_context *gcontext);
+
+
+PCRE2 NATIVE API COMPILE CONTEXT FUNCTIONS
+
+ pcre2_compile_context *pcre2_compile_context_create(
+ pcre2_general_context *gcontext);
+
+ pcre2_compile_context *pcre2_compile_context_copy(
+ pcre2_compile_context *ccontext);
+
+ void pcre2_compile_context_free(pcre2_compile_context *ccontext);
+
+ int pcre2_set_bsr(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+ int pcre2_set_character_tables(pcre2_compile_context *ccontext,
+ const uint8_t *tables);
+
+ int pcre2_set_compile_extra_options(pcre2_compile_context *ccontext,
+ uint32_t extra_options);
+
+ int pcre2_set_max_pattern_length(pcre2_compile_context *ccontext,
+ PCRE2_SIZE value);
+
+ int pcre2_set_max_pattern_compiled_length(
+ pcre2_compile_context *ccontext, PCRE2_SIZE value);
+
+ int pcre2_set_max_varlookbehind(pcre2_compile_contest *ccontext,
+ uint32_t value);
+
+ int pcre2_set_newline(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+ int pcre2_set_parens_nest_limit(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+ int pcre2_set_compile_recursion_guard(pcre2_compile_context *ccontext,
+ int (*guard_function)(uint32_t, void *), void *user_data);
+
+ int pcre2_set_optimize(pcre2_compile_context *ccontext,
+ uint32_t directive);
+
+
+PCRE2 NATIVE API MATCH CONTEXT FUNCTIONS
+
+ pcre2_match_context *pcre2_match_context_create(
+ pcre2_general_context *gcontext);
+
+ pcre2_match_context *pcre2_match_context_copy(
+ pcre2_match_context *mcontext);
+
+ void pcre2_match_context_free(pcre2_match_context *mcontext);
+
+ int pcre2_set_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_callout_block *, void *),
+ void *callout_data);
+
+ int pcre2_set_substitute_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_substitute_callout_block *, void *),
+ void *callout_data);
+
+ int pcre2_set_substitute_case_callout(pcre2_match_context *mcontext,
+ PCRE2_SIZE (*callout_function)(PCRE2_SPTR, PCRE2_SIZE,
+ PCRE2_UCHAR *, PCRE2_SIZE,
+ int, void *),
+ void *callout_data);
+
+ int pcre2_set_offset_limit(pcre2_match_context *mcontext,
+ PCRE2_SIZE value);
+
+ int pcre2_set_heap_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+ int pcre2_set_match_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+ int pcre2_set_depth_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+
+PCRE2 NATIVE API STRING EXTRACTION FUNCTIONS
+
+ int pcre2_substring_copy_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_UCHAR *buffer, PCRE2_SIZE *bufflen);
+
+ int pcre2_substring_copy_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_UCHAR *buffer,
+ PCRE2_SIZE *bufflen);
+
+ void pcre2_substring_free(PCRE2_UCHAR *buffer);
+
+ int pcre2_substring_get_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_UCHAR **bufferptr, PCRE2_SIZE *bufflen);
+
+ int pcre2_substring_get_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_UCHAR **bufferptr,
+ PCRE2_SIZE *bufflen);
+
+ int pcre2_substring_length_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_SIZE *length);
+
+ int pcre2_substring_length_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_SIZE *length);
+
+ int pcre2_substring_nametable_scan(const pcre2_code *code,
+ PCRE2_SPTR name, PCRE2_SPTR *first, PCRE2_SPTR *last);
+
+ int pcre2_substring_number_from_name(const pcre2_code *code,
+ PCRE2_SPTR name);
+
+ void pcre2_substring_list_free(PCRE2_UCHAR **list);
+
+ int pcre2_substring_list_get(pcre2_match_data *match_data,
+ PCRE2_UCHAR ***listptr, PCRE2_SIZE **lengthsptr);
+
+
+PCRE2 NATIVE API STRING SUBSTITUTION FUNCTION
+
+ int pcre2_substitute(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext, PCRE2_SPTR replacement,
+ PCRE2_SIZE rlength, PCRE2_UCHAR *outputbuffer,
+ PCRE2_SIZE *outlengthptr);
+
+
+PCRE2 NATIVE API JIT FUNCTIONS
+
+ int pcre2_jit_compile(pcre2_code *code, uint32_t options);
+
+ int pcre2_jit_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext);
+
+ void pcre2_jit_free_unused_memory(pcre2_general_context *gcontext);
+
+ pcre2_jit_stack *pcre2_jit_stack_create(size_t startsize,
+ size_t maxsize, pcre2_general_context *gcontext);
+
+ void pcre2_jit_stack_assign(pcre2_match_context *mcontext,
+ pcre2_jit_callback callback_function, void *callback_data);
+
+ void pcre2_jit_stack_free(pcre2_jit_stack *jit_stack);
+
+
+PCRE2 NATIVE API SERIALIZATION FUNCTIONS
+
+ int32_t pcre2_serialize_decode(pcre2_code **codes,
+ int32_t number_of_codes, const uint8_t *bytes,
+ pcre2_general_context *gcontext);
+
+ int32_t pcre2_serialize_encode(const pcre2_code **codes,
+ int32_t number_of_codes, uint8_t **serialized_bytes,
+ PCRE2_SIZE *serialized_size, pcre2_general_context *gcontext);
+
+ void pcre2_serialize_free(uint8_t *bytes);
+
+ int32_t pcre2_serialize_get_number_of_codes(const uint8_t *bytes);
+
+
+PCRE2 NATIVE API AUXILIARY FUNCTIONS
+
+ pcre2_code *pcre2_code_copy(const pcre2_code *code);
+
+ pcre2_code *pcre2_code_copy_with_tables(const pcre2_code *code);
+
+ int pcre2_get_error_message(int errorcode, PCRE2_UCHAR *buffer,
+ PCRE2_SIZE bufflen);
+
+ const uint8_t *pcre2_maketables(pcre2_general_context *gcontext);
+
+ void pcre2_maketables_free(pcre2_general_context *gcontext,
+ const uint8_t *tables);
+
+ int pcre2_pattern_info(const pcre2_code *code, uint32_t what,
+ void *where);
+
+ int pcre2_callout_enumerate(const pcre2_code *code,
+ int (*callback)(pcre2_callout_enumerate_block *, void *),
+ void *user_data);
+
+ int pcre2_config(uint32_t what, void *where);
+
+
+PCRE2 NATIVE API OBSOLETE FUNCTIONS
+
+ int pcre2_set_recursion_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+ int pcre2_set_recursion_memory_management(
+ pcre2_match_context *mcontext,
+ void *(*private_malloc)(size_t, void *),
+ void (*private_free)(void *, void *), void *memory_data);
+
+ These functions became obsolete at release 10.30 and are retained only
+ for backward compatibility. They should not be used in new code. The
+ first is replaced by pcre2_set_depth_limit(); the second is no longer
+ needed and has no effect (it always returns zero).
+
+
+PCRE2 EXPERIMENTAL PATTERN CONVERSION FUNCTIONS
+
+ pcre2_convert_context *pcre2_convert_context_create(
+ pcre2_general_context *gcontext);
+
+ pcre2_convert_context *pcre2_convert_context_copy(
+ pcre2_convert_context *cvcontext);
+
+ void pcre2_convert_context_free(pcre2_convert_context *cvcontext);
+
+ int pcre2_set_glob_escape(pcre2_convert_context *cvcontext,
+ uint32_t escape_char);
+
+ int pcre2_set_glob_separator(pcre2_convert_context *cvcontext,
+ uint32_t separator_char);
+
+ int pcre2_pattern_convert(PCRE2_SPTR pattern, PCRE2_SIZE length,
+ uint32_t options, PCRE2_UCHAR **buffer,
+ PCRE2_SIZE *blength, pcre2_convert_context *cvcontext);
+
+ void pcre2_converted_pattern_free(PCRE2_UCHAR *converted_pattern);
+
+ These functions provide a way of converting non-PCRE2 patterns into
+ patterns that can be processed by pcre2_compile(). This facility is ex-
+ perimental and may be changed in future releases. At present, "globs"
+ and POSIX basic and extended patterns can be converted. Details are
+ given in the pcre2convert documentation.
+
+
+PCRE2 8-BIT, 16-BIT, AND 32-BIT LIBRARIES
+
+ There are three PCRE2 libraries, supporting 8-bit, 16-bit, and 32-bit
+ code units, respectively. However, there is just one header file,
+ pcre2.h. This contains the function prototypes and other definitions
+ for all three libraries. One, two, or all three can be installed simul-
+ taneously. On Unix-like systems the libraries are called libpcre2-8,
+ libpcre2-16, and libpcre2-32, and they can also co-exist with the orig-
+ inal PCRE libraries. Every PCRE2 function comes in three different
+ forms, one for each library, for example:
+
+ pcre2_compile_8()
+ pcre2_compile_16()
+ pcre2_compile_32()
+
+ There are also three different sets of data types:
+
+ PCRE2_UCHAR8, PCRE2_UCHAR16, PCRE2_UCHAR32
+ PCRE2_SPTR8, PCRE2_SPTR16, PCRE2_SPTR32
+
+ The UCHAR types define unsigned code units of the appropriate widths.
+ For example, PCRE2_UCHAR16 is usually defined as `uint16_t'. The SPTR
+ types are pointers to constants of the equivalent UCHAR types, that is,
+ they are pointers to vectors of unsigned code units.
+
+ Character strings are passed to a PCRE2 library as sequences of un-
+ signed integers in code units of the appropriate width. The length of a
+ string may be given as a number of code units, or the string may be
+ specified as zero-terminated.
+
+ Many applications use only one code unit width. For their convenience,
+ macros are defined whose names are the generic forms such as pcre2_com-
+ pile() and PCRE2_SPTR. These macros use the value of the macro
+ PCRE2_CODE_UNIT_WIDTH to generate the appropriate width-specific func-
+ tion and macro names. PCRE2_CODE_UNIT_WIDTH is not defined by default.
+ An application must define it to be 8, 16, or 32 before including
+ pcre2.h in order to make use of the generic names.
+
+ Applications that use more than one code unit width can be linked with
+ more than one PCRE2 library, but must define PCRE2_CODE_UNIT_WIDTH to
+ be 0 before including pcre2.h, and then use the real function names.
+ Any code that is to be included in an environment where the value of
+ PCRE2_CODE_UNIT_WIDTH is unknown should also use the real function
+ names. (Unfortunately, it is not possible in C code to save and restore
+ the value of a macro.)
+
+ If PCRE2_CODE_UNIT_WIDTH is not defined before including pcre2.h, a
+ compiler error occurs.
+
+ When using multiple libraries in an application, you must take care
+ when processing any particular pattern to use only functions from a
+ single library. For example, if you want to run a match using a pat-
+ tern that was compiled with pcre2_compile_16(), you must do so with
+ pcre2_match_16(), not pcre2_match_8() or pcre2_match_32().
+
+ In the function summaries above, and in the rest of this document and
+ other PCRE2 documents, functions and data types are described using
+ their generic names, without the _8, _16, or _32 suffix.
+
+
+PCRE2 API OVERVIEW
+
+ PCRE2 has its own native API, which is described in this document.
+ There are also some wrapper functions for the 8-bit library that corre-
+ spond to the POSIX regular expression API, but they do not give access
+ to all the functionality of PCRE2 and they are not thread-safe. They
+ are described in the pcre2posix documentation. Both these APIs define a
+ set of C function calls.
+
+ The native API C data types, function prototypes, option values, and
+ error codes are defined in the header file pcre2.h, which also contains
+ definitions of PCRE2_MAJOR and PCRE2_MINOR, the major and minor release
+ numbers for the library. Applications can use these to include support
+ for different releases of PCRE2.
+
+ In a Windows environment, if you want to statically link an application
+ program against a non-dll PCRE2 library, you must define PCRE2_STATIC
+ before including pcre2.h.
+
+ The functions pcre2_compile() and pcre2_match() are used for compiling
+ and matching regular expressions in a Perl-compatible manner. A sample
+ program that demonstrates the simplest way of using them is provided in
+ the file called pcre2demo.c in the PCRE2 source distribution. A listing
+ of this program is given in the pcre2demo documentation, and the
+ pcre2sample documentation describes how to compile and run it.
+
+ The compiling and matching functions recognize various options that are
+ passed as bits in an options argument. There are also some more compli-
+ cated parameters such as custom memory management functions and re-
+ source limits that are passed in "contexts" (which are just memory
+ blocks, described below). Simple applications do not need to make use
+ of contexts.
+
+ Just-in-time (JIT) compiler support is an optional feature of PCRE2
+ that can be built in appropriate hardware environments. It greatly
+ speeds up the matching performance of many patterns. Programs can re-
+ quest that it be used if available by calling pcre2_jit_compile() after
+ a pattern has been successfully compiled by pcre2_compile(). This does
+ nothing if JIT support is not available.
+
+ More complicated programs might need to make use of the specialist
+ functions pcre2_jit_stack_create(), pcre2_jit_stack_free(), and
+ pcre2_jit_stack_assign() in order to control the JIT code's memory us-
+ age.
+
+ JIT matching is automatically used by pcre2_match() if it is available,
+ unless the PCRE2_NO_JIT option is set. There is also a direct interface
+ for JIT matching, which gives improved performance at the expense of
+ less sanity checking. The JIT-specific functions are discussed in the
+ pcre2jit documentation.
+
+ A second matching function, pcre2_dfa_match(), which is not Perl-com-
+ patible, is also provided. This uses a different algorithm for the
+ matching. The alternative algorithm finds all possible matches (at a
+ given point in the subject), and scans the subject just once (unless
+ there are lookaround assertions). However, this algorithm does not re-
+ turn captured substrings. A description of the two matching algorithms
+ and their advantages and disadvantages is given in the pcre2matching
+ documentation. There is no JIT support for pcre2_dfa_match().
+
+ In addition to the main compiling and matching functions, there are
+ convenience functions for extracting captured substrings from a subject
+ string that has been matched by pcre2_match(). They are:
+
+ pcre2_substring_copy_byname()
+ pcre2_substring_copy_bynumber()
+ pcre2_substring_get_byname()
+ pcre2_substring_get_bynumber()
+ pcre2_substring_list_get()
+ pcre2_substring_length_byname()
+ pcre2_substring_length_bynumber()
+ pcre2_substring_nametable_scan()
+ pcre2_substring_number_from_name()
+
+ pcre2_substring_free() and pcre2_substring_list_free() are also pro-
+ vided, to free memory used for extracted strings. If either of these
+ functions is called with a NULL argument, the function returns immedi-
+ ately without doing anything.
+
+ The function pcre2_substitute() can be called to match a pattern and
+ return a copy of the subject string with substitutions for parts that
+ were matched.
+
+ Functions whose names begin with pcre2_serialize_ are used for saving
+ compiled patterns on disc or elsewhere, and reloading them later.
+
+ Finally, there are functions for finding out information about a com-
+ piled pattern (pcre2_pattern_info()) and about the configuration with
+ which PCRE2 was built (pcre2_config()) and that it is using.
+
+ Functions with names ending with _free() are used for freeing memory
+ blocks of various sorts. In all cases, if one of these functions is
+ called with a NULL argument, it does nothing.
+
+
+STRING LENGTHS AND OFFSETS
+
+ The PCRE2 API uses string lengths and offsets into strings of code
+ units in several places. These values are always of type PCRE2_SIZE,
+ which is an unsigned integer type, currently always defined as size_t.
+ The largest value that can be stored in such a type (that is
+ ~(PCRE2_SIZE)0) is reserved as a special indicator for zero-terminated
+ strings and unset offsets. Therefore, the longest string that can be
+ handled is one less than this maximum. Note that string lengths are al-
+ ways given in code units. Only in the 8-bit library is such a length
+ the same as the number of bytes in the string.
+
+
+NEWLINES
+
+ PCRE2 supports five different conventions for indicating line breaks in
+ strings: a single CR (carriage return) character, a single LF (line-
+ feed) character, the two-character sequence CRLF, any of the three pre-
+ ceding, or any Unicode newline sequence. The Unicode newline sequences
+ are the three just mentioned, plus the single characters VT (vertical
+ tab, U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line
+ separator, U+2028), and PS (paragraph separator, U+2029).
+
+ Each of the first three conventions is used by at least one operating
+ system as its standard newline sequence. When PCRE2 is built, a default
+ can be specified. If it is not, the default is set to LF, which is the
+ Unix standard. However, the newline convention can be changed by an ap-
+ plication when calling pcre2_compile(), or it can be specified by spe-
+ cial text at the start of the pattern itself; this overrides any other
+ settings. See the pcre2pattern page for details of the special charac-
+ ter sequences.
+
+ In the PCRE2 documentation the word "newline" is used to mean "the
+ character or pair of characters that indicate a line break". The choice
+ of newline convention affects the handling of the dot, circumflex, and
+ dollar metacharacters, the handling of #-comments in /x mode, and, when
+ CRLF is a recognized line ending sequence, the match position advance-
+ ment for a non-anchored pattern. There is more detail about this in the
+ section on pcre2_match() options below.
+
+ The choice of newline convention does not affect the interpretation of
+ the \n or \r escape sequences, nor does it affect what \R matches; this
+ has its own separate convention.
+
+
+MULTITHREADING
+
+ In a multithreaded application it is important to keep thread-specific
+ data separate from data that can be shared between threads. The PCRE2
+ library code itself is thread-safe: it contains no static or global
+ variables. The API is designed to be fairly simple for non-threaded ap-
+ plications while at the same time ensuring that multithreaded applica-
+ tions can use it.
+
+ There are several different blocks of data that are used to pass infor-
+ mation between the application and the PCRE2 libraries.
+
+ The compiled pattern
+
+ A pointer to the compiled form of a pattern is returned to the user
+ when pcre2_compile() is successful. The data in the compiled pattern is
+ fixed, and does not change when the pattern is matched. Therefore, it
+ is thread-safe, that is, the same compiled pattern can be used by more
+ than one thread simultaneously. For example, an application can compile
+ all its patterns at the start, before forking off multiple threads that
+ use them. However, if the just-in-time (JIT) optimization feature is
+ being used, it needs separate memory stack areas for each thread. See
+ the pcre2jit documentation for more details.
+
+ In a more complicated situation, where patterns are compiled only when
+ they are first needed, but are still shared between threads, pointers
+ to compiled patterns must be protected from simultaneous writing by
+ multiple threads. This is somewhat tricky to do correctly. If you know
+ that writing to a pointer is atomic in your environment, you can use
+ logic like this:
+
+ Get a read-only (shared) lock (mutex) for pointer
+ if (pointer == NULL)
+ {
+ Get a write (unique) lock for pointer
+ if (pointer == NULL) pointer = pcre2_compile(...
+ }
+ Release the lock
+ Use pointer in pcre2_match()
+
+ Of course, testing for compilation errors should also be included in
+ the code.
+
+ The reason for checking the pointer a second time is as follows: Sev-
+ eral threads may have acquired the shared lock and tested the pointer
+ for being NULL, but only one of them will be given the write lock, with
+ the rest kept waiting. The winning thread will compile the pattern and
+ store the result. After this thread releases the write lock, another
+ thread will get it, and if it does not retest pointer for being NULL,
+ will recompile the pattern and overwrite the pointer, creating a memory
+ leak and possibly causing other issues.
+
+ In an environment where writing to a pointer may not be atomic, the
+ above logic is not sufficient. The thread that is doing the compiling
+ may be descheduled after writing only part of the pointer, which could
+ cause other threads to use an invalid value. Instead of checking the
+ pointer itself, a separate "pointer is valid" flag (that can be updated
+ atomically) must be used:
+
+ Get a read-only (shared) lock (mutex) for pointer
+ if (!pointer_is_valid)
+ {
+ Get a write (unique) lock for pointer
+ if (!pointer_is_valid)
+ {
+ pointer = pcre2_compile(...
+ pointer_is_valid = TRUE
+ }
+ }
+ Release the lock
+ Use pointer in pcre2_match()
+
+ If JIT is being used, but the JIT compilation is not being done immedi-
+ ately (perhaps waiting to see if the pattern is used often enough),
+ similar logic is required. JIT compilation updates a value within the
+ compiled code block, so a thread must gain unique write access to the
+ pointer before calling pcre2_jit_compile(). Alternatively,
+ pcre2_code_copy() or pcre2_code_copy_with_tables() can be used to ob-
+ tain a private copy of the compiled code before calling the JIT com-
+ piler.
+
+ Context blocks
+
+ The next main section below introduces the idea of "contexts" in which
+ PCRE2 functions are called. A context is nothing more than a collection
+ of parameters that control the way PCRE2 operates. Grouping a number of
+ parameters together in a context is a convenient way of passing them to
+ a PCRE2 function without using lots of arguments. The parameters that
+ are stored in contexts are in some sense "advanced features" of the
+ API. Many straightforward applications will not need to use contexts.
+
+ In a multithreaded application, if the parameters in a context are val-
+ ues that are never changed, the same context can be used by all the
+ threads. However, if any thread needs to change any value in a context,
+ it must make its own thread-specific copy.
+
+ Match blocks
+
+ The matching functions need a block of memory for storing the results
+ of a match. This includes details of what was matched, as well as addi-
+ tional information such as the name of a (*MARK) setting. Each thread
+ must provide its own copy of this memory.
+
+
+PCRE2 CONTEXTS
+
+ Some PCRE2 functions have a lot of parameters, many of which are used
+ only by specialist applications, for example, those that use custom
+ memory management or non-standard character tables. To keep function
+ argument lists at a reasonable size, and at the same time to keep the
+ API extensible, "uncommon" parameters are passed to certain functions
+ in a context instead of directly. A context is just a block of memory
+ that holds the parameter values. Applications that do not need to ad-
+ just any of the context parameters can pass NULL when a context pointer
+ is required.
+
+ There are three different types of context: a general context that is
+ relevant for several PCRE2 operations, a compile-time context, and a
+ match-time context.
+
+ The general context
+
+ At present, this context just contains pointers to (and data for) ex-
+ ternal memory management functions that are called from several places
+ in the PCRE2 library. The context is named `general' rather than
+ specifically `memory' because in future other fields may be added. If
+ you do not want to supply your own custom memory management functions,
+ you do not need to bother with a general context. A general context is
+ created by:
+
+ pcre2_general_context *pcre2_general_context_create(
+ void *(*private_malloc)(PCRE2_SIZE, void *),
+ void (*private_free)(void *, void *), void *memory_data);
+
+ The two function pointers specify custom memory management functions,
+ whose prototypes are:
+
+ void *private_malloc(PCRE2_SIZE, void *);
+ void private_free(void *, void *);
+
+ Whenever code in PCRE2 calls these functions, the final argument is the
+ value of memory_data. Either of the first two arguments of the creation
+ function may be NULL, in which case the system memory management func-
+ tions malloc() and free() are used. (This is not currently useful, as
+ there are no other fields in a general context, but in future there
+ might be.) The private_malloc() function is used (if supplied) to ob-
+ tain memory for storing the context, and all three values are saved as
+ part of the context.
+
+ Whenever PCRE2 creates a data block of any kind, the block contains a
+ pointer to the free() function that matches the malloc() function that
+ was used. When the time comes to free the block, this function is
+ called.
+
+ A general context can be copied by calling:
+
+ pcre2_general_context *pcre2_general_context_copy(
+ pcre2_general_context *gcontext);
+
+ The memory used for a general context should be freed by calling:
+
+ void pcre2_general_context_free(pcre2_general_context *gcontext);
+
+ If this function is passed a NULL argument, it returns immediately
+ without doing anything.
+
+ The compile context
+
+ A compile context is required if you want to provide an external func-
+ tion for stack checking during compilation or to change the default
+ values of any of the following compile-time parameters:
+
+ What \R matches (Unicode newlines or CR, LF, CRLF only)
+ PCRE2's character tables
+ The newline character sequence
+ The compile time nested parentheses limit
+ The maximum length of the pattern string
+ The extra options bits (none set by default)
+ Which performance optimizations the compiler should apply
+
+ A compile context is also required if you are using custom memory man-
+ agement. If none of these apply, just pass NULL as the context argu-
+ ment of pcre2_compile().
+
+ A compile context is created, copied, and freed by the following func-
+ tions:
+
+ pcre2_compile_context *pcre2_compile_context_create(
+ pcre2_general_context *gcontext);
+
+ pcre2_compile_context *pcre2_compile_context_copy(
+ pcre2_compile_context *ccontext);
+
+ void pcre2_compile_context_free(pcre2_compile_context *ccontext);
+
+ A compile context is created with default values for its parameters.
+ These can be changed by calling the following functions, which return 0
+ on success, or PCRE2_ERROR_BADDATA if invalid data is detected.
+
+ int pcre2_set_bsr(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+ The value must be PCRE2_BSR_ANYCRLF, to specify that \R matches only
+ CR, LF, or CRLF, or PCRE2_BSR_UNICODE, to specify that \R matches any
+ Unicode line ending sequence. The value is used by the JIT compiler and
+ by the two interpreted matching functions, pcre2_match() and
+ pcre2_dfa_match().
+
+ int pcre2_set_character_tables(pcre2_compile_context *ccontext,
+ const uint8_t *tables);
+
+ The value must be the result of a call to pcre2_maketables(), whose
+ only argument is a general context. This function builds a set of char-
+ acter tables in the current locale.
+
+ int pcre2_set_compile_extra_options(pcre2_compile_context *ccontext,
+ uint32_t extra_options);
+
+ As PCRE2 has developed, almost all the 32 option bits that are avail-
+ able in the options argument of pcre2_compile() have been used up. To
+ avoid running out, the compile context contains a set of extra option
+ bits which are used for some newer, assumed rarer, options. This func-
+ tion sets those bits. It always sets all the bits (either on or off).
+ It does not modify any existing setting. The available options are de-
+ fined in the section entitled "Extra compile options" below.
+
+ int pcre2_set_max_pattern_length(pcre2_compile_context *ccontext,
+ PCRE2_SIZE value);
+
+ This sets a maximum length, in code units, for any pattern string that
+ is compiled with this context. If the pattern is longer, an error is
+ generated. This facility is provided so that applications that accept
+ patterns from external sources can limit their size. The default is the
+ largest number that a PCRE2_SIZE variable can hold, which is effec-
+ tively unlimited.
+
+ int pcre2_set_max_pattern_compiled_length(
+ pcre2_compile_context *ccontext, PCRE2_SIZE value);
+
+ This sets a maximum size, in bytes, for the memory needed to hold the
+ compiled version of a pattern that is compiled with this context. If
+ the pattern needs more memory, an error is generated. This facility is
+ provided so that applications that accept patterns from external
+ sources can limit the amount of memory they use. The default is the
+ largest number that a PCRE2_SIZE variable can hold, which is effec-
+ tively unlimited.
+
+ int pcre2_set_max_varlookbehind(pcre2_compile_contest *ccontext,
+ uint32_t value);
+
+ This sets a maximum length for the number of characters matched by a
+ variable-length lookbehind assertion. The default is set when PCRE2 is
+ built, with the ultimate default being 255, the same as Perl. Lookbe-
+ hind assertions without a bounding length are not supported.
+
+ int pcre2_set_newline(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+ This specifies which characters or character sequences are to be recog-
+ nized as newlines. The value must be one of PCRE2_NEWLINE_CR (carriage
+ return only), PCRE2_NEWLINE_LF (linefeed only), PCRE2_NEWLINE_CRLF (the
+ two-character sequence CR followed by LF), PCRE2_NEWLINE_ANYCRLF (any
+ of the above), PCRE2_NEWLINE_ANY (any Unicode newline sequence), or
+ PCRE2_NEWLINE_NUL (the NUL character, that is a binary zero).
+
+ A pattern can override the value set in the compile context by starting
+ with a sequence such as (*CRLF). See the pcre2pattern page for details.
+
+ When a pattern is compiled with the PCRE2_EXTENDED or PCRE2_EX-
+ TENDED_MORE option, the newline convention affects the recognition of
+ the end of internal comments starting with #. The value is saved with
+ the compiled pattern for subsequent use by the JIT compiler and by the
+ two interpreted matching functions, pcre2_match() and
+ pcre2_dfa_match().
+
+ int pcre2_set_parens_nest_limit(pcre2_compile_context *ccontext,
+ uint32_t value);
+
+ This parameter adjusts the limit, set when PCRE2 is built (default
+ 250), on the depth of parenthesis nesting in a pattern. This limit
+ stops rogue patterns using up too much system stack when being com-
+ piled. The limit applies to parentheses of all kinds, not just captur-
+ ing parentheses.
+
+ int pcre2_set_compile_recursion_guard(pcre2_compile_context *ccontext,
+ int (*guard_function)(uint32_t, void *), void *user_data);
+
+ There is at least one application that runs PCRE2 in threads with very
+ limited system stack, where running out of stack is to be avoided at
+ all costs. The parenthesis limit above cannot take account of how much
+ stack is actually available during compilation. For a finer control,
+ you can supply a function that is called whenever pcre2_compile()
+ starts to compile a parenthesized part of a pattern. This function can
+ check the actual stack size (or anything else that it wants to, of
+ course).
+
+ The first argument to the callout function gives the current depth of
+ nesting, and the second is user data that is set up by the last argu-
+ ment of pcre2_set_compile_recursion_guard(). The callout function
+ should return zero if all is well, or non-zero to force an error.
+
+ int pcre2_set_optimize(pcre2_compile_context *ccontext,
+ uint32_t directive);
+
+ PCRE2 can apply various performance optimizations during compilation,
+ in order to make matching faster. For example, the compiler might con-
+ vert some regex constructs into an equivalent construct which
+ pcre2_match() can execute faster. By default, all available optimiza-
+ tions are enabled. However, in rare cases, one might wish to disable
+ specific optimizations. For example, if it is known that some optimiza-
+ tions cannot benefit a certain regex, it might be desirable to disable
+ them, in order to speed up compilation.
+
+ The permitted values of directive are as follows:
+
+ PCRE2_OPTIMIZATION_FULL
+
+ Enable all optional performance optimizations. This is the default
+ value.
+
+ PCRE2_OPTIMIZATION_NONE
+
+ Disable all optional performance optimizations.
+
+ PCRE2_AUTO_POSSESS
+ PCRE2_AUTO_POSSESS_OFF
+
+ Enable/disable "auto-possessification" of variable quantifiers such as
+ * and +. This optimization, for example, turns a+b into a++b in order
+ to avoid backtracks into a+ that can never be successful. However, if
+ callouts are in use, auto-possessification means that some callouts are
+ never taken. You can disable this optimization if you want the matching
+ functions to do a full, unoptimized search and run all the callouts.
+
+ PCRE2_DOTSTAR_ANCHOR
+ PCRE2_DOTSTAR_ANCHOR_OFF
+
+ Enable/disable an optimization that is applied when .* is the first
+ significant item in a top-level branch of a pattern, and all the other
+ branches also start with .* or with \A or \G or ^. Such a pattern is
+ automatically anchored if PCRE2_DOTALL is set for all the .* items and
+ PCRE2_MULTILINE is not set for any ^ items. Otherwise, the fact that
+ any match must start either at the start of the subject or following a
+ newline is remembered. Like other optimizations, this can cause call-
+ outs to be skipped.
+
+ Dotstar anchor optimization is automatically disabled for .* if it is
+ inside an atomic group or a capture group that is the subject of a
+ backreference, or if the pattern contains (*PRUNE) or (*SKIP).
+
+ PCRE2_START_OPTIMIZE
+ PCRE2_START_OPTIMIZE_OFF
+
+ Enable/disable optimizations which cause matching functions to scan the
+ subject string for specific code unit values before attempting a match.
+ For example, if it is known that an unanchored match must start with a
+ specific value, the matching code searches the subject for that value,
+ and fails immediately if it cannot find it, without actually running
+ the main matching function. This means that a special item such as
+ (*COMMIT) at the start of a pattern is not considered until after a
+ suitable starting point for the match has been found. Also, when call-
+ outs or (*MARK) items are in use, these "start-up" optimizations can
+ cause them to be skipped if the pattern is never actually used. The
+ start-up optimizations are in effect a pre-scan of the subject that
+ takes place before the pattern is run.
+
+ Disabling start-up optimizations ensures that in cases where the result
+ is "no match", the callouts do occur, and that items such as (*COMMIT)
+ and (*MARK) are considered at every possible starting position in the
+ subject string.
+
+ Disabling start-up optimizations may change the outcome of a matching
+ operation. Consider the pattern
+
+ (*COMMIT)ABC
+
+ When this is compiled, PCRE2 records the fact that a match must start
+ with the character "A". Suppose the subject string is "DEFABC". The
+ start-up optimization scans along the subject, finds "A" and runs the
+ first match attempt from there. The (*COMMIT) item means that the pat-
+ tern must match the current starting position, which in this case, it
+ does. However, if the same match is run without start-up optimizations,
+ the initial scan along the subject string does not happen. The first
+ match attempt is run starting from "D" and when this fails, (*COMMIT)
+ prevents any further matches being tried, so the overall result is "no
+ match".
+
+ Another start-up optimization makes use of a minimum length for a
+ matching subject, which is recorded when possible. Consider the pattern
+
+ (*MARK:1)B(*MARK:2)(X|Y)
+
+ The minimum length for a match is two characters. If the subject is
+ "XXBB", the "starting character" optimization skips "XX", then tries to
+ match "BB", which is long enough. In the process, (*MARK:2) is encoun-
+ tered and remembered. When the match attempt fails, the next "B" is
+ found, but there is only one character left, so there are no more at-
+ tempts, and "no match" is returned with the "last mark seen" set to
+ "2". Without start-up optimizations, however, matches are tried at
+ every possible starting position, including at the end of the subject,
+ where (*MARK:1) is encountered, but there is no "B", so the "last mark
+ seen" that is returned is "1". In this case, the optimizations do not
+ affect the overall match result, which is still "no match", but they do
+ affect the auxiliary information that is returned.
+
+ The match context
+
+ A match context is required if you want to:
+
+ Set up a callout function
+ Set an offset limit for matching an unanchored pattern
+ Change the limit on the amount of heap used when matching
+ Change the backtracking match limit
+ Change the backtracking depth limit
+ Set custom memory management specifically for the match
+
+ If none of these apply, just pass NULL as the context argument of
+ pcre2_match(), pcre2_dfa_match(), or pcre2_jit_match().
+
+ A match context is created, copied, and freed by the following func-
+ tions:
+
+ pcre2_match_context *pcre2_match_context_create(
+ pcre2_general_context *gcontext);
+
+ pcre2_match_context *pcre2_match_context_copy(
+ pcre2_match_context *mcontext);
+
+ void pcre2_match_context_free(pcre2_match_context *mcontext);
+
+ A match context is created with default values for its parameters.
+ These can be changed by calling the following functions, which return 0
+ on success, or PCRE2_ERROR_BADDATA if invalid data is detected.
+
+ int pcre2_set_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_callout_block *, void *),
+ void *callout_data);
+
+ This sets up a callout function for PCRE2 to call at specified points
+ during a matching operation. Details are given in the pcre2callout doc-
+ umentation.
+
+ int pcre2_set_substitute_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_substitute_callout_block *, void *),
+ void *callout_data);
+
+ This sets up a callout function for PCRE2 to call after each substitu-
+ tion made by pcre2_substitute(). Details are given in the section enti-
+ tled "Creating a new string with substitutions" below.
+
+ int pcre2_set_substitute_case_callout(pcre2_match_context *mcontext,
+ PCRE2_SIZE (*callout_function)(PCRE2_SPTR, PCRE2_SIZE,
+ PCRE2_UCHAR *, PCRE2_SIZE,
+ int, void *),
+ void *callout_data);
+
+ This sets up a callout function for PCRE2 to call when performing case
+ transformations inside pcre2_substitute(). Details are given in the
+ section entitled "Creating a new string with substitutions" below.
+
+ int pcre2_set_offset_limit(pcre2_match_context *mcontext,
+ PCRE2_SIZE value);
+
+ The offset_limit parameter limits how far an unanchored search can ad-
+ vance in the subject string. The default value is PCRE2_UNSET. The
+ pcre2_match() and pcre2_dfa_match() functions return PCRE2_ERROR_NO-
+ MATCH if a match with a starting point before or at the given offset is
+ not found. The pcre2_substitute() function makes no more substitutions.
+
+ For example, if the pattern /abc/ is matched against "123abc" with an
+ offset limit less than 3, the result is PCRE2_ERROR_NOMATCH. A match
+ can never be found if the startoffset argument of pcre2_match(),
+ pcre2_dfa_match(), or pcre2_substitute() is greater than the offset
+ limit set in the match context.
+
+ When using this facility, you must set the PCRE2_USE_OFFSET_LIMIT op-
+ tion when calling pcre2_compile() so that when JIT is in use, different
+ code can be compiled. If a match is started with a non-default match
+ limit when PCRE2_USE_OFFSET_LIMIT is not set, an error is generated.
+
+ The offset limit facility can be used to track progress when searching
+ large subject strings or to limit the extent of global substitutions.
+ See also the PCRE2_FIRSTLINE option, which requires a match to start
+ before or at the first newline that follows the start of matching in
+ the subject. If this is set with an offset limit, a match must occur in
+ the first line and also within the offset limit. In other words,
+ whichever limit comes first is used.
+
+ int pcre2_set_heap_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+ The heap_limit parameter specifies, in units of kibibytes (1024 bytes),
+ the maximum amount of heap memory that pcre2_match() may use to hold
+ backtracking information when running an interpretive match. This limit
+ also applies to pcre2_dfa_match(), which may use the heap when process-
+ ing patterns with a lot of nested pattern recursion or lookarounds or
+ atomic groups. This limit does not apply to matching with the JIT opti-
+ mization, which has its own memory control arrangements (see the
+ pcre2jit documentation for more details). If the limit is reached, the
+ negative error code PCRE2_ERROR_HEAPLIMIT is returned. The default
+ limit can be set when PCRE2 is built; if it is not, the default is set
+ very large and is essentially unlimited.
+
+ A value for the heap limit may also be supplied by an item at the start
+ of a pattern of the form
+
+ (*LIMIT_HEAP=ddd)
+
+ where ddd is a decimal number. However, such a setting is ignored un-
+ less ddd is less than the limit set by the caller of pcre2_match() or,
+ if no such limit is set, less than the default.
+
+ The pcre2_match() function always needs some heap memory, so setting a
+ value of zero guarantees a "heap limit exceeded" error. Details of how
+ pcre2_match() uses the heap are given in the pcre2perform documenta-
+ tion.
+
+ For pcre2_dfa_match(), a vector on the system stack is used when pro-
+ cessing pattern recursions, lookarounds, or atomic groups, and only if
+ this is not big enough is heap memory used. In this case, setting a
+ value of zero disables the use of the heap.
+
+ int pcre2_set_match_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+ The match_limit parameter provides a means of preventing PCRE2 from us-
+ ing up too many computing resources when processing patterns that are
+ not going to match, but which have a very large number of possibilities
+ in their search trees. The classic example is a pattern that uses
+ nested unlimited repeats.
+
+ There is an internal counter in pcre2_match() that is incremented each
+ time round its main matching loop. If this value reaches the match
+ limit, pcre2_match() returns the negative value PCRE2_ERROR_MATCHLIMIT.
+ This has the effect of limiting the amount of backtracking that can
+ take place. For patterns that are not anchored, the count restarts from
+ zero for each position in the subject string. This limit also applies
+ to pcre2_dfa_match(), though the counting is done in a different way.
+
+ When pcre2_match() is called with a pattern that was successfully
+ processed by pcre2_jit_compile(), the way in which matching is executed
+ is entirely different. However, there is still the possibility of run-
+ away matching that goes on for a very long time, and so the match_limit
+ value is also used in this case (but in a different way) to limit how
+ long the matching can continue.
+
+ The default value for the limit can be set when PCRE2 is built; the de-
+ fault is 10 million, which handles all but the most extreme cases. A
+ value for the match limit may also be supplied by an item at the start
+ of a pattern of the form
+
+ (*LIMIT_MATCH=ddd)
+
+ where ddd is a decimal number. However, such a setting is ignored un-
+ less ddd is less than the limit set by the caller of pcre2_match() or
+ pcre2_dfa_match() or, if no such limit is set, less than the default.
+
+ int pcre2_set_depth_limit(pcre2_match_context *mcontext,
+ uint32_t value);
+
+ This parameter limits the depth of nested backtracking in
+ pcre2_match(). Each time a nested backtracking point is passed, a new
+ memory frame is used to remember the state of matching at that point.
+ Thus, this parameter indirectly limits the amount of memory that is
+ used in a match. However, because the size of each memory frame depends
+ on the number of capturing parentheses, the actual memory limit varies
+ from pattern to pattern. This limit was more useful in versions before
+ 10.30, where function recursion was used for backtracking.
+
+ The depth limit is not relevant, and is ignored, when matching is done
+ using JIT compiled code. However, it is supported by pcre2_dfa_match(),
+ which uses it to limit the depth of nested internal recursive function
+ calls that implement atomic groups, lookaround assertions, and pattern
+ recursions. This limits, indirectly, the amount of system stack that is
+ used. It was more useful in versions before 10.32, when stack memory
+ was used for local workspace vectors for recursive function calls. From
+ version 10.32, only local variables are allocated on the stack and as
+ each call uses only a few hundred bytes, even a small stack can support
+ quite a lot of recursion.
+
+ If the depth of internal recursive function calls is great enough, lo-
+ cal workspace vectors are allocated on the heap from version 10.32 on-
+ wards, so the depth limit also indirectly limits the amount of heap
+ memory that is used. A recursive pattern such as /(.(?2))((?1)|)/, when
+ matched to a very long string using pcre2_dfa_match(), can use a great
+ deal of memory. However, it is probably better to limit heap usage di-
+ rectly by calling pcre2_set_heap_limit().
+
+ The default value for the depth limit can be set when PCRE2 is built;
+ if it is not, the default is set to the same value as the default for
+ the match limit. If the limit is exceeded, pcre2_match() or
+ pcre2_dfa_match() returns PCRE2_ERROR_DEPTHLIMIT. A value for the depth
+ limit may also be supplied by an item at the start of a pattern of the
+ form
+
+ (*LIMIT_DEPTH=ddd)
+
+ where ddd is a decimal number. However, such a setting is ignored un-
+ less ddd is less than the limit set by the caller of pcre2_match() or
+ pcre2_dfa_match() or, if no such limit is set, less than the default.
+
+
+CHECKING BUILD-TIME OPTIONS
+
+ int pcre2_config(uint32_t what, void *where);
+
+ The function pcre2_config() makes it possible for a PCRE2 client to
+ find the value of certain configuration parameters and to discover
+ which optional features have been compiled into the PCRE2 library. The
+ pcre2build documentation has more details about these features.
+
+ The first argument for pcre2_config() specifies which information is
+ required. The second argument is a pointer to memory into which the in-
+ formation is placed. If NULL is passed, the function returns the amount
+ of memory that is needed for the requested information. For calls that
+ return numerical values, the value is in bytes; when requesting these
+ values, where should point to appropriately aligned memory. For calls
+ that return strings, the required length is given in code units, not
+ counting the terminating zero.
+
+ When requesting information, the returned value from pcre2_config() is
+ non-negative on success, or the negative error code PCRE2_ERROR_BADOP-
+ TION if the value in the first argument is not recognized. The follow-
+ ing information is available:
+
+ PCRE2_CONFIG_BSR
+
+ The output is a uint32_t integer whose value indicates what character
+ sequences the \R escape sequence matches by default. A value of
+ PCRE2_BSR_UNICODE means that \R matches any Unicode line ending se-
+ quence; a value of PCRE2_BSR_ANYCRLF means that \R matches only CR, LF,
+ or CRLF. The default can be overridden when a pattern is compiled.
+
+ PCRE2_CONFIG_COMPILED_WIDTHS
+
+ The output is a uint32_t integer whose lower bits indicate which code
+ unit widths were selected when PCRE2 was built. The 1-bit indicates
+ 8-bit support, and the 2-bit and 4-bit indicate 16-bit and 32-bit sup-
+ port, respectively.
+
+ PCRE2_CONFIG_DEPTHLIMIT
+
+ The output is a uint32_t integer that gives the default limit for the
+ depth of nested backtracking in pcre2_match() or the depth of nested
+ recursions, lookarounds, and atomic groups in pcre2_dfa_match(). Fur-
+ ther details are given with pcre2_set_depth_limit() above.
+
+ PCRE2_CONFIG_EFFECTIVE_LINKSIZE
+
+ The output is a uint32_t integer that contains the number of bytes the
+ library uses for internal linkage in compiled regular expressions. Its
+ value is derived from the value that was provided at build time and
+ that is described below by PCRE2_CONFIG_LINKSIZE.
+
+ PCRE2_CONFIG_HEAPLIMIT
+
+ The output is a uint32_t integer that gives, in kibibytes, the default
+ limit for the amount of heap memory used by pcre2_match() or
+ pcre2_dfa_match(). Further details are given with
+ pcre2_set_heap_limit() above.
+
+ PCRE2_CONFIG_JIT
+
+ The output is a uint32_t integer that is set to one if support for
+ just-in-time compiling is included in the library; otherwise it is set
+ to zero. Note that having the support in the library does not guarantee
+ that JIT will be used for any given match, and neither does it guaran-
+ tee that JIT will actually be able to function, because it may not be
+ able to allocate executable memory in some environments. There is a
+ special call to pcre2_jit_compile() that can be used to check this. See
+ the pcre2jit documentation for more details.
+
+ PCRE2_CONFIG_JITTARGET
+
+ The where argument should point to a code-unit-aligned buffer. All pre-
+ vious versions of PCRE2 have required no more than 128 code units of
+ buffer capacity. However, this requirement is not guaranteed to be
+ maintained, so applications should call pcre2_config() with where set
+ to NULL to receive the required buffer size, then assert or allocate a
+ suitably-size buffer for a second call to pcre2_config(). The buffer is
+ filled with a string that contains the name of the architecture for
+ which the JIT compiler is configured at build time, for example, a
+ 64-bit ARM CPU that supports the Armv8.1 extension writes "ARM-64 (LSE)
+ 64bit (little endian + unaligned)". If JIT support is not available,
+ PCRE2_ERROR_BADOPTION is returned; otherwise the number of code units
+ used is returned. This is the length of the string plus one unit for
+ the terminating zero.
+
+ PCRE2_CONFIG_LINKSIZE
+
+ The output is a uint32_t integer that contains the number of bytes the
+ library was instructed to use for internal linkage in compiled regular
+ expressions. When PCRE2 is configured, the value can be set to 2, 3,
+ or 4, with the default being 2 for most libraries.
+
+ The actual number of bytes used depends on the size of the code units
+ that the library supports and can be higher. See PCRE2_CONFIG_EFFEC-
+ TIVE_LINKSIZE above for details.
+
+ The default value of 2 for the 8-bit and 16-bit libraries is sufficient
+ for all but the most massive patterns, since it allows the size of the
+ compiled pattern to be up to 65535 code units. Larger values allow
+ larger regular expressions to be compiled by those two libraries, but
+ at the expense of slower matching.
+
+ PCRE2_CONFIG_MATCHLIMIT
+
+ The output is a uint32_t integer that gives the default match limit for
+ pcre2_match(). Further details are given with pcre2_set_match_limit()
+ above.
+
+ PCRE2_CONFIG_NEWLINE
+
+ The output is a uint32_t integer whose value specifies the default
+ character sequence that is recognized as meaning "newline". The values
+ are:
+
+ PCRE2_NEWLINE_CR Carriage return (CR)
+ PCRE2_NEWLINE_LF Linefeed (LF)
+ PCRE2_NEWLINE_CRLF Carriage return, linefeed (CRLF)
+ PCRE2_NEWLINE_ANY Any Unicode line ending
+ PCRE2_NEWLINE_ANYCRLF Any of CR, LF, or CRLF
+ PCRE2_NEWLINE_NUL The NUL character (binary zero)
+
+ The default should normally correspond to the standard sequence for
+ your operating system.
+
+ PCRE2_CONFIG_NEVER_BACKSLASH_C
+
+ The output is a uint32_t integer that is set to one if the use of \C
+ was permanently disabled when PCRE2 was built; otherwise it is set to
+ zero.
+
+ PCRE2_CONFIG_PARENSLIMIT
+
+ The output is a uint32_t integer that gives the maximum depth of nest-
+ ing of parentheses (of any kind) in a pattern. This limit is imposed to
+ cap the amount of system stack used when a pattern is compiled. It is
+ specified when PCRE2 is built; the default is 250. This limit does not
+ take into account the stack that may already be used by the calling ap-
+ plication. For finer control over compilation stack usage, see
+ pcre2_set_compile_recursion_guard().
+
+ PCRE2_CONFIG_STACKRECURSE
+
+ This parameter is obsolete and should not be used in new code. The out-
+ put is a uint32_t integer that is always set to zero.
+
+ PCRE2_CONFIG_TABLES_LENGTH
+
+ The output is a uint32_t integer that gives the length of PCRE2's char-
+ acter processing tables in bytes. For details of these tables see the
+ section on locale support below.
+
+ PCRE2_CONFIG_UNICODE_VERSION
+
+ The where argument should point to a code-unit-aligned buffer. All pre-
+ vious versions of PCRE2 have required no more than 24 code units of
+ buffer capacity. However, applications should call pcre2_config() with
+ where set to NULL to receive the required buffer size, then assert or
+ allocate a suitably-size buffer for a second call to pcre2_config(). If
+ PCRE2 has been compiled without Unicode support, the buffer is filled
+ with the text "Unicode not supported". Otherwise, the Unicode version
+ string (for example, "8.0.0") is written. The number of code units used
+ is returned. This is the length of the string plus one unit for the
+ terminating zero.
+
+ PCRE2_CONFIG_UNICODE
+
+ The output is a uint32_t integer that is set to one if Unicode support
+ is available; otherwise it is set to zero. Unicode support implies UTF
+ support.
+
+ PCRE2_CONFIG_VERSION
+
+ The where argument should point to a code-unit-aligned buffer. All pre-
+ vious versions of PCRE2 have required no more than 24 code units of
+ buffer capacity. However, applications should call pcre2_config() with
+ where set to NULL to receive the required buffer size, then assert or
+ allocate a suitably-size buffer for a second call to pcre2_config().
+ The buffer is filled with the PCRE2 version string, zero-terminated.
+ The number of code units used is returned. This is the length of the
+ string plus one unit for the terminating zero.
+
+
+COMPILING A PATTERN
+
+ pcre2_code *pcre2_compile(PCRE2_SPTR pattern, PCRE2_SIZE length,
+ uint32_t options, int *errorcode, PCRE2_SIZE *erroroffset,
+ pcre2_compile_context *ccontext);
+
+ void pcre2_code_free(pcre2_code *code);
+
+ pcre2_code *pcre2_code_copy(const pcre2_code *code);
+
+ pcre2_code *pcre2_code_copy_with_tables(const pcre2_code *code);
+
+ The pcre2_compile() function compiles a pattern into an internal form.
+ The pattern is defined by a pointer to a string of code units and a
+ length in code units. If the pattern is zero-terminated, the length can
+ be specified as PCRE2_ZERO_TERMINATED. A NULL pattern pointer with a
+ length of zero is treated as an empty string (NULL with a non-zero
+ length causes an error return). The function returns a pointer to a
+ block of memory that contains the compiled pattern and related data, or
+ NULL if an error occurred.
+
+ If the compile context argument ccontext is NULL, memory for the com-
+ piled pattern is obtained by calling malloc(). Otherwise, it is ob-
+ tained from the same memory function that was used for the compile con-
+ text. The caller must free the memory by calling pcre2_code_free() when
+ it is no longer needed. If pcre2_code_free() is called with a NULL ar-
+ gument, it returns immediately, without doing anything.
+
+ The function pcre2_code_copy() makes a copy of the compiled code in new
+ memory, using the same memory allocator as was used for the original.
+ However, if the code has been processed by the JIT compiler (see be-
+ low), the JIT information cannot be copied (because it is position-de-
+ pendent). The new copy can initially be used only for non-JIT match-
+ ing, though it can be passed to pcre2_jit_compile() if required. If
+ pcre2_code_copy() is called with a NULL argument, it returns NULL.
+
+ The pcre2_code_copy() function provides a way for individual threads in
+ a multithreaded application to acquire a private copy of shared com-
+ piled code. However, it does not make a copy of the character tables
+ used by the compiled pattern; the new pattern code points to the same
+ tables as the original code. (See "Locale Support" below for details
+ of these character tables.) In many applications the same tables are
+ used throughout, so this behaviour is appropriate. Nevertheless, there
+ are occasions when a copy of a compiled pattern and the relevant tables
+ are needed. The pcre2_code_copy_with_tables() provides this facility.
+ Copies of both the code and the tables are made, with the new code
+ pointing to the new tables. The memory for the new tables is automati-
+ cally freed when pcre2_code_free() is called for the new copy of the
+ compiled code. If pcre2_code_copy_with_tables() is called with a NULL
+ argument, it returns NULL.
+
+ NOTE: When one of the matching functions is called, pointers to the
+ compiled pattern and the subject string are set in the match data block
+ so that they can be referenced by the substring extraction functions
+ after a successful match. After running a match, you must not free a
+ compiled pattern or a subject string until after all operations on the
+ match data block have taken place, unless, in the case of the subject
+ string, you have used the PCRE2_COPY_MATCHED_SUBJECT option, which is
+ described in the section entitled "Option bits for pcre2_match()" be-
+ low.
+
+ The options argument for pcre2_compile() contains various bit settings
+ that affect the compilation. It should be zero if none of them are re-
+ quired. The available options are described below. Some of them (in
+ particular, those that are compatible with Perl, but some others as
+ well) can also be set and unset from within the pattern (see the de-
+ tailed description in the pcre2pattern documentation).
+
+ For those options that can be different in different parts of the pat-
+ tern, the contents of the options argument specifies their settings at
+ the start of compilation. The PCRE2_ANCHORED, PCRE2_ENDANCHORED, and
+ PCRE2_NO_UTF_CHECK options can be set at the time of matching as well
+ as at compile time.
+
+ Some additional options and less frequently required compile-time para-
+ meters (for example, the newline setting) can be provided in a compile
+ context (as described above).
+
+ If errorcode or erroroffset is NULL, pcre2_compile() returns NULL imme-
+ diately. Otherwise, the variables to which these point are set to an
+ error code and an offset (number of code units) within the pattern, re-
+ spectively, when pcre2_compile() returns NULL because a compilation er-
+ ror has occurred.
+
+ There are over 100 positive error codes that pcre2_compile() may return
+ if it finds an error in the pattern. There are also some negative error
+ codes that are used for invalid UTF strings when validity checking is
+ in force. These are the same as given by pcre2_match() and
+ pcre2_dfa_match(), and are described in the pcre2unicode documentation.
+ There is no separate documentation for the positive error codes, be-
+ cause the textual error messages that are obtained by calling the
+ pcre2_get_error_message() function (see "Obtaining a textual error mes-
+ sage" below) should be self-explanatory. Macro names starting with
+ PCRE2_ERROR_ are defined for both positive and negative error codes in
+ pcre2.h. When compilation is successful errorcode is set to a value
+ that returns the message "no error" if passed to pcre2_get_error_mes-
+ sage().
+
+ The value returned in erroroffset is an indication of where in the pat-
+ tern an error occurred. When there is no error, zero is returned. A
+ non-zero value is not necessarily the furthest point in the pattern
+ that was read. For example, after the error "lookbehind assertion is
+ not fixed length", the error offset points to the start of the failing
+ assertion. For an invalid UTF-8 or UTF-16 string, the offset is that of
+ the first code unit of the failing character.
+
+ Some errors are not detected until the whole pattern has been scanned;
+ in these cases, the offset passed back is the length of the pattern.
+ Note that the offset is in code units, not characters, even in a UTF
+ mode. It may sometimes point into the middle of a UTF-8 or UTF-16 char-
+ acter.
+
+ This code fragment shows a typical straightforward call to pcre2_com-
+ pile():
+
+ pcre2_code *re;
+ PCRE2_SIZE erroffset;
+ int errorcode;
+ re = pcre2_compile(
+ "^A.*Z", /* the pattern */
+ PCRE2_ZERO_TERMINATED, /* the pattern is zero-terminated */
+ 0, /* default options */
+ &errorcode, /* for error code */
+ &erroffset, /* for error offset */
+ NULL); /* no compile context */
+
+
+ Main compile options
+
+ The following names for option bits are defined in the pcre2.h header
+ file:
+
+ PCRE2_ANCHORED
+
+ If this bit is set, the pattern is forced to be "anchored", that is, it
+ is constrained to match only at the first matching point in the string
+ that is being searched (the "subject string"). This effect can also be
+ achieved by appropriate constructs in the pattern itself, which is the
+ only way to do it in Perl.
+
+ PCRE2_ALLOW_EMPTY_CLASS
+
+ By default, for compatibility with Perl, a closing square bracket that
+ immediately follows an opening one is treated as a data character for
+ the class. When PCRE2_ALLOW_EMPTY_CLASS is set, it terminates the
+ class, which therefore contains no characters and so can never match.
+
+ PCRE2_ALT_BSUX
+
+ This option request alternative handling of three escape sequences,
+ which makes PCRE2's behaviour more like ECMAscript (aka JavaScript).
+ When it is set:
+
+ (1) \U matches an upper case "U" character; by default \U causes a com-
+ pile time error (Perl uses \U to upper case subsequent characters).
+
+ (2) \u matches a lower case "u" character unless it is followed by four
+ hexadecimal digits, in which case the hexadecimal number defines the
+ code point to match. By default, \u causes a compile time error (Perl
+ uses it to upper case the following character).
+
+ (3) \x matches a lower case "x" character unless it is followed by two
+ hexadecimal digits, in which case the hexadecimal number defines the
+ code point to match. By default, as in Perl, a hexadecimal number is
+ always expected after \x, but it may have one or two digits.
+
+ ECMAscript 6 added additional functionality to \u. This can be accessed
+ using the PCRE2_EXTRA_ALT_BSUX extra option (see "Extra compile op-
+ tions" below). Note that this alternative escape handling applies only
+ to patterns. Neither of these options affects the processing of re-
+ placement strings passed to pcre2_substitute().
+
+ PCRE2_ALT_CIRCUMFLEX
+
+ In multiline mode (when PCRE2_MULTILINE is set), the circumflex
+ metacharacter matches at the start of the subject (unless PCRE2_NOTBOL
+ is set), and also after any internal newline. However, it does not
+ match after a newline at the end of the subject, for compatibility with
+ Perl. If you want a multiline circumflex also to match after a termi-
+ nating newline, you must set PCRE2_ALT_CIRCUMFLEX.
+
+ PCRE2_ALT_EXTENDED_CLASS
+
+ Alters the parsing of character classes to follow the extended syntax
+ described by Unicode UTS#18. The PCRE2_ALT_EXTENDED_CLASS option has no
+ impact on the behaviour of the Perl-specific "(?[...])" syntax for ex-
+ tended classes, but instead enables the alternative syntax of extended
+ class behaviour inside ordinary "[...]" character classes. See the
+ pcre2pattern documentation for details of the character classes sup-
+ ported.
+
+ PCRE2_ALT_VERBNAMES
+
+ By default, for compatibility with Perl, the name in any verb sequence
+ such as (*MARK:NAME) is any sequence of characters that does not in-
+ clude a closing parenthesis. The name is not processed in any way, and
+ it is not possible to include a closing parenthesis in the name. How-
+ ever, if the PCRE2_ALT_VERBNAMES option is set, normal backslash pro-
+ cessing is applied to verb names and only an unescaped closing paren-
+ thesis terminates the name. A closing parenthesis can be included in a
+ name either as \) or between \Q and \E. If the PCRE2_EXTENDED or
+ PCRE2_EXTENDED_MORE option is set with PCRE2_ALT_VERBNAMES, unescaped
+ white space in verb names is skipped and #-comments are recognized, ex-
+ actly as in the rest of the pattern.
+
+ PCRE2_AUTO_CALLOUT
+
+ If this bit is set, pcre2_compile() automatically inserts callout
+ items, all with number 255, before each pattern item, except immedi-
+ ately before or after an explicit callout in the pattern. For discus-
+ sion of the callout facility, see the pcre2callout documentation.
+
+ PCRE2_CASELESS
+
+ If this bit is set, letters in the pattern match both upper and lower
+ case letters in the subject. It is equivalent to Perl's /i option, and
+ it can be changed within a pattern by a (?i) option setting. If either
+ PCRE2_UTF or PCRE2_UCP is set, Unicode properties are used for all
+ characters with more than one other case, and for all characters whose
+ code points are greater than U+007F.
+
+ Note that there are two ASCII characters, K and S, that, in addition to
+ their lower case ASCII equivalents, are case-equivalent with U+212A
+ (Kelvin sign) and U+017F (long S) respectively. If you do not want this
+ case equivalence, you can suppress it by setting PCRE2_EXTRA_CASE-
+ LESS_RESTRICT.
+
+ One language family, Turkish and Azeri, has its own case-insensitivity
+ rules, which can be selected by setting PCRE2_EXTRA_TURKISH_CASING.
+ This alters the behaviour of the 'i', 'I', U+0130 (capital I with dot
+ above), and U+0131 (small dotless i) characters.
+
+ For lower valued characters with only one other case, a lookup table is
+ used for speed. When neither PCRE2_UTF nor PCRE2_UCP is set, a lookup
+ table is used for all code points less than 256, and higher code points
+ (available only in 16-bit or 32-bit mode) are treated as not having an-
+ other case.
+
+ From release 10.45 PCRE2_CASELESS also affects what some of the letter-
+ related Unicode property escapes (\p and \P) match. The properties Lu
+ (upper case letter), Ll (lower case letter), and Lt (title case letter)
+ are all treated as LC (cased letter) when PCRE2_CASELESS is set.
+
+ PCRE2_DOLLAR_ENDONLY
+
+ If this bit is set, a dollar metacharacter in the pattern matches only
+ at the end of the subject string. Without this option, a dollar also
+ matches immediately before a newline at the end of the string (but not
+ before any other newlines). The PCRE2_DOLLAR_ENDONLY option is ignored
+ if PCRE2_MULTILINE is set. There is no equivalent to this option in
+ Perl, and no way to set it within a pattern.
+
+ PCRE2_DOTALL
+
+ If this bit is set, a dot metacharacter in the pattern matches any
+ character, including one that indicates a newline. However, it only
+ ever matches one character, even if newlines are coded as CRLF. Without
+ this option, a dot does not match when the current position in the sub-
+ ject is at a newline. This option is equivalent to Perl's /s option,
+ and it can be changed within a pattern by a (?s) option setting. A neg-
+ ative class such as [^a] always matches newline characters, and the \N
+ escape sequence always matches a non-newline character, independent of
+ the setting of PCRE2_DOTALL.
+
+ PCRE2_DUPNAMES
+
+ If this bit is set, names used to identify capture groups need not be
+ unique. This can be helpful for certain types of pattern when it is
+ known that only one instance of the named group can ever be matched.
+ There are more details of named capture groups below; see also the
+ pcre2pattern documentation.
+
+ PCRE2_ENDANCHORED
+
+ If this bit is set, the end of any pattern match must be right at the
+ end of the string being searched (the "subject string"). If the pattern
+ match succeeds by reaching (*ACCEPT), but does not reach the end of the
+ subject, the match fails at the current starting point. For unanchored
+ patterns, a new match is then tried at the next starting point. How-
+ ever, if the match succeeds by reaching the end of the pattern, but not
+ the end of the subject, backtracking occurs and an alternative match
+ may be found. Consider these two patterns:
+
+ .(*ACCEPT)|..
+ .|..
+
+ If matched against "abc" with PCRE2_ENDANCHORED set, the first matches
+ "c" whereas the second matches "bc". The effect of PCRE2_ENDANCHORED
+ can also be achieved by appropriate constructs in the pattern itself,
+ which is the only way to do it in Perl.
+
+ For DFA matching with pcre2_dfa_match(), PCRE2_ENDANCHORED applies only
+ to the first (that is, the longest) matched string. Other parallel
+ matches, which are necessarily substrings of the first one, must obvi-
+ ously end before the end of the subject.
+
+ PCRE2_EXTENDED
+
+ If this bit is set, most white space characters in the pattern are to-
+ tally ignored except when escaped, inside a character class, or inside
+ a \Q...\E sequence. However, white space is not allowed within se-
+ quences such as (?> that introduce various parenthesized groups, nor
+ within numerical quantifiers such as {1,3}. Ignorable white space is
+ permitted between an item and a following quantifier and between a
+ quantifier and a following + that indicates possessiveness. PCRE2_EX-
+ TENDED is equivalent to Perl's /x option, and it can be changed within
+ a pattern by a (?x) option setting.
+
+ When PCRE2 is compiled without Unicode support, PCRE2_EXTENDED recog-
+ nizes as white space only those characters with code points less than
+ 256 that are flagged as white space in its low-character table. The ta-
+ ble is normally created by pcre2_maketables(), which uses the isspace()
+ function to identify space characters. In most ASCII environments, the
+ relevant characters are those with code points 0x0009 (tab), 0x000A
+ (linefeed), 0x000B (vertical tab), 0x000C (formfeed), 0x000D (carriage
+ return), and 0x0020 (space).
+
+ When PCRE2 is compiled with Unicode support, in addition to these char-
+ acters, five more Unicode "Pattern White Space" characters are recog-
+ nized by PCRE2_EXTENDED. These are U+0085 (next line), U+200E (left-to-
+ right mark), U+200F (right-to-left mark), U+2028 (line separator), and
+ U+2029 (paragraph separator). This set of characters is the same as
+ recognized by Perl's /x option. Note that the horizontal and vertical
+ space characters that are matched by the \h and \v escapes in patterns
+ are a much bigger set.
+
+ As well as ignoring most white space, PCRE2_EXTENDED also causes char-
+ acters between an unescaped # outside a character class and the next
+ newline, inclusive, to be ignored, which makes it possible to include
+ comments inside complicated patterns. Note that the end of this type of
+ comment is a literal newline sequence in the pattern; escape sequences
+ that happen to represent a newline do not count.
+
+ Which characters are interpreted as newlines can be specified by a set-
+ ting in the compile context that is passed to pcre2_compile() or by a
+ special sequence at the start of the pattern, as described in the sec-
+ tion entitled "Newline conventions" in the pcre2pattern documentation.
+ A default is defined when PCRE2 is built.
+
+ PCRE2_EXTENDED_MORE
+
+ This option has the effect of PCRE2_EXTENDED, but, in addition, un-
+ escaped space and horizontal tab characters are ignored inside a char-
+ acter class. Note: only these two characters are ignored, not the full
+ set of pattern white space characters that are ignored outside a char-
+ acter class. PCRE2_EXTENDED_MORE is equivalent to Perl's /xx option,
+ and it can be changed within a pattern by a (?xx) option setting.
+
+ PCRE2_FIRSTLINE
+
+ If this option is set, the start of an unanchored pattern match must be
+ before or at the first newline in the subject string following the
+ start of matching, though the matched text may continue over the new-
+ line. If startoffset is non-zero, the limiting newline is not necessar-
+ ily the first newline in the subject. For example, if the subject
+ string is "abc\nxyz" (where \n represents a single-character newline) a
+ pattern match for "yz" succeeds with PCRE2_FIRSTLINE if startoffset is
+ greater than 3. See also PCRE2_USE_OFFSET_LIMIT, which provides a more
+ general limiting facility. If PCRE2_FIRSTLINE is set with an offset
+ limit, a match must occur in the first line and also within the offset
+ limit. In other words, whichever limit comes first is used. This option
+ has no effect for anchored patterns.
+
+ PCRE2_LITERAL
+
+ If this option is set, all meta-characters in the pattern are disabled,
+ and it is treated as a literal string. Matching literal strings with a
+ regular expression engine is not the most efficient way of doing it. If
+ you are doing a lot of literal matching and are worried about effi-
+ ciency, you should consider using other approaches. The only other main
+ options that are allowed with PCRE2_LITERAL are: PCRE2_ANCHORED,
+ PCRE2_ENDANCHORED, PCRE2_AUTO_CALLOUT, PCRE2_CASELESS, PCRE2_FIRSTLINE,
+ PCRE2_MATCH_INVALID_UTF, PCRE2_NO_START_OPTIMIZE, PCRE2_NO_UTF_CHECK,
+ PCRE2_UTF, and PCRE2_USE_OFFSET_LIMIT. The extra options PCRE2_EX-
+ TRA_MATCH_LINE and PCRE2_EXTRA_MATCH_WORD are also supported. Any other
+ options cause an error.
+
+ PCRE2_MATCH_INVALID_UTF
+
+ This option forces PCRE2_UTF (see below) and also enables support for
+ matching by pcre2_match() in subject strings that contain invalid UTF
+ sequences. Note, however, that the 16-bit and 32-bit PCRE2 libraries
+ process strings as sequences of uint16_t or uint32_t code points. They
+ cannot find valid UTF sequences within an arbitrary string of bytes un-
+ less such sequences are suitably aligned. This facility is not sup-
+ ported for DFA matching. For details, see the pcre2unicode documenta-
+ tion.
+
+ PCRE2_MATCH_UNSET_BACKREF
+
+ If this option is set, a backreference to an unset capture group
+ matches an empty string (by default this causes the current matching
+ alternative to fail). A pattern such as (\1)(a) succeeds when this op-
+ tion is set (assuming it can find an "a" in the subject), whereas it
+ fails by default, for Perl compatibility. Setting this option makes
+ PCRE2 behave more like ECMAscript (aka JavaScript).
+
+ PCRE2_MULTILINE
+
+ By default, for the purposes of matching "start of line" and "end of
+ line", PCRE2 treats the subject string as consisting of a single line
+ of characters, even if it actually contains newlines. The "start of
+ line" metacharacter (^) matches only at the start of the string, and
+ the "end of line" metacharacter ($) matches only at the end of the
+ string, or before a terminating newline (except when PCRE2_DOLLAR_EN-
+ DONLY is set). Note, however, that unless PCRE2_DOTALL is set, the "any
+ character" metacharacter (.) does not match at a newline. This behav-
+ iour (for ^, $, and dot) is the same as Perl.
+
+ When PCRE2_MULTILINE it is set, the "start of line" and "end of line"
+ constructs match immediately following or immediately before internal
+ newlines in the subject string, respectively, as well as at the very
+ start and end. This is equivalent to Perl's /m option, and it can be
+ changed within a pattern by a (?m) option setting. Note that the "start
+ of line" metacharacter does not match after a newline at the end of the
+ subject, for compatibility with Perl. However, you can change this by
+ setting the PCRE2_ALT_CIRCUMFLEX option. If there are no newlines in a
+ subject string, or no occurrences of ^ or $ in a pattern, setting
+ PCRE2_MULTILINE has no effect.
+
+ PCRE2_NEVER_BACKSLASH_C
+
+ This option locks out the use of \C in the pattern that is being com-
+ piled. This escape can cause unpredictable behaviour in UTF-8 or
+ UTF-16 modes, because it may leave the current matching point in the
+ middle of a multi-code-unit character. This option may be useful in ap-
+ plications that process patterns from external sources. Note that there
+ is also a build-time option that permanently locks out the use of \C.
+
+ PCRE2_NEVER_UCP
+
+ This option locks out the use of Unicode properties for handling \B,
+ \b, \D, \d, \S, \s, \W, \w, and some of the POSIX character classes, as
+ described for the PCRE2_UCP option below. In particular, it prevents
+ the creator of the pattern from enabling this facility by starting the
+ pattern with (*UCP). This option may be useful in applications that
+ process patterns from external sources. The option combination
+ PCRE2_UCP and PCRE2_NEVER_UCP causes an error.
+
+ PCRE2_NEVER_UTF
+
+ This option locks out interpretation of the pattern as UTF-8, UTF-16,
+ or UTF-32, depending on which library is in use. In particular, it pre-
+ vents the creator of the pattern from switching to UTF interpretation
+ by starting the pattern with (*UTF). This option may be useful in ap-
+ plications that process patterns from external sources. The combination
+ of PCRE2_UTF and PCRE2_NEVER_UTF causes an error.
+
+ PCRE2_NO_AUTO_CAPTURE
+
+ If this option is set, it disables the use of numbered capturing paren-
+ theses in the pattern. Any opening parenthesis that is not followed by
+ ? behaves as if it were followed by ?: but named parentheses can still
+ be used for capturing (and they acquire numbers in the usual way). This
+ is the same as Perl's /n option. Note that, when this option is set,
+ references to capture groups (backreferences or recursion/subroutine
+ calls) may only refer to named groups, though the reference can be by
+ name or by number.
+
+ PCRE2_NO_AUTO_POSSESS
+
+ If this (deprecated) option is set, it disables "auto-possessifica-
+ tion", which is an optimization that, for example, turns a+b into a++b
+ in order to avoid backtracks into a+ that can never be successful. How-
+ ever, if callouts are in use, auto-possessification means that some
+ callouts are never taken. You can set this option if you want the
+ matching functions to do a full unoptimized search and run all the
+ callouts, but it is mainly provided for testing purposes.
+
+ If a compile context is available, it is recommended to use
+ pcre2_set_optimize() with the directive PCRE2_AUTO_POSSESS_OFF rather
+ than the compile option PCRE2_NO_AUTO_POSSESS. Note that
+ PCRE2_NO_AUTO_POSSESS takes precedence over the pcre2_set_optimize()
+ optimization directives PCRE2_AUTO_POSSESS and PCRE2_AUTO_POSSESS_OFF.
+
+ PCRE2_NO_DOTSTAR_ANCHOR
+
+ If this (deprecated) option is set, it disables an optimization that is
+ applied when .* is the first significant item in a top-level branch of
+ a pattern, and all the other branches also start with .* or with \A or
+ \G or ^. The optimization is automatically disabled for .* if it is in-
+ side an atomic group or a capture group that is the subject of a back-
+ reference, or if the pattern contains (*PRUNE) or (*SKIP). When the op-
+ timization is not disabled, such a pattern is automatically anchored if
+ PCRE2_DOTALL is set for all the .* items and PCRE2_MULTILINE is not set
+ for any ^ items. Otherwise, the fact that any match must start either
+ at the start of the subject or following a newline is remembered. Like
+ other optimizations, this can cause callouts to be skipped. (If a com-
+ pile context is available, it is recommended to use pcre2_set_opti-
+ mize() with the directive PCRE2_DOTSTAR_ANCHOR_OFF instead.)
+
+ PCRE2_NO_START_OPTIMIZE
+
+ This is an option whose main effect is at matching time. It does not
+ change what pcre2_compile() generates, but it does affect the output of
+ the JIT compiler. Setting this option is equivalent to calling
+ pcre2_set_optimize() with the directive parameter set to
+ PCRE2_START_OPTIMIZE_OFF.
+
+ There are a number of optimizations that may occur at the start of a
+ match, in order to speed up the process. For example, if it is known
+ that an unanchored match must start with a specific code unit value,
+ the matching code searches the subject for that value, and fails imme-
+ diately if it cannot find it, without actually running the main match-
+ ing function. The start-up optimizations are in effect a pre-scan of
+ the subject that takes place before the pattern is run.
+
+ Disabling the start-up optimizations may cause performance to suffer.
+ However, this may be desirable for patterns which contain callouts or
+ items such as (*COMMIT) and (*MARK). See the above description of
+ PCRE2_START_OPTIMIZE_OFF for further details.
+
+ PCRE2_NO_UTF_CHECK
+
+ When PCRE2_UTF is set, the validity of the pattern as a UTF string is
+ automatically checked. There are discussions about the validity of
+ UTF-8 strings, UTF-16 strings, and UTF-32 strings in the pcre2unicode
+ document. If an invalid UTF sequence is found, pcre2_compile() returns
+ a negative error code.
+
+ If you know that your pattern is a valid UTF string, and you want to
+ skip this check for performance reasons, you can set the
+ PCRE2_NO_UTF_CHECK option. When it is set, the effect of passing an in-
+ valid UTF string as a pattern is undefined. It may cause your program
+ to crash or loop.
+
+ Note that this option can also be passed to pcre2_match() and
+ pcre2_dfa_match(), to suppress UTF validity checking of the subject
+ string.
+
+ Note also that setting PCRE2_NO_UTF_CHECK at compile time does not dis-
+ able the error that is given if an escape sequence for an invalid Uni-
+ code code point is encountered in the pattern. In particular, the so-
+ called "surrogate" code points (0xd800 to 0xdfff) are invalid. If you
+ want to allow escape sequences such as \x{d800} you can set the
+ PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES extra option, as described in the
+ section entitled "Extra compile options" below. However, this is pos-
+ sible only in UTF-8 and UTF-32 modes, because these values are not rep-
+ resentable in UTF-16.
+
+ PCRE2_UCP
+
+ This option has two effects. Firstly, it change the way PCRE2 processes
+ \B, \b, \D, \d, \S, \s, \W, \w, and some of the POSIX character
+ classes. By default, only ASCII characters are recognized, but if
+ PCRE2_UCP is set, Unicode properties are used to classify characters.
+ There are some PCRE2_EXTRA options (see below) that add finer control
+ to this behaviour. More details are given in the section on generic
+ character types in the pcre2pattern page.
+
+ The second effect of PCRE2_UCP is to force the use of Unicode proper-
+ ties for upper/lower casing operations, even when PCRE2_UTF is not set.
+ This makes it possible to process strings in the 16-bit UCS-2 code.
+ This option is available only if PCRE2 has been compiled with Unicode
+ support (which is the default).
+
+ The PCRE2_EXTRA_CASELESS_RESTRICT option (see above) restricts caseless
+ matching such that ASCII characters match only ASCII characters and
+ non-ASCII characters match only non-ASCII characters. The PCRE2_EX-
+ TRA_TURKISH_CASING option (see above) alters the matching of the 'i'
+ characters to follow their behaviour in Turkish and Azeri languages.
+ For further details on PCRE2_EXTRA_CASELESS_RESTRICT and PCRE2_EX-
+ TRA_TURKISH_CASING, see the pcre2unicode page.
+
+ PCRE2_UNGREEDY
+
+ This option inverts the "greediness" of the quantifiers so that they
+ are not greedy by default, but become greedy if followed by "?". It is
+ not compatible with Perl. It can also be set by a (?U) option setting
+ within the pattern.
+
+ PCRE2_USE_OFFSET_LIMIT
+
+ This option must be set for pcre2_compile() if pcre2_set_offset_limit()
+ is going to be used to set a non-default offset limit in a match con-
+ text for matches that use this pattern. An error is generated if an
+ offset limit is set without this option. For more details, see the de-
+ scription of pcre2_set_offset_limit() in the section that describes
+ match contexts. See also the PCRE2_FIRSTLINE option above.
+
+ PCRE2_UTF
+
+ This option causes PCRE2 to regard both the pattern and the subject
+ strings that are subsequently processed as strings of UTF characters
+ instead of single-code-unit strings. It is available when PCRE2 is
+ built to include Unicode support (which is the default). If Unicode
+ support is not available, the use of this option provokes an error. De-
+ tails of how PCRE2_UTF changes the behaviour of PCRE2 are given in the
+ pcre2unicode page. In particular, note that it changes the way
+ PCRE2_CASELESS works.
+
+ Extra compile options
+
+ The option bits that can be set in a compile context by calling the
+ pcre2_set_compile_extra_options() function are as follows:
+
+ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK
+
+ Since release 10.38 PCRE2 has forbidden the use of \K within lookaround
+ assertions, following Perl's lead. This option is provided to re-enable
+ the previous behaviour (act in positive lookarounds, ignore in negative
+ ones) in case anybody is relying on it.
+
+ PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES
+
+ This option applies when compiling a pattern in UTF-8 or UTF-32 mode.
+ It is forbidden in UTF-16 mode, and ignored in non-UTF modes. Unicode
+ "surrogate" code points in the range 0xd800 to 0xdfff are used in pairs
+ in UTF-16 to encode code points with values in the range 0x10000 to
+ 0x10ffff. The surrogates cannot therefore be represented in UTF-16.
+ They can be represented in UTF-8 and UTF-32, but are defined as invalid
+ code points, and cause errors if encountered in a UTF-8 or UTF-32
+ string that is being checked for validity by PCRE2.
+
+ These values also cause errors if encountered in escape sequences such
+ as \x{d912} within a pattern. However, it seems that some applications,
+ when using PCRE2 to check for unwanted characters in UTF-8 strings, ex-
+ plicitly test for the surrogates using escape sequences. The
+ PCRE2_NO_UTF_CHECK option does not disable the error that occurs, be-
+ cause it applies only to the testing of input strings for UTF validity.
+
+ If the extra option PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is set, surro-
+ gate code point values in UTF-8 and UTF-32 patterns no longer provoke
+ errors and are incorporated in the compiled pattern. However, they can
+ only match subject characters if the matching function is called with
+ PCRE2_NO_UTF_CHECK set.
+
+ PCRE2_EXTRA_ALT_BSUX
+
+ The original option PCRE2_ALT_BSUX causes PCRE2 to process \U, \u, and
+ \x in the way that ECMAscript (aka JavaScript) does. Additional func-
+ tionality was defined by ECMAscript 6; setting PCRE2_EXTRA_ALT_BSUX has
+ the effect of PCRE2_ALT_BSUX, but in addition it recognizes \u{hhh..}
+ as a hexadecimal character code, where hhh.. is any number of hexadeci-
+ mal digits.
+
+ PCRE2_EXTRA_ASCII_BSD
+
+ This option forces \d to match only ASCII digits, even when PCRE2_UCP
+ is set. It can be changed within a pattern by means of the (?aD) op-
+ tion setting.
+
+ PCRE2_EXTRA_ASCII_BSS
+
+ This option forces \s to match only ASCII space characters, even when
+ PCRE2_UCP is set. It can be changed within a pattern by means of the
+ (?aS) option setting.
+
+ PCRE2_EXTRA_ASCII_BSW
+
+ This option forces \w to match only ASCII word characters, even when
+ PCRE2_UCP is set. It can be changed within a pattern by means of the
+ (?aW) option setting.
+
+ PCRE2_EXTRA_ASCII_DIGIT
+
+ This option forces the POSIX character classes [:digit:] and [:xdigit:]
+ to match only ASCII digits, even when PCRE2_UCP is set. It can be
+ changed within a pattern by means of the (?aT) option setting.
+
+ PCRE2_EXTRA_ASCII_POSIX
+
+ This option forces all the POSIX character classes, including [:digit:]
+ and [:xdigit:], to match only ASCII characters, even when PCRE2_UCP is
+ set. It can be changed within a pattern by means of the (?aP) option
+ setting, but note that this also sets PCRE2_EXTRA_ASCII_DIGIT in order
+ to ensure that (?-aP) unsets all ASCII restrictions for POSIX classes.
+
+ PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL
+
+ This is a dangerous option. Use with care. By default, an unrecognized
+ escape such as \j or a malformed one such as \x{2z} causes a compile-
+ time error when detected by pcre2_compile(). Perl is somewhat inconsis-
+ tent in handling such items: for example, \j is treated as a literal
+ "j", and non-hexadecimal digits in \x{} are just ignored, though warn-
+ ings are given in both cases if Perl's warning switch is enabled. How-
+ ever, a malformed octal number after \o{ always causes an error in
+ Perl.
+
+ If the PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL extra option is passed to
+ pcre2_compile(), all unrecognized or malformed escape sequences are
+ treated as single-character escapes. For example, \j is a literal "j"
+ and \x{2z} is treated as the literal string "x{2z}". Setting this op-
+ tion means that typos in patterns may go undetected and have unexpected
+ results. Also note that a sequence such as [\N{] is interpreted as a
+ malformed attempt at [\N{...}] and so is treated as [N{] whereas [\N]
+ gives an error because an unqualified \N is a valid escape sequence but
+ is not supported in a character class. To reiterate: this is a danger-
+ ous option. Use with great care.
+
+ PCRE2_EXTRA_CASELESS_RESTRICT
+
+ When either PCRE2_UCP or PCRE2_UTF is set, caseless matching follows
+ Unicode rules, which allow for more than two cases per character. There
+ are two case-equivalent character sets that contain both ASCII and non-
+ ASCII characters. The ASCII letter S is case-equivalent to U+017f (long
+ S) and the ASCII letter K is case-equivalent to U+212a (Kelvin sign).
+ This option disables recognition of case-equivalences that cross the
+ ASCII/non-ASCII boundary. In a caseless match, both characters must ei-
+ ther be ASCII or non-ASCII. The option can be changed within a pattern
+ by the (*CASELESS_RESTRICT) or (?r) option settings.
+
+ PCRE2_EXTRA_ESCAPED_CR_IS_LF
+
+ There are some legacy applications where the escape sequence \r in a
+ pattern is expected to match a newline. If this option is set, \r in a
+ pattern is converted to \n so that it matches a LF (linefeed) instead
+ of a CR (carriage return) character. The option does not affect a lit-
+ eral CR in the pattern, nor does it affect CR specified as an explicit
+ code point such as \x{0D}.
+
+ PCRE2_EXTRA_MATCH_LINE
+
+ This option is provided for use by the -x option of pcre2grep. It
+ causes the pattern only to match complete lines. This is achieved by
+ automatically inserting the code for "^(?:" at the start of the com-
+ piled pattern and ")$" at the end. Thus, when PCRE2_MULTILINE is set,
+ the matched line may be in the middle of the subject string. This op-
+ tion can be used with PCRE2_LITERAL.
+
+ PCRE2_EXTRA_MATCH_WORD
+
+ This option is provided for use by the -w option of pcre2grep. It
+ causes the pattern only to match strings that have a word boundary at
+ the start and the end. This is achieved by automatically inserting the
+ code for "\b(?:" at the start of the compiled pattern and ")\b" at the
+ end. The option may be used with PCRE2_LITERAL. However, it is ignored
+ if PCRE2_EXTRA_MATCH_LINE is also set.
+
+ PCRE2_EXTRA_NO_BS0
+
+ If this option is set (note that its final character is the digit 0) it
+ locks out the use of the sequence \0 unless at least one more octal
+ digit follows.
+
+ PCRE2_EXTRA_PYTHON_OCTAL
+
+ If this option is set, PCRE2 follows Python's rules for interpreting
+ octal escape sequences. The rules for handling sequences such as \14,
+ which could be an octal number or a back reference are different. De-
+ tails are given in the pcre2pattern documentation.
+
+ PCRE2_EXTRA_NEVER_CALLOUT
+
+ If this option is set, PCRE2 treats callouts in the pattern as a syntax
+ error, returning PCRE2_ERROR_CALLOUT_CALLER_DISABLED. This is useful if
+ the application knows that a callout will not be provided to
+ pcre2_match(), so that callouts in the pattern are not silently ig-
+ nored.
+
+ PCRE2_EXTRA_TURKISH_CASING
+
+ This option alters case-equivalence of the 'i' letters to follow the
+ alphabet used by Turkish and Azeri languages. The option can be changed
+ within a pattern by the (*TURKISH_CASING) start-of-pattern setting. Ei-
+ ther the UTF or UCP options must be set. In the 8-bit library, UTF must
+ be set. This option cannot be combined with PCRE2_EXTRA_CASELESS_RE-
+ STRICT.
+
+
+JUST-IN-TIME (JIT) COMPILATION
+
+ int pcre2_jit_compile(pcre2_code *code, uint32_t options);
+
+ int pcre2_jit_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext);
+
+ void pcre2_jit_free_unused_memory(pcre2_general_context *gcontext);
+
+ pcre2_jit_stack *pcre2_jit_stack_create(size_t startsize,
+ size_t maxsize, pcre2_general_context *gcontext);
+
+ void pcre2_jit_stack_assign(pcre2_match_context *mcontext,
+ pcre2_jit_callback callback_function, void *callback_data);
+
+ void pcre2_jit_stack_free(pcre2_jit_stack *jit_stack);
+
+ These functions provide support for JIT compilation, which, if the
+ just-in-time compiler is available, further processes a compiled pat-
+ tern into machine code that executes much faster than the pcre2_match()
+ interpretive matching function. Full details are given in the pcre2jit
+ documentation.
+
+ JIT compilation is a heavyweight optimization. It can take some time
+ for patterns to be analyzed, and for one-off matches and simple pat-
+ terns the benefit of faster execution might be offset by a much slower
+ compilation time. Most (but not all) patterns can be optimized by the
+ JIT compiler.
+
+
+LOCALE SUPPORT
+
+ const uint8_t *pcre2_maketables(pcre2_general_context *gcontext);
+
+ void pcre2_maketables_free(pcre2_general_context *gcontext,
+ const uint8_t *tables);
+
+ PCRE2 handles caseless matching, and determines whether characters are
+ letters, digits, or whatever, by reference to a set of tables, indexed
+ by character code point. However, this applies only to characters whose
+ code points are less than 256. By default, higher-valued code points
+ never match escapes such as \w or \d.
+
+ When PCRE2 is built with Unicode support (the default), certain Unicode
+ character properties can be tested with \p and \P, or, alternatively,
+ the PCRE2_UCP option can be set when a pattern is compiled; this causes
+ \w and friends to use Unicode property support instead of the built-in
+ tables. PCRE2_UCP also causes upper/lower casing operations on charac-
+ ters with code points greater than 127 to use Unicode properties. These
+ effects apply even when PCRE2_UTF is not set. There are, however, some
+ PCRE2_EXTRA options (see above) that can be used to modify or suppress
+ them.
+
+ The use of locales with Unicode is discouraged. If you are handling
+ characters with code points greater than 127, you should either use
+ Unicode support, or use locales, but not try to mix the two.
+
+ PCRE2 contains a built-in set of character tables that are used by de-
+ fault. These are sufficient for many applications. Normally, the in-
+ ternal tables recognize only ASCII characters. However, when PCRE2 is
+ built, it is possible to cause the internal tables to be rebuilt in the
+ default "C" locale of the local system, which may cause them to be dif-
+ ferent.
+
+ The built-in tables can be overridden by tables supplied by the appli-
+ cation that calls PCRE2. These may be created in a different locale
+ from the default. As more and more applications change to using Uni-
+ code, the need for this locale support is expected to die away.
+
+ External tables are built by calling the pcre2_maketables() function,
+ in the relevant locale. The only argument to this function is a general
+ context, which can be used to pass a custom memory allocator. If the
+ argument is NULL, the system malloc() is used. The result can be passed
+ to pcre2_compile() as often as necessary, by creating a compile context
+ and calling pcre2_set_character_tables() to set the tables pointer
+ therein.
+
+ For example, to build and use tables that are appropriate for the
+ French locale (where accented characters with values greater than 127
+ are treated as letters), the following code could be used:
+
+ setlocale(LC_CTYPE, "fr_FR");
+ tables = pcre2_maketables(NULL);
+ ccontext = pcre2_compile_context_create(NULL);
+ pcre2_set_character_tables(ccontext, tables);
+ re = pcre2_compile(..., ccontext);
+
+ The locale name "fr_FR" is used on Linux and other Unix-like systems;
+ if you are using Windows, the name for the French locale is "french".
+
+ The pointer that is passed (via the compile context) to pcre2_compile()
+ is saved with the compiled pattern, and the same tables are used by the
+ matching functions. Thus, for any single pattern, compilation and
+ matching both happen in the same locale, but different patterns can be
+ processed in different locales.
+
+ It is the caller's responsibility to ensure that the memory containing
+ the tables remains available while they are still in use. When they are
+ no longer needed, you can discard them using pcre2_maketables_free(),
+ which should pass as its first parameter the same global context that
+ was used to create the tables.
+
+ Saving locale tables
+
+ The tables described above are just a sequence of binary bytes, which
+ makes them independent of hardware characteristics such as endianness
+ or whether the processor is 32-bit or 64-bit. A copy of the result of
+ pcre2_maketables() can therefore be saved in a file or elsewhere and
+ re-used later, even in a different program or on another computer. The
+ size of the tables (number of bytes) must be obtained by calling
+ pcre2_config() with the PCRE2_CONFIG_TABLES_LENGTH option because
+ pcre2_maketables() does not return this value. Note that the
+ pcre2_dftables program, which is part of the PCRE2 build system, can be
+ used stand-alone to create a file that contains a set of binary tables.
+ See the pcre2build documentation for details.
+
+
+INFORMATION ABOUT A COMPILED PATTERN
+
+ int pcre2_pattern_info(const pcre2 *code, uint32_t what, void *where);
+
+ The pcre2_pattern_info() function returns general information about a
+ compiled pattern. For information about callouts, see the next section.
+ The first argument for pcre2_pattern_info() is a pointer to the com-
+ piled pattern. The second argument specifies which piece of information
+ is required, and the third argument is a pointer to a variable to re-
+ ceive the data. If the third argument is NULL, the first argument is
+ ignored, and the function returns the size in bytes of the variable
+ that is required for the information requested. Otherwise, the yield of
+ the function is zero for success, or one of the following negative num-
+ bers:
+
+ PCRE2_ERROR_NULL the argument code was NULL
+ PCRE2_ERROR_BADMAGIC the "magic number" was not found
+ PCRE2_ERROR_BADOPTION the value of what was invalid
+ PCRE2_ERROR_UNSET the requested field is not set
+
+ The "magic number" is placed at the start of each compiled pattern as a
+ simple check against passing an arbitrary memory pointer. Here is a
+ typical call of pcre2_pattern_info(), to obtain the length of the com-
+ piled pattern:
+
+ int rc;
+ size_t length;
+ rc = pcre2_pattern_info(
+ re, /* result of pcre2_compile() */
+ PCRE2_INFO_SIZE, /* what is required */
+ &length); /* where to put the data */
+
+ The possible values for the second argument are defined in pcre2.h, and
+ are as follows:
+
+ PCRE2_INFO_ALLOPTIONS
+ PCRE2_INFO_ARGOPTIONS
+ PCRE2_INFO_EXTRAOPTIONS
+
+ Return copies of the pattern's options. The third argument should point
+ to a uint32_t variable. PCRE2_INFO_ARGOPTIONS returns exactly the op-
+ tions that were passed to pcre2_compile(), whereas PCRE2_INFO_ALLOP-
+ TIONS returns the compile options as modified by any top-level (*XXX)
+ option settings such as (*UTF) at the start of the pattern itself.
+ PCRE2_INFO_EXTRAOPTIONS returns the extra options that were set in the
+ compile context by calling the pcre2_set_compile_extra_options() func-
+ tion.
+
+ For example, if the pattern /(*UTF)abc/ is compiled with the PCRE2_EX-
+ TENDED option, the result for PCRE2_INFO_ALLOPTIONS is PCRE2_EXTENDED
+ and PCRE2_UTF. Option settings such as (?i) that can change within a
+ pattern do not affect the result of PCRE2_INFO_ALLOPTIONS, even if they
+ appear right at the start of the pattern. (This was different in some
+ earlier releases.)
+
+ A pattern compiled without PCRE2_ANCHORED is automatically anchored by
+ PCRE2 if the first significant item in every top-level branch is one of
+ the following:
+
+ ^ unless PCRE2_MULTILINE is set
+ \A always
+ \G always
+ .* sometimes - see below
+
+ When .* is the first significant item, anchoring is possible only when
+ all the following are true:
+
+ .* is not in an atomic group
+ .* is not in a capture group that is the subject
+ of a backreference
+ PCRE2_DOTALL is in force for .*
+ Neither (*PRUNE) nor (*SKIP) appears in the pattern
+ PCRE2_NO_DOTSTAR_ANCHOR is not set
+ Dotstar anchoring has not been disabled with PCRE2_DOTSTAR_ANCHOR_OFF
+
+ For patterns that are auto-anchored, the PCRE2_ANCHORED bit is set in
+ the options returned for PCRE2_INFO_ALLOPTIONS.
+
+ PCRE2_INFO_BACKREFMAX
+
+ Return the number of the highest backreference in the pattern. The
+ third argument should point to a uint32_t variable. Named capture
+ groups acquire numbers as well as names, and these count towards the
+ highest backreference. Backreferences such as \4 or \g{12} match the
+ captured characters of the given group, but in addition, the check that
+ a capture group is set in a conditional group such as (?(3)a|b) is also
+ a backreference. Zero is returned if there are no backreferences.
+
+ PCRE2_INFO_BSR
+
+ The output is a uint32_t integer whose value indicates what character
+ sequences the \R escape sequence matches. A value of PCRE2_BSR_UNICODE
+ means that \R matches any Unicode line ending sequence; a value of
+ PCRE2_BSR_ANYCRLF means that \R matches only CR, LF, or CRLF.
+
+ PCRE2_INFO_CAPTURECOUNT
+
+ Return the highest capture group number in the pattern. In patterns
+ where (?| is not used, this is also the total number of capture groups.
+ The third argument should point to a uint32_t variable.
+
+ PCRE2_INFO_DEPTHLIMIT
+
+ If the pattern set a backtracking depth limit by including an item of
+ the form (*LIMIT_DEPTH=nnnn) at the start, the value is returned. The
+ third argument should point to a uint32_t integer. If no such value has
+ been set, the call to pcre2_pattern_info() returns the error PCRE2_ER-
+ ROR_UNSET. Note that this limit will only be used during matching if it
+ is less than the limit set or defaulted by the caller of the match
+ function.
+
+ PCRE2_INFO_FIRSTBITMAP
+
+ In the absence of a single first code unit for a non-anchored pattern,
+ pcre2_compile() may construct a 256-bit table that defines a fixed set
+ of values for the first code unit in any match. For example, a pattern
+ that starts with [abc] results in a table with three bits set. When
+ code unit values greater than 255 are supported, the flag bit for 255
+ means "any code unit of value 255 or above". If such a table was con-
+ structed, a pointer to it is returned. Otherwise NULL is returned. The
+ third argument should point to a const uint8_t * variable.
+
+ PCRE2_INFO_FIRSTCODETYPE
+
+ Return information about the first code unit of any matched string, for
+ a non-anchored pattern. The third argument should point to a uint32_t
+ variable. If there is a fixed first value, for example, the letter "c"
+ from a pattern such as (cat|cow|coyote), 1 is returned, and the value
+ can be retrieved using PCRE2_INFO_FIRSTCODEUNIT. If there is no fixed
+ first value, but it is known that a match can occur only at the start
+ of the subject or following a newline in the subject, 2 is returned.
+ Otherwise, and for anchored patterns, 0 is returned.
+
+ PCRE2_INFO_FIRSTCODEUNIT
+
+ Return the value of the first code unit of any matched string for a
+ pattern where PCRE2_INFO_FIRSTCODETYPE returns 1; otherwise return 0.
+ The third argument should point to a uint32_t variable. In the 8-bit
+ library, the value is always less than 256. In the 16-bit library the
+ value can be up to 0xffff. In the 32-bit library in UTF-32 mode the
+ value can be up to 0x10ffff, and up to 0xffffffff when not using UTF-32
+ mode.
+
+ PCRE2_INFO_FRAMESIZE
+
+ Return the size (in bytes) of the data frames that are used to remember
+ backtracking positions when the pattern is processed by pcre2_match()
+ without the use of JIT. The third argument should point to a size_t
+ variable. The frame size depends on the number of capturing parentheses
+ in the pattern. Each additional capture group adds two PCRE2_SIZE vari-
+ ables.
+
+ PCRE2_INFO_HASBACKSLASHC
+
+ Return 1 if the pattern contains any instances of \C, otherwise 0. The
+ third argument should point to a uint32_t variable.
+
+ PCRE2_INFO_HASCRORLF
+
+ Return 1 if the pattern contains any explicit matches for CR or LF
+ characters, otherwise 0. The third argument should point to a uint32_t
+ variable. An explicit match is either a literal CR or LF character, or
+ \r or \n or one of the equivalent hexadecimal or octal escape se-
+ quences.
+
+ PCRE2_INFO_HEAPLIMIT
+
+ If the pattern set a heap memory limit by including an item of the form
+ (*LIMIT_HEAP=nnnn) at the start, the value is returned. The third argu-
+ ment should point to a uint32_t integer. If no such value has been set,
+ the call to pcre2_pattern_info() returns the error PCRE2_ERROR_UNSET.
+ Note that this limit will only be used during matching if it is less
+ than the limit set or defaulted by the caller of the match function.
+
+ PCRE2_INFO_JCHANGED
+
+ Return 1 if the (?J) or (?-J) option setting is used in the pattern,
+ otherwise 0. The third argument should point to a uint32_t variable.
+ (?J) and (?-J) set and unset the local PCRE2_DUPNAMES option, respec-
+ tively.
+
+ PCRE2_INFO_JITSIZE
+
+ If the compiled pattern was successfully processed by pcre2_jit_com-
+ pile(), return the size of the JIT compiled code, otherwise return
+ zero. The third argument should point to a size_t variable.
+
+ PCRE2_INFO_LASTCODETYPE
+
+ Returns 1 if there is a rightmost literal code unit that must exist in
+ any matched string, other than at its start. The third argument should
+ point to a uint32_t variable. If there is no such value, 0 is returned.
+ When 1 is returned, the code unit value itself can be retrieved using
+ PCRE2_INFO_LASTCODEUNIT. For anchored patterns, a last literal value is
+ recorded only if it follows something of variable length. For example,
+ for the pattern /^a\d+z\d+/ the returned value is 1 (with "z" returned
+ from PCRE2_INFO_LASTCODEUNIT), but for /^a\dz\d/ the returned value is
+ 0.
+
+ PCRE2_INFO_LASTCODEUNIT
+
+ Return the value of the rightmost literal code unit that must exist in
+ any matched string, other than at its start, for a pattern where
+ PCRE2_INFO_LASTCODETYPE returns 1. Otherwise, return 0. The third argu-
+ ment should point to a uint32_t variable.
+
+ PCRE2_INFO_MATCHEMPTY
+
+ Return 1 if the pattern might match an empty string, otherwise 0. The
+ third argument should point to a uint32_t variable. When a pattern con-
+ tains recursive subroutine calls it is not always possible to determine
+ whether or not it can match an empty string. PCRE2 takes a cautious ap-
+ proach and returns 1 in such cases.
+
+ PCRE2_INFO_MATCHLIMIT
+
+ If the pattern set a match limit by including an item of the form
+ (*LIMIT_MATCH=nnnn) at the start, the value is returned. The third ar-
+ gument should point to a uint32_t integer. If no such value has been
+ set, the call to pcre2_pattern_info() returns the error PCRE2_ERROR_UN-
+ SET. Note that this limit will only be used during matching if it is
+ less than the limit set or defaulted by the caller of the match func-
+ tion.
+
+ PCRE2_INFO_MAXLOOKBEHIND
+
+ A lookbehind assertion moves back a certain number of characters (not
+ code units) when it starts to process each of its branches. This re-
+ quest returns the largest of these backward moves. The third argument
+ should point to a uint32_t integer. The simple assertions \b and \B re-
+ quire a one-character lookbehind and cause PCRE2_INFO_MAXLOOKBEHIND to
+ return 1 in the absence of anything longer. \A also registers a one-
+ character lookbehind, though it does not actually inspect the previous
+ character.
+
+ Note that this information is useful for multi-segment matching only if
+ the pattern contains no nested lookbehinds. For example, the pattern
+ (?<=a(?<=ba)c) returns a maximum lookbehind of 2, but when it is
+ processed, the first lookbehind moves back by two characters, matches
+ one character, then the nested lookbehind also moves back by two char-
+ acters. This puts the matching point three characters earlier than it
+ was at the start. PCRE2_INFO_MAXLOOKBEHIND is really only useful as a
+ debugging tool. See the pcre2partial documentation for a discussion of
+ multi-segment matching.
+
+ PCRE2_INFO_MINLENGTH
+
+ If a minimum length for matching subject strings was computed, its
+ value is returned. Otherwise the returned value is 0. This value is not
+ computed when PCRE2_NO_START_OPTIMIZE is set. The value is a number of
+ characters, which in UTF mode may be different from the number of code
+ units. The third argument should point to a uint32_t variable. The
+ value is a lower bound to the length of any matching string. There may
+ not be any strings of that length that do actually match, but every
+ string that does match is at least that long.
+
+ PCRE2_INFO_NAMECOUNT
+ PCRE2_INFO_NAMEENTRYSIZE
+ PCRE2_INFO_NAMETABLE
+
+ PCRE2 supports the use of named as well as numbered capturing parenthe-
+ ses. The names are just an additional way of identifying the parenthe-
+ ses, which still acquire numbers. Several convenience functions such as
+ pcre2_substring_get_byname() are provided for extracting captured sub-
+ strings by name. It is also possible to extract the data directly, by
+ first converting the name to a number in order to access the correct
+ pointers in the output vector (described with pcre2_match() below). To
+ do the conversion, you need to use the name-to-number map, which is de-
+ scribed by these three values.
+
+ The map consists of a number of fixed-size entries. PCRE2_INFO_NAME-
+ COUNT gives the number of entries, and PCRE2_INFO_NAMEENTRYSIZE gives
+ the size of each entry in code units; both of these return a uint32_t
+ value. The entry size depends on the length of the longest name.
+
+ PCRE2_INFO_NAMETABLE returns a pointer to the first entry of the table.
+ This is a PCRE2_SPTR pointer to a block of code units. In the 8-bit li-
+ brary, the first two bytes of each entry are the number of the captur-
+ ing parenthesis, most significant byte first. In the 16-bit library,
+ the pointer points to 16-bit code units, the first of which contains
+ the parenthesis number. In the 32-bit library, the pointer points to
+ 32-bit code units, the first of which contains the parenthesis number.
+ The rest of the entry is the corresponding name, zero terminated.
+
+ The names are in alphabetical order. If (?| is used to create multiple
+ capture groups with the same number, as described in the section on du-
+ plicate group numbers in the pcre2pattern page, the groups may be given
+ the same name, but there is only one entry in the table. Different
+ names for groups of the same number are not permitted.
+
+ Duplicate names for capture groups with different numbers are permit-
+ ted, but only if PCRE2_DUPNAMES is set. They appear in the table in the
+ order in which they were found in the pattern. In the absence of (?|
+ this is the order of increasing number; when (?| is used this is not
+ necessarily the case because later capture groups may have lower num-
+ bers.
+
+ As a simple example of the name/number table, consider the following
+ pattern after compilation by the 8-bit library (assume PCRE2_EXTENDED
+ is set, so white space - including newlines - is ignored):
+
+ (? (?(\d\d)?\d\d) -
+ (?\d\d) - (?\d\d) )
+
+ There are four named capture groups, so the table has four entries, and
+ each entry in the table is eight bytes long. The table is as follows,
+ with non-printing bytes shows in hexadecimal, and undefined bytes shown
+ as ??:
+
+ 00 01 d a t e 00 ??
+ 00 05 d a y 00 ?? ??
+ 00 04 m o n t h 00
+ 00 02 y e a r 00 ??
+
+ When writing code to extract data from named capture groups using the
+ name-to-number map, remember that the length of the entries is likely
+ to be different for each compiled pattern.
+
+ PCRE2_INFO_NEWLINE
+
+ The output is one of the following uint32_t values:
+
+ PCRE2_NEWLINE_CR Carriage return (CR)
+ PCRE2_NEWLINE_LF Linefeed (LF)
+ PCRE2_NEWLINE_CRLF Carriage return, linefeed (CRLF)
+ PCRE2_NEWLINE_ANY Any Unicode line ending
+ PCRE2_NEWLINE_ANYCRLF Any of CR, LF, or CRLF
+ PCRE2_NEWLINE_NUL The NUL character (binary zero)
+
+ This identifies the character sequence that will be recognized as mean-
+ ing "newline" while matching.
+
+ PCRE2_INFO_SIZE
+
+ Return the size of the compiled pattern in bytes (for all three li-
+ braries). The third argument should point to a size_t variable. This
+ value includes the size of the general data block that precedes the
+ code units of the compiled pattern itself. The value that is used when
+ pcre2_compile() is getting memory in which to place the compiled pat-
+ tern may be slightly larger than the value returned by this option, be-
+ cause there are cases where the code that calculates the size has to
+ over-estimate. Processing a pattern with the JIT compiler does not al-
+ ter the value returned by this option.
+
+
+INFORMATION ABOUT A PATTERN'S CALLOUTS
+
+ int pcre2_callout_enumerate(const pcre2_code *code,
+ int (*callback)(pcre2_callout_enumerate_block *, void *),
+ void *user_data);
+
+ A script language that supports the use of string arguments in callouts
+ might like to scan all the callouts in a pattern before running the
+ match. This can be done by calling pcre2_callout_enumerate(). The first
+ argument is a pointer to a compiled pattern, the second points to a
+ callback function, and the third is arbitrary user data. The callback
+ function is called for every callout in the pattern in the order in
+ which they appear. Its first argument is a pointer to a callout enumer-
+ ation block, and its second argument is the user_data value that was
+ passed to pcre2_callout_enumerate(). The contents of the callout enu-
+ meration block are described in the pcre2callout documentation, which
+ also gives further details about callouts.
+
+
+SERIALIZATION AND PRECOMPILING
+
+ It is possible to save compiled patterns on disc or elsewhere, and re-
+ load them later, subject to a number of restrictions. The host on which
+ the patterns are reloaded must be running the same version of PCRE2,
+ with the same code unit width, and must also have the same endianness,
+ pointer width, and PCRE2_SIZE type. Before compiled patterns can be
+ saved, they must be converted to a "serialized" form, which in the case
+ of PCRE2 is really just a bytecode dump. The functions whose names be-
+ gin with pcre2_serialize_ are used for converting to and from the seri-
+ alized form. They are described in the pcre2serialize documentation.
+ Note that PCRE2 serialization does not convert compiled patterns to an
+ abstract format like Java or .NET serialization.
+
+
+THE MATCH DATA BLOCK
+
+ pcre2_match_data *pcre2_match_data_create(uint32_t ovecsize,
+ pcre2_general_context *gcontext);
+
+ pcre2_match_data *pcre2_match_data_create_from_pattern(
+ const pcre2_code *code, pcre2_general_context *gcontext);
+
+ void pcre2_match_data_free(pcre2_match_data *match_data);
+
+ Information about a successful or unsuccessful match is placed in a
+ match data block, which is an opaque structure that is accessed by
+ function calls. In particular, the match data block contains a vector
+ of offsets into the subject string that define the matched parts of the
+ subject. This is known as the ovector.
+
+ Before calling pcre2_match(), pcre2_dfa_match(), or pcre2_jit_match()
+ you must create a match data block by calling one of the creation func-
+ tions above. For pcre2_match_data_create(), the first argument is the
+ number of pairs of offsets in the ovector.
+
+ When using pcre2_match(), one pair of offsets is required to identify
+ the string that matched the whole pattern, with an additional pair for
+ each captured substring. For example, a value of 4 creates enough space
+ to record the matched portion of the subject plus three captured sub-
+ strings.
+
+ When using pcre2_dfa_match() there may be multiple matched substrings
+ of different lengths at the same point in the subject. The ovector
+ should be made large enough to hold as many as are expected.
+
+ A minimum of at least 1 pair is imposed by pcre2_match_data_create(),
+ so it is always possible to return the overall matched string in the
+ case of pcre2_match() or the longest match in the case of
+ pcre2_dfa_match(). The maximum number of pairs is 65535; if the first
+ argument of pcre2_match_data_create() is greater than this, 65535 is
+ used.
+
+ The second argument of pcre2_match_data_create() is a pointer to a gen-
+ eral context, which can specify custom memory management for obtaining
+ the memory for the match data block. If you are not using custom memory
+ management, pass NULL, which causes malloc() to be used.
+
+ For pcre2_match_data_create_from_pattern(), the first argument is a
+ pointer to a compiled pattern. The ovector is created to be exactly the
+ right size to hold all the substrings a pattern might capture when
+ matched using pcre2_match(). You should not use this call when matching
+ with pcre2_dfa_match(). The second argument is again a pointer to a
+ general context, but in this case if NULL is passed, the memory is ob-
+ tained using the same allocator that was used for the compiled pattern
+ (custom or default).
+
+ A match data block can be used many times, with the same or different
+ compiled patterns. You can extract information from a match data block
+ after a match operation has finished, using functions that are de-
+ scribed in the sections on matched strings and other match data below.
+
+ When a call of pcre2_match() fails, valid data is available in the
+ match block only when the error is PCRE2_ERROR_NOMATCH, PCRE2_ER-
+ ROR_PARTIAL, or one of the error codes for an invalid UTF string. Ex-
+ actly what is available depends on the error, and is detailed below.
+
+ When one of the matching functions is called, pointers to the compiled
+ pattern and the subject string are set in the match data block so that
+ they can be referenced by the extraction functions after a successful
+ match. After running a match, you must not free a compiled pattern or a
+ subject string until after all operations on the match data block (for
+ that match) have taken place, unless, in the case of the subject
+ string, you have used the PCRE2_COPY_MATCHED_SUBJECT option, which is
+ described in the section entitled "Option bits for pcre2_match()" be-
+ low.
+
+ When a match data block itself is no longer needed, it should be freed
+ by calling pcre2_match_data_free(). If this function is called with a
+ NULL argument, it returns immediately, without doing anything.
+
+
+MEMORY USE FOR MATCH DATA BLOCKS
+
+ PCRE2_SIZE pcre2_get_match_data_size(pcre2_match_data *match_data);
+
+ PCRE2_SIZE pcre2_get_match_data_heapframes_size(
+ pcre2_match_data *match_data);
+
+ The size of a match data block depends on the size of the ovector that
+ it contains. The function pcre2_get_match_data_size() returns the size,
+ in bytes, of the block that is its argument.
+
+ When pcre2_match() runs interpretively (that is, without using JIT), it
+ makes use of a vector of data frames for remembering backtracking posi-
+ tions. The size of each individual frame depends on the number of cap-
+ turing parentheses in the pattern and can be obtained by calling
+ pcre2_pattern_info() with the PCRE2_INFO_FRAMESIZE option (see the sec-
+ tion entitled "Information about a compiled pattern" above).
+
+ Heap memory is used for the frames vector; if the initial memory block
+ turns out to be too small during matching, it is automatically ex-
+ panded. When pcre2_match() returns, the memory is not freed, but re-
+ mains attached to the match data block, for use by any subsequent
+ matches that use the same block. It is automatically freed when the
+ match data block itself is freed.
+
+ You can find the current size of the frames vector that a match data
+ block owns by calling pcre2_get_match_data_heapframes_size(). For a
+ newly created match data block the size will be zero. Some types of
+ match may require a lot of frames and thus a large vector; applications
+ that run in environments where memory is constrained can check this and
+ free the match data block if the heap frames vector has become too big.
+
+
+MATCHING A PATTERN: THE TRADITIONAL FUNCTION
+
+ int pcre2_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext);
+
+ The function pcre2_match() is called to match a subject string against
+ a compiled pattern, which is passed in the code argument. You can call
+ pcre2_match() with the same code argument as many times as you like, in
+ order to find multiple matches in the subject string or to match dif-
+ ferent subject strings with the same pattern.
+
+ This function is the main matching facility of the library, and it op-
+ erates in a Perl-like manner. For specialist use there is also an al-
+ ternative matching function, which is described below in the section
+ about the pcre2_dfa_match() function.
+
+ Here is an example of a simple call to pcre2_match():
+
+ pcre2_match_data *md = pcre2_match_data_create(4, NULL);
+ int rc = pcre2_match(
+ re, /* result of pcre2_compile() */
+ "some string", /* the subject string */
+ 11, /* the length of the subject string */
+ 0, /* start at offset 0 in the subject */
+ 0, /* default options */
+ md, /* the match data block */
+ NULL); /* a match context; NULL means use defaults */
+
+ If the subject string is zero-terminated, the length can be given as
+ PCRE2_ZERO_TERMINATED. A match context must be provided if certain less
+ common matching parameters are to be changed. For details, see the sec-
+ tion on the match context above.
+
+ The string to be matched by pcre2_match()
+
+ The subject string is passed to pcre2_match() as a pointer in subject,
+ a length in length, and a starting offset in startoffset. The length
+ and offset are in code units, not characters. That is, they are in
+ bytes for the 8-bit library, 16-bit code units for the 16-bit library,
+ and 32-bit code units for the 32-bit library, whether or not UTF pro-
+ cessing is enabled. As a special case, if subject is NULL and length is
+ zero, the subject is assumed to be an empty string. If length is non-
+ zero, an error occurs if subject is NULL.
+
+ If startoffset is greater than the length of the subject, pcre2_match()
+ returns PCRE2_ERROR_BADOFFSET. When the starting offset is zero, the
+ search for a match starts at the beginning of the subject, and this is
+ by far the most common case. In UTF-8 or UTF-16 mode, the starting off-
+ set must point to the start of a character, or to the end of the sub-
+ ject (in UTF-32 mode, one code unit equals one character, so all off-
+ sets are valid). Like the pattern string, the subject may contain bi-
+ nary zeros.
+
+ A non-zero starting offset is useful when searching for another match
+ in the same subject by calling pcre2_match() again after a previous
+ success. Setting startoffset differs from passing over a shortened
+ string and setting PCRE2_NOTBOL in the case of a pattern that begins
+ with any kind of lookbehind. For example, consider the pattern
+
+ \Biss\B
+
+ which finds occurrences of "iss" in the middle of words. (\B matches
+ only if the current position in the subject is not a word boundary.)
+ When applied to the string "Mississippi" the first call to
+ pcre2_match() finds the first occurrence. If pcre2_match() is called
+ again with just the remainder of the subject, namely "issippi", it does
+ not match, because \B is always false at the start of the subject,
+ which is deemed to be a word boundary. However, if pcre2_match() is
+ passed the entire string again, but with startoffset set to 4, it finds
+ the second occurrence of "iss" because it is able to look behind the
+ starting point to discover that it is preceded by a letter.
+
+ Finding all the matches in a subject is tricky when the pattern can
+ match an empty string. PCRE2 includes a helper API to assist with this;
+ see the section entitled "Iterating over all matches" below for de-
+ tails.
+
+ If a non-zero starting offset is passed when the pattern is anchored, a
+ single attempt to match at the given offset is made. This can only suc-
+ ceed if the pattern does not require the match to be at the start of
+ the subject. In other words, the anchoring must be the result of set-
+ ting the PCRE2_ANCHORED option or the use of .* with PCRE2_DOTALL, not
+ by starting the pattern with ^ or \A.
+
+ Option bits for pcre2_match()
+
+ The unused bits of the options argument for pcre2_match() must be zero.
+ The only bits that may be set are PCRE2_ANCHORED,
+ PCRE2_COPY_MATCHED_SUBJECT, PCRE2_DISABLE_RECURSELOOP_CHECK, PCRE2_EN-
+ DANCHORED, PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY,
+ PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_JIT, PCRE2_NO_UTF_CHECK, PCRE2_PAR-
+ TIAL_HARD, and PCRE2_PARTIAL_SOFT. Their action is described below.
+
+ Setting PCRE2_ANCHORED or PCRE2_ENDANCHORED at match time is not sup-
+ ported by the just-in-time (JIT) compiler. If it is set, JIT matching
+ is disabled and the interpretive code in pcre2_match() is run.
+ PCRE2_DISABLE_RECURSELOOP_CHECK is ignored by JIT, but apart from
+ PCRE2_NO_JIT (obviously), the remaining options are supported for JIT
+ matching.
+
+ PCRE2_ANCHORED
+
+ The PCRE2_ANCHORED option limits pcre2_match() to matching at the first
+ matching position. If a pattern was compiled with PCRE2_ANCHORED, or
+ turned out to be anchored by virtue of its contents, it cannot be made
+ unanchored at matching time. Note that setting the option at match time
+ disables JIT matching.
+
+ PCRE2_COPY_MATCHED_SUBJECT
+
+ By default, a pointer to the subject is remembered in the match data
+ block so that, after a successful match, it can be referenced by the
+ substring extraction functions. This means that the subject's memory
+ must not be freed until all such operations are complete. For some ap-
+ plications where the lifetime of the subject string is not guaranteed,
+ it may be necessary to make a copy of the subject string, but it is
+ wasteful to do this unless the match is successful. After a successful
+ match, if PCRE2_COPY_MATCHED_SUBJECT is set, the subject is copied and
+ the new pointer is remembered in the match data block instead of the
+ original subject pointer. The memory allocator that was used for the
+ match block itself is used. The copy is automatically freed when
+ pcre2_match_data_free() is called to free the match data block. It is
+ also automatically freed if the match data block is re-used for another
+ match operation.
+
+ PCRE2_DISABLE_RECURSELOOP_CHECK
+
+ This option is relevant only to pcre2_match() for interpretive match-
+ ing. It is ignored when JIT is used, and is forbidden for
+ pcre2_dfa_match().
+
+ The use of recursion in patterns can lead to infinite loops. In the in-
+ terpretive matcher these would be eventually caught by the match or
+ heap limits, but this could take a long time and/or use a lot of memory
+ if the limits are large. There is therefore a check at the start of
+ each recursion. If the same group is still active from a previous
+ call, and the current subject pointer is the same as it was at the
+ start of that group, and the furthest inspected character of the sub-
+ ject has not changed, an error is generated.
+
+ There are rare cases of matches that would complete, but nevertheless
+ trigger this error. This option disables the check. It is provided
+ mainly for testing when comparing JIT and interpretive behaviour.
+
+ PCRE2_ENDANCHORED
+
+ If the PCRE2_ENDANCHORED option is set, any string that pcre2_match()
+ matches must be right at the end of the subject string. Note that set-
+ ting the option at match time disables JIT matching.
+
+ PCRE2_NOTBOL
+
+ This option specifies that first character of the subject string is not
+ the beginning of a line, so the circumflex metacharacter should not
+ match before it. Setting this without having set PCRE2_MULTILINE at
+ compile time causes circumflex never to match. This option affects only
+ the behaviour of the circumflex metacharacter. It does not affect \A.
+
+ PCRE2_NOTEOL
+
+ This option specifies that the end of the subject string is not the end
+ of a line, so the dollar metacharacter should not match it nor (except
+ in multiline mode) a newline immediately before it. Setting this with-
+ out having set PCRE2_MULTILINE at compile time causes dollar never to
+ match. This option affects only the behaviour of the dollar metacharac-
+ ter. It does not affect \Z or \z.
+
+ PCRE2_NOTEMPTY
+
+ An empty string is not considered to be a valid match if this option is
+ set. If there are alternatives in the pattern, they are tried. If all
+ the alternatives match the empty string, the entire match fails. For
+ example, if the pattern
+
+ a?b?
+
+ is applied to a string not beginning with "a" or "b", it matches an
+ empty string at the start of the subject. With PCRE2_NOTEMPTY set, this
+ match is not valid, so pcre2_match() searches further into the string
+ for occurrences of "a" or "b".
+
+ PCRE2_NOTEMPTY_ATSTART
+
+ This is like PCRE2_NOTEMPTY, except that it locks out an empty string
+ match only at the first matching position, that is, at the start of the
+ subject plus the starting offset. An empty string match later in the
+ subject is permitted. If the pattern is anchored, such a match can oc-
+ cur only if the pattern contains \K.
+
+ PCRE2_NO_JIT
+
+ By default, if a pattern has been successfully processed by
+ pcre2_jit_compile(), JIT is automatically used when pcre2_match() is
+ called with options that JIT supports. Setting PCRE2_NO_JIT disables
+ the use of JIT; it forces matching to be done by the interpreter.
+
+ PCRE2_NO_UTF_CHECK
+
+ When PCRE2_UTF is set at compile time, the validity of the subject as a
+ UTF string is checked unless PCRE2_NO_UTF_CHECK is passed to
+ pcre2_match() or PCRE2_MATCH_INVALID_UTF was passed to pcre2_compile().
+ The latter special case is discussed in detail in the pcre2unicode doc-
+ umentation.
+
+ In the default case, if a non-zero starting offset is given, the check
+ is applied only to that part of the subject that could be inspected
+ during matching, and there is a check that the starting offset points
+ to the first code unit of a character or to the end of the subject. If
+ there are no lookbehind assertions in the pattern, the check starts at
+ the starting offset. Otherwise, it starts at the length of the longest
+ lookbehind before the starting offset, or at the start of the subject
+ if there are not that many characters before the starting offset. Note
+ that the sequences \b and \B are one-character lookbehinds.
+
+ The check is carried out before any other processing takes place, and a
+ negative error code is returned if the check fails. There are several
+ UTF error codes for each code unit width, corresponding to different
+ problems with the code unit sequence. There are discussions about the
+ validity of UTF-8 strings, UTF-16 strings, and UTF-32 strings in the
+ pcre2unicode documentation.
+
+ If you know that your subject is valid, and you want to skip this check
+ for performance reasons, you can set the PCRE2_NO_UTF_CHECK option when
+ calling pcre2_match(). You might want to do this for the second and
+ subsequent calls to pcre2_match() if you are making repeated calls to
+ find multiple matches in the same subject string.
+
+ Warning: Unless PCRE2_MATCH_INVALID_UTF was set at compile time, when
+ PCRE2_NO_UTF_CHECK is set at match time the effect of passing an in-
+ valid string as a subject, or an invalid value of startoffset, is unde-
+ fined. Your program may crash or loop indefinitely or give wrong re-
+ sults.
+
+ PCRE2_PARTIAL_HARD
+ PCRE2_PARTIAL_SOFT
+
+ These options turn on the partial matching feature. A partial match oc-
+ curs if the end of the subject string is reached successfully, but
+ there are not enough subject characters to complete the match. In addi-
+ tion, either at least one character must have been inspected or the
+ pattern must contain a lookbehind, or the pattern must be one that
+ could match an empty string.
+
+ If this situation arises when PCRE2_PARTIAL_SOFT (but not PCRE2_PAR-
+ TIAL_HARD) is set, matching continues by testing any remaining alterna-
+ tives. Only if no complete match can be found is PCRE2_ERROR_PARTIAL
+ returned instead of PCRE2_ERROR_NOMATCH. In other words, PCRE2_PAR-
+ TIAL_SOFT specifies that the caller is prepared to handle a partial
+ match, but only if no complete match can be found.
+
+ If PCRE2_PARTIAL_HARD is set, it overrides PCRE2_PARTIAL_SOFT. In this
+ case, if a partial match is found, pcre2_match() immediately returns
+ PCRE2_ERROR_PARTIAL, without considering any other alternatives. In
+ other words, when PCRE2_PARTIAL_HARD is set, a partial match is consid-
+ ered to be more important than an alternative complete match.
+
+ There is a more detailed discussion of partial and multi-segment match-
+ ing, with examples, in the pcre2partial documentation.
+
+
+NEWLINE HANDLING WHEN MATCHING
+
+ When PCRE2 is built, a default newline convention is set; this is usu-
+ ally the standard convention for the operating system. The default can
+ be overridden in a compile context by calling pcre2_set_newline(). It
+ can also be overridden by starting a pattern string with, for example,
+ (*CRLF), as described in the section on newline conventions in the
+ pcre2pattern page. During matching, the newline choice affects the be-
+ haviour of the dot, circumflex, and dollar metacharacters. It may also
+ alter the way the match starting position is advanced after a match
+ failure for an unanchored pattern.
+
+ When PCRE2_NEWLINE_CRLF, PCRE2_NEWLINE_ANYCRLF, or PCRE2_NEWLINE_ANY is
+ set as the newline convention, and a match attempt for an unanchored
+ pattern fails when the current starting position is at a CRLF sequence,
+ and the pattern contains no explicit matches for CR or LF characters,
+ the match position is advanced by two characters instead of one, in
+ other words, to after the CRLF.
+
+ The above rule is a compromise that makes the most common cases work as
+ expected. For example, if the pattern is .+A (and the PCRE2_DOTALL op-
+ tion is not set), it does not match the string "\r\nA" because, after
+ failing at the start, it skips both the CR and the LF before retrying.
+ However, the pattern [\r\n]A does match that string, because it con-
+ tains an explicit CR or LF reference, and so advances only by one char-
+ acter after the first failure.
+
+ An explicit match for CR of LF is either a literal appearance of one of
+ those characters in the pattern, or one of the \r or \n or equivalent
+ octal or hexadecimal escape sequences. Implicit matches such as [^X] do
+ not count, nor does \s, even though it includes CR and LF in the char-
+ acters that it matches.
+
+ Notwithstanding the above, anomalous effects may still occur when CRLF
+ is a valid newline sequence and explicit \r or \n escapes appear in the
+ pattern.
+
+
+HOW PCRE2_MATCH() RETURNS A STRING AND CAPTURED SUBSTRINGS
+
+ uint32_t pcre2_get_ovector_count(pcre2_match_data *match_data);
+
+ PCRE2_SIZE *pcre2_get_ovector_pointer(pcre2_match_data *match_data);
+
+ In general, a pattern matches a certain portion of the subject, and in
+ addition, further substrings from the subject may be picked out by
+ parenthesized parts of the pattern. Following the usage in Jeffrey
+ Friedl's book, this is called "capturing" in what follows, and the
+ phrase "capture group" (Perl terminology) is used for a fragment of a
+ pattern that picks out a substring. PCRE2 supports several other kinds
+ of parenthesized group that do not cause substrings to be captured. The
+ pcre2_pattern_info() function can be used to find out how many capture
+ groups there are in a compiled pattern.
+
+ You can use auxiliary functions for accessing captured substrings by
+ number or by name, as described in sections below.
+
+ Alternatively, you can make direct use of the vector of PCRE2_SIZE val-
+ ues, called the ovector, which contains the offsets of captured
+ strings. It is part of the match data block. The function
+ pcre2_get_ovector_pointer() returns the address of the ovector, and
+ pcre2_get_ovector_count() returns the number of pairs of values it con-
+ tains.
+
+ Within the ovector, the first in each pair of values is set to the off-
+ set of the first code unit of a substring, and the second is set to the
+ offset of the first code unit after the end of a substring. These val-
+ ues are always code unit offsets, not character offsets. That is, they
+ are byte offsets in the 8-bit library, 16-bit offsets in the 16-bit li-
+ brary, and 32-bit offsets in the 32-bit library.
+
+ After a partial match (error return PCRE2_ERROR_PARTIAL), only the
+ first pair of offsets (that is, ovector[0] and ovector[1]) are set.
+ They identify the part of the subject that was partially matched. See
+ the pcre2partial documentation for details of partial matching.
+
+ After a fully successful match, the first pair of offsets identifies
+ the portion of the subject string that was matched by the entire pat-
+ tern. The next pair is used for the first captured substring, and so
+ on. The value returned by pcre2_match() is one more than the highest
+ numbered pair that has been set. For example, if two substrings have
+ been captured, the returned value is 3. If there are no captured sub-
+ strings, the return value from a successful match is 1, indicating that
+ just the first pair of offsets has been set.
+
+ If a pattern uses the \K escape sequence within a positive lookahead
+ assertion, the reported start of a successful match can be greater than
+ the end of the match. For example, if the pattern (?=ab\K) is matched
+ against "ab", the start and end offset values for the match are 2 and
+ 0.
+
+ If a capture group is matched repeatedly within a single match opera-
+ tion, it is the last portion of the subject that it matched that is re-
+ turned.
+
+ If the ovector is too small to hold all the captured substring offsets,
+ as much as possible is filled in, and the function returns a value of
+ zero. If captured substrings are not of interest, pcre2_match() may be
+ called with a match data block whose ovector is of minimum length (that
+ is, one pair).
+
+ It is possible for capture group number n+1 to match some part of the
+ subject when group n has not been used at all. For example, if the
+ string "abc" is matched against the pattern (a|(z))(bc) the return from
+ the function is 4, and groups 1 and 3 are matched, but 2 is not. When
+ this happens, both values in the offset pairs corresponding to unused
+ groups are set to PCRE2_UNSET.
+
+ Offset values that correspond to unused groups at the end of the ex-
+ pression are also set to PCRE2_UNSET. For example, if the string "abc"
+ is matched against the pattern (abc)(x(yz)?)? groups 2 and 3 are not
+ matched. The return from the function is 2, because the highest used
+ capture group number is 1. The offsets for the second and third capture
+ groups (assuming the vector is large enough, of course) are set to
+ PCRE2_UNSET.
+
+ Elements in the ovector that do not correspond to capturing parentheses
+ in the pattern are never changed. That is, if a pattern contains n cap-
+ turing parentheses, no more than ovector[0] to ovector[2n+1] are set by
+ pcre2_match(). The other elements retain whatever values they previ-
+ ously had. After a failed match attempt, the contents of the ovector
+ are unchanged.
+
+
+OTHER INFORMATION ABOUT A MATCH
+
+ PCRE2_SPTR pcre2_get_mark(pcre2_match_data *match_data);
+
+ PCRE2_SIZE pcre2_get_startchar(pcre2_match_data *match_data);
+
+ As well as the offsets in the ovector, other information about a match
+ is retained in the match data block and can be retrieved by the above
+ functions in appropriate circumstances. If they are called at other
+ times, the result is undefined.
+
+ After a successful match, a partial match (PCRE2_ERROR_PARTIAL), or a
+ failure to match (PCRE2_ERROR_NOMATCH), a mark name may be available.
+ The function pcre2_get_mark() can be called to access this name, which
+ can be specified in the pattern by any of the backtracking control
+ verbs, not just (*MARK). The same function applies to all the verbs. It
+ returns a pointer to the zero-terminated name, which is within the com-
+ piled pattern. If no name is available, NULL is returned. The length of
+ the name (excluding the terminating zero) is stored in the code unit
+ that precedes the name. You should use this length instead of relying
+ on the terminating zero if the name might contain a binary zero.
+
+ After a successful match, the name that is returned is the last mark
+ name encountered on the matching path through the pattern. Instances of
+ backtracking verbs without names do not count. Thus, for example, if
+ the matching path contains (*MARK:A)(*PRUNE), the name "A" is returned.
+ After a "no match" or a partial match, the last encountered name is re-
+ turned. For example, consider this pattern:
+
+ ^(*MARK:A)((*MARK:B)a|b)c
+
+ When it matches "bc", the returned name is A. The B mark is "seen" in
+ the first branch of the group, but it is not on the matching path. On
+ the other hand, when this pattern fails to match "bx", the returned
+ name is B.
+
+ Warning: By default, certain start-of-match optimizations are used to
+ give a fast "no match" result in some situations. For example, if the
+ anchoring is removed from the pattern above, there is an initial check
+ for the presence of "c" in the subject before running the matching en-
+ gine. This check fails for "bx", causing a match failure without seeing
+ any marks. You can disable the start-of-match optimizations by setting
+ the PCRE2_NO_START_OPTIMIZE option for pcre2_compile() or by starting
+ the pattern with (*NO_START_OPT).
+
+ After a successful match, a partial match, or one of the invalid UTF
+ errors (for example, PCRE2_ERROR_UTF8_ERR5), pcre2_get_startchar() can
+ be called. After a successful or partial match it returns the code unit
+ offset of the character at which the match started. For a non-partial
+ match, this can be different to the value of ovector[0] if the pattern
+ contains the \K escape sequence. After a partial match, however, this
+ value is always the same as ovector[0] because \K does not affect the
+ result of a partial match.
+
+ After a UTF check failure, pcre2_get_startchar() can be used to obtain
+ the code unit offset of the invalid UTF character. Details are given in
+ the pcre2unicode page.
+
+
+ERROR RETURNS FROM pcre2_match()
+
+ If pcre2_match() fails, it returns a negative number. This can be con-
+ verted to a text string by calling the pcre2_get_error_message() func-
+ tion (see "Obtaining a textual error message" below). Negative error
+ codes are also returned by other functions, and are documented with
+ them. The codes are given names in the header file. If UTF checking is
+ in force and an invalid UTF subject string is detected, one of a number
+ of UTF-specific negative error codes is returned. Details are given in
+ the pcre2unicode page. The following are the other errors that may be
+ returned by pcre2_match():
+
+ PCRE2_ERROR_NOMATCH
+
+ The subject string did not match the pattern.
+
+ PCRE2_ERROR_PARTIAL
+
+ The subject string did not match, but it did match partially. See the
+ pcre2partial documentation for details of partial matching.
+
+ PCRE2_ERROR_BADMAGIC
+
+ PCRE2 stores a 4-byte "magic number" at the start of the compiled code,
+ to catch the case when it is passed a junk pointer. This is the error
+ that is returned when the magic number is not present.
+
+ PCRE2_ERROR_BADMODE
+
+ This error is given when a compiled pattern is passed to a function in
+ a library of a different code unit width, for example, a pattern com-
+ piled by the 8-bit library is passed to a 16-bit or 32-bit library
+ function.
+
+ PCRE2_ERROR_BADOFFSET
+
+ The value of startoffset was greater than the length of the subject.
+
+ PCRE2_ERROR_BADOPTION
+
+ An unrecognized bit was set in the options argument.
+
+ PCRE2_ERROR_BADUTFOFFSET
+
+ The UTF code unit sequence that was passed as a subject was checked and
+ found to be valid (the PCRE2_NO_UTF_CHECK option was not set), but the
+ value of startoffset did not point to the beginning of a UTF character
+ or the end of the subject.
+
+ PCRE2_ERROR_CALLOUT
+
+ This error is never generated by pcre2_match() itself. It is provided
+ for use by callout functions that want to cause pcre2_match() or
+ pcre2_callout_enumerate() to return a distinctive error code. See the
+ pcre2callout documentation for details.
+
+ PCRE2_ERROR_DEPTHLIMIT
+
+ The nested backtracking depth limit was reached.
+
+ PCRE2_ERROR_HEAPLIMIT
+
+ The heap limit was reached.
+
+ PCRE2_ERROR_INTERNAL
+
+ An unexpected internal error has occurred. This error could be caused
+ by a bug in PCRE2 or by overwriting of the compiled pattern.
+
+ PCRE2_ERROR_JIT_STACKLIMIT
+
+ This error is returned when a pattern that was successfully studied us-
+ ing JIT is being matched, but the memory available for the just-in-time
+ processing stack is not large enough. See the pcre2jit documentation
+ for more details.
+
+ PCRE2_ERROR_MATCHLIMIT
+
+ The backtracking match limit was reached.
+
+ PCRE2_ERROR_NOMEMORY
+
+ Heap memory is used to remember backtracking points. This error is
+ given when the memory allocation function (default or custom) fails.
+ Note that a different error, PCRE2_ERROR_HEAPLIMIT, is given if the
+ amount of memory needed exceeds the heap limit. PCRE2_ERROR_NOMEMORY is
+ also returned if PCRE2_COPY_MATCHED_SUBJECT is set and memory alloca-
+ tion fails.
+
+ PCRE2_ERROR_NULL
+
+ Either the code, subject, or match_data argument was passed as NULL.
+
+ PCRE2_ERROR_RECURSELOOP
+
+ This error is returned when pcre2_match() detects a recursion loop
+ within the pattern. Specifically, it means that either the whole pat-
+ tern or a capture group has been called recursively for the second time
+ at the same position in the subject string. Some simple patterns that
+ might do this are detected and faulted at compile time, but more com-
+ plicated cases, in particular mutual recursions between two different
+ groups, cannot be detected until matching is attempted.
+
+
+OBTAINING A TEXTUAL ERROR MESSAGE
+
+ int pcre2_get_error_message(int errorcode, PCRE2_UCHAR *buffer,
+ PCRE2_SIZE bufflen);
+
+ A text message for an error code from any PCRE2 function (compile,
+ match, or auxiliary) can be obtained by calling pcre2_get_error_mes-
+ sage(). The code is passed as the first argument, with the remaining
+ two arguments specifying a code unit buffer and its length in code
+ units, into which the text message is placed. The message is returned
+ in code units of the appropriate width for the library that is being
+ used.
+
+ The returned message is terminated with a trailing zero, and the func-
+ tion returns the number of code units used, excluding the trailing
+ zero. If the error number is unknown, the negative error code PCRE2_ER-
+ ROR_BADDATA is returned. If the buffer is too small, the message is
+ truncated (but still with a trailing zero), and the negative error code
+ PCRE2_ERROR_NOMEMORY is returned. None of the messages is very long; a
+ buffer size of 120 code units is ample.
+
+
+ITERATING OVER ALL MATCHES
+
+ int pcre2_next_match(pcre2_match_data *match_data,
+ PCRE2_SIZE *pstart_offset, uint32_t *poptions);
+
+ A common task for applications is to implement "global" matching behav-
+ iour, for example, replacing all matches in the subject; splitting the
+ subject on all matches; or simply counting the number of matches. The
+ pcre2_next_match() function helps with this task by providing the ap-
+ propriate parameters for the next match attempt (available since PCRE2
+ 10.47).
+
+ First, a match attempt should be made using one of the matching func-
+ tions (pcre2_match(), pcre2_dfa_match(), or pcre2_jit_match()). Then,
+ pcre2_next_match() can be called, providing the same match_data parame-
+ ter.
+
+ It returns 0 ("false") if there is no need to make a further match at-
+ tempt, or 1 ("true") if another match should be attempted. Returning 1
+ does not imply that there is another match, only that another match
+ should be attempted (which may return PCRE2_ERROR_NOMATCH).
+
+ The *pstart_offset and *poptions are set if the function returns 1.
+ The *pstart_offset should be passed to the next match attempt directly,
+ and the *poptions should be passed to the next match attempt by combin-
+ ing with the application's match options using OR.
+
+ There is some code that demonstrates how to do this in the pcre2demo
+ sample program. The general pattern is:
+
+ uint32_t app_options = ...;
+ uint32_t global_options = 0;
+ PCRE2_SIZE start_offset = 0;
+ while (1)
+ {
+ int rc = pcre2_match(re, subject, subject_len, start_offset,
+ app_options | global_options, match_data,
+ match_context);
+
+ if (rc == PCRE2_ERROR_NOMATCH) break; /* no match, and no more attempts */
+ if (rc < 0) { ... exit }
+
+ ...handle the match
+
+ if (!pcre2_next_match(match_data, &start_offset, &global_options))
+ break; /* no more attempts */
+ }
+
+ The guarantees provided by pcre2_next_match() are that the start_offset
+ will advance, so the loop will definitely terminate. The conditions
+ which ensure this are that either: (a) pcre2_next_match() returns 0
+ (false); or (b) the returned *pstart_offset is strictly greater than
+ the previous start_offset; or (c) if the previous match was a success-
+ ful match of the empty string then the returned *pstart_offset is equal
+ to the previous ovector[1], and *poptions will be set to
+ PCRE2_NOTEMPTY_ATSTART to prevent another empty match from being re-
+ turned.
+
+ A loop implemented as shown above will always terminate, unless there
+ is a bug in PCRE2. As a measure of "defensive programming", applica-
+ tions are encouraged to add an assertion or check to break their loop
+ if it does not make progress (and report the issue as a bug).
+
+ If an application does not use the flag PCRE2_EXTRA_AL-
+ LOW_LOOKAROUND_BSK, then each match is "well-behaved" and satisfies:
+
+ start_offset <= ovector[0] <= ovector[1].
+
+ In this case, the matches found by pcre2_match() with
+ pcre2_next_match() will be sorted, non-overlapping (possibly touching),
+ and with no duplicates.
+
+ Otherwise, if PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK is used, then the guar-
+ antees are considerably weaker. We do not guarantee that the matches
+ will always advance: only that the start_offset will. The matches found
+ by pcre2_match() with pcre2_next_match() will be a finite sequence (as
+ pcre2_next_match() ensures that start_offset advances, so the search
+ will terminate). The matches can however be overlapping, can contain
+ duplicates, and (in truly pathological examples) may not even be sorted
+ by ovector[0]. Additionally, each match itself can end before it starts
+ (ovector[1] < ovector[0]). We recommend that applications do not set
+ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK.
+
+
+EXTRACTING CAPTURED SUBSTRINGS BY NUMBER
+
+ int pcre2_substring_length_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_SIZE *length);
+
+ int pcre2_substring_copy_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_UCHAR *buffer,
+ PCRE2_SIZE *bufflen);
+
+ int pcre2_substring_get_bynumber(pcre2_match_data *match_data,
+ uint32_t number, PCRE2_UCHAR **bufferptr,
+ PCRE2_SIZE *bufflen);
+
+ void pcre2_substring_free(PCRE2_UCHAR *buffer);
+
+ Captured substrings can be accessed directly by using the ovector as
+ described above. For convenience, auxiliary functions are provided for
+ extracting captured substrings as new, separate, zero-terminated
+ strings. A substring that contains a binary zero is correctly extracted
+ and has a further zero added on the end, but the result is not, of
+ course, a C string.
+
+ The functions in this section identify substrings by number. The number
+ zero refers to the entire matched substring, with higher numbers refer-
+ ring to substrings captured by parenthesized groups. After a partial
+ match, only substring zero is available. An attempt to extract any
+ other substring gives the error PCRE2_ERROR_PARTIAL. The next section
+ describes similar functions for extracting captured substrings by name.
+
+ If a pattern uses the \K escape sequence within a positive lookahead
+ assertion, the reported start of a successful match can be greater than
+ the end of the match. For example, if the pattern (?=ab\K) is matched
+ against "ab", the start and end offset values for the match are 2 and
+ 0. In this situation, calling these functions with a zero substring
+ number extracts a zero-length empty string.
+
+ You can find the length in code units of a captured substring without
+ extracting it by calling pcre2_substring_length_bynumber(). The first
+ argument is a pointer to the match data block, the second is the group
+ number, and the third is a pointer to a variable into which the length
+ is placed. If you just want to know whether or not the substring has
+ been captured, you can pass the third argument as NULL.
+
+ The pcre2_substring_copy_bynumber() function copies a captured sub-
+ string into a supplied buffer, whereas pcre2_substring_get_bynumber()
+ copies it into new memory, obtained using the same memory allocation
+ function that was used for the match data block. The first two argu-
+ ments of these functions are a pointer to the match data block and a
+ capture group number.
+
+ The final arguments of pcre2_substring_copy_bynumber() are a pointer to
+ the buffer and a pointer to a variable that contains its length in code
+ units. This is updated to contain the actual number of code units used
+ for the extracted substring, excluding the terminating zero.
+
+ For pcre2_substring_get_bynumber() the third and fourth arguments point
+ to variables that are updated with a pointer to the new memory and the
+ number of code units that comprise the substring, again excluding the
+ terminating zero. When the substring is no longer needed, the memory
+ should be freed by calling pcre2_substring_free().
+
+ The return value from all these functions is zero for success, or a
+ negative error code. If the pattern match failed, the match failure
+ code is returned. If a substring number greater than zero is used af-
+ ter a partial match, PCRE2_ERROR_PARTIAL is returned. Other possible
+ error codes are:
+
+ PCRE2_ERROR_NOMEMORY
+
+ The buffer was too small for pcre2_substring_copy_bynumber(), or the
+ attempt to get memory failed for pcre2_substring_get_bynumber().
+
+ PCRE2_ERROR_NOSUBSTRING
+
+ There is no substring with that number in the pattern, that is, the
+ number is greater than the number of capturing parentheses.
+
+ PCRE2_ERROR_UNAVAILABLE
+
+ The substring number, though not greater than the number of captures in
+ the pattern, is greater than the number of slots in the ovector, so the
+ substring could not be captured.
+
+ PCRE2_ERROR_UNSET
+
+ The substring did not participate in the match. For example, if the
+ pattern is (abc)|(def) and the subject is "def", and the ovector con-
+ tains at least two capturing slots, substring number 1 is unset.
+
+
+EXTRACTING A LIST OF ALL CAPTURED SUBSTRINGS
+
+ int pcre2_substring_list_get(pcre2_match_data *match_data,
+ PCRE2_UCHAR ***listptr, PCRE2_SIZE **lengthsptr);
+
+ void pcre2_substring_list_free(PCRE2_UCHAR **list);
+
+ The pcre2_substring_list_get() function extracts all available sub-
+ strings and builds a list of pointers to them. It also (optionally)
+ builds a second list that contains their lengths (in code units), ex-
+ cluding a terminating zero that is added to each of them. All this is
+ done in a single block of memory that is obtained using the same memory
+ allocation function that was used to get the match data block.
+
+ This function must be called only after a successful match. If called
+ after a partial match, the error code PCRE2_ERROR_PARTIAL is returned.
+
+ The address of the memory block is returned via listptr, which is also
+ the start of the list of string pointers. The end of the list is marked
+ by a NULL pointer. The address of the list of lengths is returned via
+ lengthsptr. If your strings do not contain binary zeros and you do not
+ therefore need the lengths, you may supply NULL as the lengthsptr argu-
+ ment to disable the creation of a list of lengths. The yield of the
+ function is zero if all went well, or PCRE2_ERROR_NOMEMORY if the mem-
+ ory block could not be obtained. When the list is no longer needed, it
+ should be freed by calling pcre2_substring_list_free().
+
+ If this function encounters a substring that is unset, which can happen
+ when capture group number n+1 matches some part of the subject, but
+ group n has not been used at all, it returns an empty string. This can
+ be distinguished from a genuine zero-length substring by inspecting the
+ appropriate offset in the ovector, which contain PCRE2_UNSET for unset
+ substrings, or by calling pcre2_substring_length_bynumber().
+
+
+EXTRACTING CAPTURED SUBSTRINGS BY NAME
+
+ int pcre2_substring_number_from_name(const pcre2_code *code,
+ PCRE2_SPTR name);
+
+ int pcre2_substring_length_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_SIZE *length);
+
+ int pcre2_substring_copy_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_UCHAR *buffer, PCRE2_SIZE *bufflen);
+
+ int pcre2_substring_get_byname(pcre2_match_data *match_data,
+ PCRE2_SPTR name, PCRE2_UCHAR **bufferptr, PCRE2_SIZE *bufflen);
+
+ void pcre2_substring_free(PCRE2_UCHAR *buffer);
+
+ To extract a substring by name, you first have to find associated num-
+ ber. For example, for this pattern:
+
+ (a+)b(?\d+)...
+
+ the number of the capture group called "xxx" is 2. If the name is known
+ to be unique (PCRE2_DUPNAMES was not set), you can find the number from
+ the name by calling pcre2_substring_number_from_name(). The first argu-
+ ment is the compiled pattern, and the second is the name. The yield of
+ the function is the group number, PCRE2_ERROR_NOSUBSTRING if there is
+ no group with that name, or PCRE2_ERROR_NOUNIQUESUBSTRING if there is
+ more than one group with that name. Given the number, you can extract
+ the substring directly from the ovector, or use one of the "bynumber"
+ functions described above.
+
+ For convenience, there are also "byname" functions that correspond to
+ the "bynumber" functions, the only difference being that the second ar-
+ gument is a name instead of a number. If PCRE2_DUPNAMES is set and
+ there are duplicate names, these functions scan all the groups with the
+ given name, and return the captured substring from the first named
+ group that is set.
+
+ If there are no groups with the given name, PCRE2_ERROR_NOSUBSTRING is
+ returned. If all groups with the name have numbers that are greater
+ than the number of slots in the ovector, PCRE2_ERROR_UNAVAILABLE is re-
+ turned. If there is at least one group with a slot in the ovector, but
+ no group is found to be set, PCRE2_ERROR_UNSET is returned.
+
+ Warning: If the pattern uses the (?| feature to set up multiple capture
+ groups with the same number, as described in the section on duplicate
+ group numbers in the pcre2pattern page, you cannot use names to distin-
+ guish the different capture groups, because names are not included in
+ the compiled code. The matching process uses only numbers. For this
+ reason, the use of different names for groups with the same number
+ causes an error at compile time.
+
+
+CREATING A NEW STRING WITH SUBSTITUTIONS
+
+ int pcre2_substitute(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext, PCRE2_SPTR replacement,
+ PCRE2_SIZE rlength, PCRE2_UCHAR *outputbuffer,
+ PCRE2_SIZE *outlengthptr);
+
+ This function optionally calls pcre2_match() and then makes a copy of
+ the subject string in outputbuffer, replacing parts that were matched
+ with the replacement string, whose length is supplied in rlength, which
+ can be given as PCRE2_ZERO_TERMINATED for a zero-terminated string. As
+ a special case, if replacement is NULL and rlength is zero, the re-
+ placement is assumed to be an empty string. If rlength is non-zero, an
+ error occurs if replacement is NULL.
+
+ There is an option (see PCRE2_SUBSTITUTE_REPLACEMENT_ONLY below) to re-
+ turn just the replacement string(s). The default action is to perform
+ just one replacement if the pattern matches, but there is an option
+ that requests multiple replacements (see PCRE2_SUBSTITUTE_GLOBAL be-
+ low).
+
+ If successful, pcre2_substitute() returns the number of substitutions
+ that were carried out. This may be zero if no match was found, and is
+ never greater than one unless PCRE2_SUBSTITUTE_GLOBAL is set. A nega-
+ tive value is returned if an error is detected.
+
+ Matches in which a \K item in a lookahead in the pattern causes the
+ match to end before it starts are not supported, and give rise to an
+ error return. For global replacements, matches in which \K in a lookbe-
+ hind causes the match to start earlier than the point that was reached
+ in the previous iteration are also not supported. (These cases are only
+ possible if the pattern was compiled with the backwards-compatibility
+ option PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK.)
+
+ The first seven arguments of pcre2_substitute() are the same as for
+ pcre2_match(), except that the partial matching options are not permit-
+ ted, and match_data may be passed as NULL, in which case a match data
+ block is obtained and freed within this function, using memory manage-
+ ment functions from the match context, if provided, or else those that
+ were used to allocate memory for the compiled code.
+
+ If match_data is not NULL and PCRE2_SUBSTITUTE_MATCHED is not set, the
+ provided block is used for all calls to pcre2_match(), and its contents
+ afterwards are the result of the final call made internally by
+ pcre2_substitute() to the matching function. For global changes, this
+ will always be a no-match error. The contents of the ovector within the
+ match data block may or may not have been changed.
+
+ As well as the usual options for pcre2_match(), a number of additional
+ options can be set in the options argument of pcre2_substitute(). One
+ such option is PCRE2_SUBSTITUTE_MATCHED. When this is set, an external
+ match_data block must be provided, and it must have already been used
+ for an external call to pcre2_match() (or pcre2_jit_match()) with the
+ same pattern, subject pointer, effective subject length, start offset,
+ and match option arguments (substitute-specific options can be added to
+ the options argument). If any of these parameters is changed,
+ pcre2_substitute() returns an error. The data in the match_data block
+ (return code, offset vector) is used for the first substitution instead
+ of calling pcre2_match() from within pcre2_substitute(). This allows an
+ application to check for a match before choosing to substitute, without
+ having to repeat the match.
+
+ If the contents of the subject buffer are mutated in between
+ pcre2_match() and a call to pcre2_substitute() with PCRE2_SUBSTI-
+ TUTE_MATCHED, the behaviour is unsafe; in particular, in this case,
+ PCRE2 is unable to ensure that the offsets in the ovector point to the
+ start of characters (with UTF-encoded input).
+
+ The contents of the externally supplied match data block are not
+ changed when PCRE2_SUBSTITUTE_MATCHED is set, and so the match block is
+ permitted for use in another call using PCRE2_SUBSTITUTE_MATCHED. If
+ PCRE2_SUBSTITUTE_GLOBAL is also set, pcre2_match() is called after the
+ first substitution to check for furthe matches, but this is done using
+ an internally obtained match data block, thus always leaving the exter-
+ nal block unchanged.
+
+ The code argument is not used for matching before the first substitu-
+ tion when PCRE2_SUBSTITUTE_MATCHED is set, but it must be provided,
+ even when PCRE2_SUBSTITUTE_GLOBAL is not set, because it contains in-
+ formation such as the UTF setting and the number of capturing parenthe-
+ ses in the pattern.
+
+ When using PCRE2_SUBSTITUTE_MATCHED, you should not modify the subject
+ string in between the prior call to pcre2_match() and pcre2_substi-
+ tute(), as the substitution assumes that the passed-in ovector is com-
+ patible with the subject string. Although PCRE2 does verify that the
+ subject is a pointer to the same buffer, it cannot in general verify
+ whether the contents of the buffer have changed. For example, if the
+ subject buffer is mutated from one valid UTF-8 string to another valid
+ string, of the same length in code units, the ovector offsets are no
+ longer guaranteed to point to the start of a character. Beware that
+ with PCRE2_SUBSTITUTE_MATCHED in UTF mode, the subject string is not
+ re-scanned for UTF validity when pcre2_substitute() first uses it.
+
+ The default action of pcre2_substitute() is to return a copy of the
+ subject string with matched substrings replaced. However, if PCRE2_SUB-
+ STITUTE_REPLACEMENT_ONLY is set, only the replacement substrings are
+ returned. In the global case, multiple replacements are concatenated in
+ the output buffer. Substitution callouts (see below) can be used to
+ separate them if necessary.
+
+ Partial matching is supported, with limitations: if matching succeeds
+ but with a partial match, then pcre2_substitute returns PCRE2_ER-
+ ROR_PARTIAL. When partial-matching (either of PCRE2_PARTIAL_HARD or
+ PCRE2_PARTIAL_SOFT is passed), then PCRE2_SUBSTITUTE_REPLACEMENT_ONLY
+ must also be set, or else PCRE2_ERROR_BADOPTION is returned. Similarly,
+ certain replacement items ($' and $_) cause PCRE2_ERROR_PARTIALSUBS to
+ be returned when partial-matching, even if a complete match is found.
+
+ The outlengthptr argument of pcre2_substitute() must point to a vari-
+ able that contains the length, in code units, of the output buffer. If
+ the function is successful, the value is updated to contain the length
+ in code units of the new string, excluding the trailing zero that is
+ automatically added.
+
+ If the function is not successful, the value set via outlengthptr de-
+ pends on the type of error. For syntax errors in the replacement
+ string, the value is the offset in the replacement string where the er-
+ ror was detected. For other errors, the value is PCRE2_UNSET by de-
+ fault. This includes the case of the output buffer being too small, un-
+ less PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set.
+
+ PCRE2_SUBSTITUTE_OVERFLOW_LENGTH changes what happens when the output
+ buffer is too small. The default action is to return PCRE2_ERROR_NOMEM-
+ ORY immediately. If this option is set, however, pcre2_substitute()
+ continues to go through the motions of matching and substituting (with-
+ out, of course, writing anything) in order to compute the size of
+ buffer that is needed, which will include the extra space for the ter-
+ minating NUL. This value is passed back via the outlengthptr variable,
+ with the result of the function still being PCRE2_ERROR_NOMEMORY.
+
+ Passing a buffer size of zero is a permitted way of finding out how
+ much memory is needed for given substitution. However, this does mean
+ that the entire operation is carried out twice. Depending on the appli-
+ cation, it may be more efficient to allocate a large buffer and free
+ the excess afterwards, instead of using PCRE2_SUBSTITUTE_OVER-
+ FLOW_LENGTH.
+
+ The replacement string, which is interpreted as a UTF string in UTF
+ mode, is checked for UTF validity unless PCRE2_NO_UTF_CHECK is set. An
+ invalid UTF replacement string causes an immediate return with the rel-
+ evant UTF error code.
+
+ If PCRE2_SUBSTITUTE_LITERAL is set, the replacement string is not in-
+ terpreted in any way. By default, however, a dollar character is an es-
+ cape character that can specify the insertion of characters from cap-
+ ture groups and names from (*MARK) or other control verbs in the pat-
+ tern. Dollar is the only escape character (backslash is treated as lit-
+ eral). The following forms are recognized:
+
+ $$ insert a dollar character
+ $n or ${n} insert the contents of group n
+ $0 or $& insert the entire matched substring
+ $` insert the substring that precedes the match
+ $' insert the substring that follows the match
+ $_ insert the entire input string
+ $+ insert the highest-numbered capture group which
+ matched
+ $*MARK or ${*MARK} insert a control verb name
+
+ Either a group number or a group name can be given for n, for example
+ $2 or $NAME. Curly brackets are required only if the following charac-
+ ter would be interpreted as part of the number or name. The number may
+ be zero to include the entire matched string. For example, if the pat-
+ tern a(b)c is matched with "=abc=" and the replacement string
+ "+$1$0$1+", the result is "=+babcb+=".
+
+ The JavaScript form $, where the angle brackets are part of the
+ syntax, is also recognized for group names, but not for group numbers
+ or *MARK.
+
+ $*MARK inserts the name from the last encountered backtracking control
+ verb on the matching path that has a name. (*MARK) must always include
+ a name, but the other verbs need not. For example, in the case of
+ (*MARK:A)(*PRUNE) the name inserted is "A", but for (*MARK:A)(*PRUNE:B)
+ the relevant name is "B". This facility can be used to perform simple
+ simultaneous substitutions, as this pcre2test example shows:
+
+ /(*MARK:pear)apple|(*MARK:orange)lemon/g,replace=${*MARK}
+ apple lemon
+ 2: pear orange
+
+ PCRE2_SUBSTITUTE_GLOBAL causes the function to iterate over the subject
+ string, replacing every matching substring. If this option is not set,
+ only the first matching substring is replaced. The search for matches
+ takes place in the original subject string (that is, previous replace-
+ ments do not affect it). Iteration is implemented by advancing the
+ startoffset value for each search, which is always passed the entire
+ subject string. If an offset limit is set in the match context, search-
+ ing stops when that limit is reached.
+
+ Because global substitutions apply the pattern repeatedly to the sub-
+ ject string, and always iterate over non-overlapping matches, the sub-
+ stitutions done by pcre2_substitute() do not match and substitute text
+ inside the replacement strings themselves (no recursive/iterative sub-
+ stitution). However, applications can easily implement other alterna-
+ tive replacement strategies, such as iteratively replacing, then match-
+ ing and replacing on the result. The replacement loop inside pcre2_sub-
+ stitute() is simple and can be emulated in client code by allocating a
+ buffer, searching for matches in a loop, and calling pcre2_substitute()
+ with PCRE2_SUBSTITUTE_REPLACEMENT_ONLY an PCRE2_SUBSTITUTE_MATCHED, and
+ without PCRE2_SUBSTITUTE_GLOBAL.
+
+ You can restrict the effect of a global substitution to a portion of
+ the subject string by setting either or both of startoffset and an off-
+ set limit. Here is a pcre2test example:
+
+ /B/g,replace=!,use_offset_limit
+ ABC ABC ABC ABC\=offset=3,offset_limit=12
+ 2: ABC A!C A!C ABC
+
+ When continuing with global substitutions after matching a substring
+ with zero length, an attempt to find a non-empty match at the same off-
+ set is performed. If this is not successful, the offset is advanced by
+ one character except when CRLF is a valid newline sequence and the next
+ two characters are CR, LF. In this case, the offset is advanced by two
+ characters.
+
+ PCRE2_SUBSTITUTE_UNKNOWN_UNSET causes references to capture groups that
+ do not appear in the pattern to be treated as unset groups. This option
+ should be used with care, because it means that a typo in a group name
+ or number no longer causes the PCRE2_ERROR_NOSUBSTRING error.
+
+ PCRE2_SUBSTITUTE_UNSET_EMPTY causes unset capture groups (including un-
+ known groups when PCRE2_SUBSTITUTE_UNKNOWN_UNSET is set) to be treated
+ as empty strings when inserted as described above. If this option is
+ not set, an attempt to insert an unset group causes the PCRE2_ERROR_UN-
+ SET error. This option does not influence the extended substitution
+ syntax described below.
+
+ PCRE2_SUBSTITUTE_EXTENDED causes extra processing to be applied to the
+ replacement string. Without this option, only the dollar character is
+ special, and only the group insertion forms listed above are valid.
+ When PCRE2_SUBSTITUTE_EXTENDED is set, several things change:
+
+ Firstly, backslash in a replacement string is interpreted as an escape
+ character. The usual forms such as \x{ddd} can be used to specify par-
+ ticular character codes, and backslash followed by any non-alphanumeric
+ character quotes that character. Extended quoting can be coded using
+ \Q...\E, exactly as in pattern strings. The escapes \b and \v are in-
+ terpreted as the characters backspace and vertical tab, respectively.
+
+ The interpretation of backslash followed by one or more digits is the
+ same as in a pattern, which in Perl has some ambiguities. Details are
+ given in the pcre2pattern page.
+
+ The Python form \g, where the angle brackets are part of the syntax
+ and n is either a group name or number, is recognized as an alternative
+ way of inserting the contents of a group, for example \g<3>.
+
+ There are also four escape sequences for forcing the case of inserted
+ letters. Case forcing applies to all inserted characters, including
+ those from capture groups and letters within \Q...\E quoted sequences.
+ The insertion mechanism has three states: no case forcing, force upper
+ case, and force lower case. The escape sequences change the current
+ state: \U and \L change to upper or lower case forcing, respectively,
+ and \E (when not terminating a \Q quoted sequence) reverts to no case
+ forcing. The sequences \u and \l force the next character (if it is a
+ letter) to upper or lower case, respectively, and then the state auto-
+ matically reverts to no case forcing.
+
+ However, if \u is immediately followed by \L or \l is immediately fol-
+ lowed by \U, the next character's case is forced by the first escape
+ sequence, and subsequent characters by the second. This provides a "ti-
+ tle casing" facility that can be applied to group captures. For exam-
+ ple, if group 1 has captured "heLLo", the replacement string "\u\L$1"
+ becomes "Hello".
+
+ If either PCRE2_UTF or PCRE2_UCP was set when the pattern was compiled,
+ Unicode properties are used for case forcing characters whose code
+ points are greater than 127. However, only simple case folding, as de-
+ termined by the Unicode file CaseFolding.txt is supported. PCRE2 does
+ not support language-specific special casing rules such as using dif-
+ ferent lower case Greek sigmas in the middle and ends of words (as de-
+ fined in the Unicode file SpecialCasing.txt).
+
+ Note that case forcing sequences such as \U...\E do not nest. For exam-
+ ple, the result of processing "\Uaa\LBB\Ecc\E" is "AAbbcc"; the final
+ \E has no effect. Note also that the PCRE2_ALT_BSUX and PCRE2_EX-
+ TRA_ALT_BSUX options do not apply to replacement strings.
+
+ The final effect of setting PCRE2_SUBSTITUTE_EXTENDED is to add more
+ flexibility to capture group substitution. The syntax is similar to
+ that used by Bash:
+
+ ${n:-string}
+ ${n:+string1:string2}
+
+ As in the simple case, n may be a group number or a name. The first
+ form specifies a default value. If group n is set, its value is in-
+ serted; if not, the string is expanded and the result inserted. The
+ second form specifies strings that are expanded and inserted when group
+ n is set or unset, respectively. The first form is just a convenient
+ shorthand for
+
+ ${n:+${n}:string}
+
+ Backslash can be used to escape colons and closing curly brackets in
+ the replacement strings. A change of the case forcing state within a
+ replacement string remains in force afterwards, as shown in this
+ pcre2test example:
+
+ /(some)?(body)/substitute_extended,replace=${1:+\U:\L}HeLLo
+ body
+ 1: hello
+ somebody
+ 1: HELLO
+
+ The PCRE2_SUBSTITUTE_UNSET_EMPTY option does not affect these extended
+ substitutions. However, PCRE2_SUBSTITUTE_UNKNOWN_UNSET does cause un-
+ known groups in the extended syntax forms to be treated as unset.
+
+ If PCRE2_SUBSTITUTE_LITERAL is set, PCRE2_SUBSTITUTE_UNKNOWN_UNSET,
+ PCRE2_SUBSTITUTE_UNSET_EMPTY, and PCRE2_SUBSTITUTE_EXTENDED are irrele-
+ vant and are ignored.
+
+ Substitution errors
+
+ In the event of an error, pcre2_substitute() returns a negative error
+ code. Except for PCRE2_ERROR_NOMATCH (which is never returned), errors
+ from pcre2_match() are passed straight back.
+
+ PCRE2_ERROR_NOSUBSTRING is returned for a non-existent substring inser-
+ tion, unless PCRE2_SUBSTITUTE_UNKNOWN_UNSET is set.
+
+ PCRE2_ERROR_UNSET is returned for an unset substring insertion (includ-
+ ing an unknown substring when PCRE2_SUBSTITUTE_UNKNOWN_UNSET is set)
+ when the simple (non-extended) syntax is used and PCRE2_SUBSTITUTE_UN-
+ SET_EMPTY is not set.
+
+ PCRE2_ERROR_NOMEMORY is returned if the output buffer is not big
+ enough. If the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option is set, the size
+ of buffer that is needed is returned via outlengthptr. Note that this
+ does not happen by default.
+
+ PCRE2_ERROR_NULL is returned if PCRE2_SUBSTITUTE_MATCHED is set but the
+ match_data argument is NULL or if the subject or replacement arguments
+ are NULL. For backward compatibility reasons an exception is made for
+ the replacement argument if the rlength argument is also 0.
+
+ PCRE2_ERROR_BADREPLACEMENT is used for miscellaneous syntax errors in
+ the replacement string, with more particular errors being PCRE2_ER-
+ ROR_BADREPESCAPE (invalid escape sequence), PCRE2_ERROR_REPMISSINGBRACE
+ (closing curly bracket not found), PCRE2_ERROR_BADSUBSTITUTION (syntax
+ error in extended group substitution), and PCRE2_ERROR_BADSUBSPATTERN
+ (the pattern match ended before it started or the match started earlier
+ than the current position in the subject, which can happen if \K is
+ used in a lookaround assertion).
+
+ As for all PCRE2 errors, a text message that describes the error can be
+ obtained by calling the pcre2_get_error_message() function (see "Ob-
+ taining a textual error message" above).
+
+ Substitution callouts
+
+ int pcre2_set_substitute_callout(pcre2_match_context *mcontext,
+ int (*callout_function)(pcre2_substitute_callout_block *, void *),
+ void *callout_data);
+
+ The pcre2_set_substitute_callout() function can be used to specify a
+ callout function for pcre2_substitute(). This information is passed in
+ a match context. The callout function is called after each substitution
+ has been processed, but it can cause the replacement not to happen.
+
+ The callout function is not called for simulated substitutions that
+ happen as a result of the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option. In
+ this mode, when substitution processing exceeds the buffer space pro-
+ vided by the caller, processing continues by counting code units. The
+ simulation is unable to populate the callout block, and so the simula-
+ tion is pessimistic about the required buffer size. Whichever is larger
+ of accepted or rejected substitution is reported as the required size.
+ Therefore, the returned buffer length may be an overestimate (without a
+ substitution callout, it is normally an exact measurement).
+
+ The first argument of the callout function is a pointer to a substitute
+ callout block structure, which contains the following fields, not nec-
+ essarily in this order:
+
+ uint32_t version;
+ uint32_t subscount;
+ PCRE2_SPTR input;
+ PCRE2_SPTR output;
+ PCRE2_SIZE *ovector;
+ uint32_t oveccount;
+ PCRE2_SIZE output_offsets[2];
+
+ The version field contains the version number of the block format. The
+ current version is 0. The version number will increase in future if
+ more fields are added, but the intention is never to remove any of the
+ existing fields.
+
+ The subscount field is the number of the current match. It is 1 for the
+ first callout, 2 for the second, and so on. The input and output point-
+ ers are copies of the values passed to pcre2_substitute().
+
+ The ovector field points to the ovector, which contains the result of
+ the most recent match. The oveccount field contains the number of pairs
+ that are set in the ovector, and is always greater than zero.
+
+ The output_offsets vector contains the offsets of the replacement in
+ the output string. This has already been processed for dollar and (if
+ requested) backslash substitutions as described above.
+
+ The second argument of the callout function is the value passed as
+ callout_data when the function was registered. The value returned by
+ the callout function is interpreted as follows:
+
+ If the value is zero, the replacement is accepted, and, if PCRE2_SUB-
+ STITUTE_GLOBAL is set, processing continues with a search for the next
+ match. If the value is not zero, the current replacement is not ac-
+ cepted. If the value is greater than zero, processing continues when
+ PCRE2_SUBSTITUTE_GLOBAL is set. Otherwise (the value is less than zero
+ or PCRE2_SUBSTITUTE_GLOBAL is not set), the rest of the input is copied
+ to the output and the call to pcre2_substitute() exits, returning the
+ number of matches so far.
+
+ Substitution case callouts
+
+ int pcre2_set_substitute_case_callout(pcre2_match_context *mcontext,
+ PCRE2_SIZE (*callout_function)(PCRE2_SPTR, PCRE2_SIZE,
+ PCRE2_UCHAR *, PCRE2_SIZE,
+ int, void *),
+ void *callout_data);
+
+ The pcre2_set_substitute_case_callout() function can be used to specify
+ a callout function for pcre2_substitute() to use when performing case
+ transformations. This does not affect any case insensitivity behaviour
+ when performing a match, but only the user-visible transformations per-
+ formed when processing a substitution such as:
+
+ pcre2_substitute(..., "\\U$1", ...)
+
+ The default case transformations applied by PCRE2 are reasonably com-
+ plete, and, in UTF or UCP mode, perform the simple locale-invariant
+ case transformations as specified by Unicode. This is suitable for the
+ internal (invisible) case-equivalence procedures used during pattern
+ matching, but an application may wish to use more sophisticated locale-
+ aware processing for the user-visible substitution transformations.
+
+ One example implementation of the callout_function using the ICU li-
+ brary would be:
+
+ PCRE2_SIZE
+ icu_case_callout(
+ PCRE2_SPTR input, PCRE2_SIZE input_len,
+ PCRE2_UCHAR *output, PCRE2_SIZE output_cap,
+ int to_case, void *data_ptr)
+ {
+ UErrorCode err = U_ZERO_ERROR;
+ int32_t r = to_case == PCRE2_SUBSTITUTE_CASE_LOWER
+ ? u_strToLower(output, output_cap, input, input_len, NULL, &err)
+ : to_case == PCRE2_SUBSTITUTE_CASE_UPPER
+ ? u_strToUpper(output, output_cap, input, input_len, NULL, &err)
+ : u_strToTitle(output, output_cap, input, input_len, &first_char_only,
+ NULL, &err);
+ if (U_FAILURE(err)) return (~(PCRE2_SIZE)0);
+ return r;
+ }
+
+ The first and second arguments of the case callout function are the
+ Unicode string to transform.
+
+ The third and fourth arguments are the output buffer and its capacity.
+
+ The fifth is one of the constants PCRE2_SUBSTITUTE_CASE_LOWER,
+ PCRE2_SUBSTITUTE_CASE_UPPER, or PCRE2_SUBSTITUTE_CASE_TITLE_FIRST.
+ PCRE2_SUBSTITUTE_CASE_LOWER and PCRE2_SUBSTITUTE_CASE_UPPER are passed
+ to the callout to indicate that the case of the entire callout input
+ should be case-transformed. PCRE2_SUBSTITUTE_CASE_TITLE_FIRST is passed
+ to indicate that only the first character or glyph should be trans-
+ formed to Unicode titlecase and the rest to Unicode lowercase (note
+ that titlecasing sometimes uses Unicode properties to titlecase each
+ word in a string; but PCRE2 is requesting that only the single leading
+ character is to be titlecased).
+
+ The sixth argument is the callout_data supplied to pcre2_set_substi-
+ tute_case_callout().
+
+ The resulting string in the destination buffer may be larger or smaller
+ than the input, if the casing rules merge or split characters. The re-
+ turn value is the length required for the output string. If a buffer of
+ sufficient size was provided to the callout, then the result must be
+ written to the buffer and the number of code units returned. If the re-
+ sult does not fit in the provided buffer, then the required capacity
+ must be returned and PCRE2 will not make use of the output buffer.
+ PCRE2 provides input and output buffers which overlap, so the callout
+ must support this by suitable internal buffering.
+
+ Alternatively, if the callout wishes to indicate an error, then it may
+ return (~(PCRE2_SIZE)0). In this case pcre2_substitute() will immedi-
+ ately fail with error PCRE2_ERROR_REPLACECASE.
+
+ When a case callout is combined with the PCRE2_SUBSTITUTE_OVER-
+ FLOW_LENGTH option, there are situations when pcre2_substitute() will
+ return an underestimate of the required buffer size. If you call
+ pcre2_substitute() once with PCRE2_SUBSTITUTE_OVERFLOW_LENGTH, and the
+ input buffer is too small for the replacement string to be constructed,
+ then instead of calling the case callout, pcre2_substitute() will make
+ an estimate of the required buffer size. The second call should also
+ pass PCRE2_SUBSTITUTE_OVERFLOW_LENGTH, because that second call is not
+ guaranteed to succeed either, if the case callout requires more buffer
+ space than expected. The caller must make repeated attempts in a loop.
+
+
+DUPLICATE CAPTURE GROUP NAMES
+
+ int pcre2_substring_nametable_scan(const pcre2_code *code,
+ PCRE2_SPTR name, PCRE2_SPTR *first, PCRE2_SPTR *last);
+
+ When a pattern is compiled with the PCRE2_DUPNAMES option, names for
+ capture groups are not required to be unique. Duplicate names are al-
+ ways allowed for groups with the same number, created by using the (?|
+ feature. Indeed, if such groups are named, they are required to use the
+ same names.
+
+ Normally, patterns that use duplicate names are such that in any one
+ match, only one of each set of identically-named groups participates.
+ An example is shown in the pcre2pattern documentation.
+
+ When duplicates are present, pcre2_substring_copy_byname() and
+ pcre2_substring_get_byname() return the first substring corresponding
+ to the given name that is set. Only if none are set is PCRE2_ERROR_UN-
+ SET is returned. The pcre2_substring_number_from_name() function re-
+ turns the error PCRE2_ERROR_NOUNIQUESUBSTRING when there are duplicate
+ names.
+
+ If you want to get full details of all captured substrings for a given
+ name, you must use the pcre2_substring_nametable_scan() function. The
+ first argument is the compiled pattern, and the second is the name. If
+ the third and fourth arguments are NULL, the function returns a group
+ number for a unique name, or PCRE2_ERROR_NOUNIQUESUBSTRING otherwise.
+
+ When the third and fourth arguments are not NULL, they must be pointers
+ to variables that are updated by the function. After it has run, they
+ point to the first and last entries in the name-to-number table for the
+ given name, and the function returns the length of each entry in code
+ units. In both cases, PCRE2_ERROR_NOSUBSTRING is returned if there are
+ no entries for the given name.
+
+ The format of the name table is described above in the section entitled
+ Information about a pattern. Given all the relevant entries for the
+ name, you can extract each of their numbers, and hence the captured
+ data.
+
+
+FINDING ALL POSSIBLE MATCHES AT ONE POSITION
+
+ The traditional matching function uses a similar algorithm to Perl,
+ which stops when it finds the first match at a given point in the sub-
+ ject. If you want to find all possible matches, or the longest possible
+ match at a given position, consider using the alternative matching
+ function (see below) instead. If you cannot use the alternative func-
+ tion, you can kludge it up by making use of the callout facility, which
+ is described in the pcre2callout documentation.
+
+ What you have to do is to insert a callout right at the end of the pat-
+ tern. When your callout function is called, extract and save the cur-
+ rent matched substring. Then return 1, which forces pcre2_match() to
+ backtrack and try other alternatives. Ultimately, when it runs out of
+ matches, pcre2_match() will yield PCRE2_ERROR_NOMATCH.
+
+
+MATCHING A PATTERN: THE ALTERNATIVE FUNCTION
+
+ int pcre2_dfa_match(const pcre2_code *code, PCRE2_SPTR subject,
+ PCRE2_SIZE length, PCRE2_SIZE startoffset,
+ uint32_t options, pcre2_match_data *match_data,
+ pcre2_match_context *mcontext,
+ int *workspace, PCRE2_SIZE wscount);
+
+ The function pcre2_dfa_match() is called to match a subject string
+ against a compiled pattern, using a matching algorithm that scans the
+ subject string just once (not counting lookaround assertions), and does
+ not backtrack (except when processing lookaround assertions). This has
+ different characteristics to the normal algorithm, and is not compati-
+ ble with Perl. Some of the features of PCRE2 patterns are not sup-
+ ported. Nevertheless, there are times when this kind of matching can be
+ useful. For a discussion of the two matching algorithms, and a list of
+ features that pcre2_dfa_match() does not support, see the pcre2matching
+ documentation.
+
+ The arguments for the pcre2_dfa_match() function are the same as for
+ pcre2_match(), plus two extras. The ovector within the match data block
+ is used in a different way, and this is described below. The other com-
+ mon arguments are used in the same way as for pcre2_match(), so their
+ description is not repeated here.
+
+ The two additional arguments provide workspace for the function. The
+ workspace vector should contain at least 20 elements. It is used for
+ keeping track of multiple paths through the pattern tree. More work-
+ space is needed for patterns and subjects where there are a lot of po-
+ tential matches.
+
+ Here is an example of a simple call to pcre2_dfa_match():
+
+ int wspace[20];
+ pcre2_match_data *md = pcre2_match_data_create(4, NULL);
+ int rc = pcre2_dfa_match(
+ re, /* result of pcre2_compile() */
+ "some string", /* the subject string */
+ 11, /* the length of the subject string */
+ 0, /* start at offset 0 in the subject */
+ 0, /* default options */
+ md, /* the match data block */
+ NULL, /* a match context; NULL means use defaults */
+ wspace, /* working space vector */
+ 20); /* number of elements (NOT size in bytes) */
+
+ Option bits for pcre2_dfa_match()
+
+ The unused bits of the options argument for pcre2_dfa_match() must be
+ zero. The only bits that may be set are PCRE2_ANCHORED,
+ PCRE2_COPY_MATCHED_SUBJECT, PCRE2_ENDANCHORED, PCRE2_NOTBOL, PCRE2_NO-
+ TEOL, PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_UTF_CHECK,
+ PCRE2_PARTIAL_HARD, PCRE2_PARTIAL_SOFT, PCRE2_DFA_SHORTEST, and
+ PCRE2_DFA_RESTART. All but the last four of these are exactly the same
+ as for pcre2_match(), so their description is not repeated here.
+
+ PCRE2_PARTIAL_HARD
+ PCRE2_PARTIAL_SOFT
+
+ These have the same general effect as they do for pcre2_match(), but
+ the details are slightly different. When PCRE2_PARTIAL_HARD is set for
+ pcre2_dfa_match(), it returns PCRE2_ERROR_PARTIAL if the end of the
+ subject is reached and there is still at least one matching possibility
+ that requires additional characters. This happens even if some complete
+ matches have already been found. When PCRE2_PARTIAL_SOFT is set, the
+ return code PCRE2_ERROR_NOMATCH is converted into PCRE2_ERROR_PARTIAL
+ if the end of the subject is reached, there have been no complete
+ matches, but there is still at least one matching possibility. The por-
+ tion of the string that was inspected when the longest partial match
+ was found is set as the first matching string in both cases. There is a
+ more detailed discussion of partial and multi-segment matching, with
+ examples, in the pcre2partial documentation.
+
+ PCRE2_DFA_SHORTEST
+
+ Setting the PCRE2_DFA_SHORTEST option causes the matching algorithm to
+ stop as soon as it has found one match. Because of the way the alterna-
+ tive algorithm works, this is necessarily the shortest possible match
+ at the first possible matching point in the subject string.
+
+ PCRE2_DFA_RESTART
+
+ When pcre2_dfa_match() returns a partial match, it is possible to call
+ it again, with additional subject characters, and have it continue with
+ the same match. The PCRE2_DFA_RESTART option requests this action; when
+ it is set, the workspace and wscount options must reference the same
+ vector as before because data about the match so far is left in them
+ after a partial match. There is more discussion of this facility in the
+ pcre2partial documentation.
+
+ Successful returns from pcre2_dfa_match()
+
+ When pcre2_dfa_match() succeeds, it may have matched more than one sub-
+ string in the subject. Note, however, that all the matches from one run
+ of the function start at the same point in the subject. The shorter
+ matches are all initial substrings of the longer matches. For example,
+ if the pattern
+
+ <.*>
+
+ is matched against the string
+
+ This is no more
+
+ the three matched strings are
+
+
+
+
+
+ On success, the yield of the function is a number greater than zero,
+ which is the number of matched substrings. The offsets of the sub-
+ strings are returned in the ovector, and can be extracted by number in
+ the same way as for pcre2_match(), but the numbers bear no relation to
+ any capture groups that may exist in the pattern, because DFA matching
+ does not support capturing.
+
+ Calls to the convenience functions that extract substrings by name re-
+ turn the error PCRE2_ERROR_DFA_UFUNC (unsupported function) if used af-
+ ter a DFA match. The convenience functions that extract substrings by
+ number never return PCRE2_ERROR_NOSUBSTRING.
+
+ The matched strings are stored in the ovector in reverse order of
+ length; that is, the longest matching string is first. If there were
+ too many matches to fit into the ovector, the yield of the function is
+ zero, and the vector is filled with the longest matches.
+
+ NOTE: PCRE2's "auto-possessification" optimization usually applies to
+ character repeats at the end of a pattern (as well as internally). For
+ example, the pattern "a\d+" is compiled as if it were "a\d++". For DFA
+ matching, this means that only one possible match is found. If you re-
+ ally do want multiple matches in such cases, either use an ungreedy re-
+ peat such as "a\d+?" or set the PCRE2_NO_AUTO_POSSESS option when com-
+ piling.
+
+ Error returns from pcre2_dfa_match()
+
+ The pcre2_dfa_match() function returns a negative number when it fails.
+ Many of the errors are the same as for pcre2_match(), as described
+ above. There are in addition the following errors that are specific to
+ pcre2_dfa_match():
+
+ PCRE2_ERROR_DFA_UITEM
+
+ This return is given if pcre2_dfa_match() encounters an item in the
+ pattern that it does not support, for instance, the use of \C in a UTF
+ mode or a backreference.
+
+ PCRE2_ERROR_DFA_UCOND
+
+ This return is given if pcre2_dfa_match() encounters a condition item
+ that uses a backreference for the condition, or a test for recursion in
+ a specific capture group. These are not supported.
+
+ PCRE2_ERROR_DFA_UINVALID_UTF
+
+ This return is given if pcre2_dfa_match() is called for a pattern that
+ was compiled with PCRE2_MATCH_INVALID_UTF. This is not supported for
+ DFA matching.
+
+ PCRE2_ERROR_DFA_WSSIZE
+
+ This return is given if pcre2_dfa_match() runs out of space in the
+ workspace vector.
+
+ PCRE2_ERROR_DFA_RECURSE
+
+ When a recursion or subroutine call is processed, the matching function
+ calls itself recursively, using private memory for the ovector and
+ workspace. This error is given if the internal ovector is not large
+ enough. This should be extremely rare, as a vector of size 1000 is
+ used.
+
+ PCRE2_ERROR_DFA_BADRESTART
+
+ When pcre2_dfa_match() is called with the PCRE2_DFA_RESTART option,
+ some plausibility checks are made on the contents of the workspace,
+ which should contain data about the previous partial match. If any of
+ these checks fail, this error is given.
+
+
+SEE ALSO
+
+ pcre2build(3), pcre2callout(3), pcre2demo(3), pcre2matching(3),
+ pcre2partial(3), pcre2posix(3), pcre2sample(3), pcre2unicode(3).
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 08 December 2025
+ Copyright (c) 1997-2024 University of Cambridge.
+
+
+PCRE2 10.48 08 December 2025 PCRE2API(3)
+------------------------------------------------------------------------------
+
+
+PCRE2BUILD(3) Library Functions Manual PCRE2BUILD(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+
+BUILDING PCRE2
+
+ PCRE2 is distributed with a configure script that can be used to build
+ the library in Unix-like environments using the Autotools applications.
+ Also in the distribution are files to support building using CMake in-
+ stead of configure. The text file README contains general information
+ about building with Autotools (some of which is repeated below), and
+ also has some comments about building on various operating systems. The
+ files in the vms directory support building under OpenVMS. There is a
+ lot more information about building PCRE2 without using Autotools (in-
+ cluding information about using CMake and building "by hand") in the
+ text file called NON-AUTOTOOLS-BUILD. You should consult this file as
+ well as the README file if you are building in a non-Unix-like environ-
+ ment.
+
+
+PCRE2 BUILD-TIME OPTIONS
+
+ The rest of this document describes the optional features of PCRE2 that
+ can be selected when the library is compiled. It assumes use of the
+ configure script, where the optional features are selected or dese-
+ lected by providing options to configure before running the make com-
+ mand. However, the same options can be selected in both Unix-like and
+ non-Unix-like environments if you are using CMake instead of configure
+ to build PCRE2.
+
+ If you are not using Autotools or CMake, option selection can be done
+ by editing the config.h file, or by passing parameter settings to the
+ compiler, as described in NON-AUTOTOOLS-BUILD.
+
+ The complete list of options for configure (which includes the standard
+ ones such as the selection of the installation directory) can be ob-
+ tained by running
+
+ ./configure --help
+
+ The following sections include descriptions of "on/off" options whose
+ names begin with --enable or --disable. Because of the way that config-
+ ure works, --enable and --disable always come in pairs, so the comple-
+ mentary option always exists as well, but as it specifies the default,
+ it is not described. Options that specify values have names that start
+ with --with. At the end of a configure run, a summary of the configura-
+ tion is output.
+
+
+BUILDING 8-BIT, 16-BIT AND 32-BIT LIBRARIES
+
+ By default, a library called libpcre2-8 is built, containing functions
+ that take string arguments contained in arrays of bytes, interpreted
+ either as single-byte characters, or UTF-8 strings. You can also build
+ two other libraries, called libpcre2-16 and libpcre2-32, which process
+ strings that are contained in arrays of 16-bit and 32-bit code units,
+ respectively. These can be interpreted either as single-unit characters
+ or UTF-16/UTF-32 strings. To build these additional libraries, add one
+ or both of the following to the configure command:
+
+ --enable-pcre2-16
+ --enable-pcre2-32
+
+ If you do not want the 8-bit library, add
+
+ --disable-pcre2-8
+
+ as well. At least one of the three libraries must be built. Note that
+ the POSIX wrapper is for the 8-bit library only, and that pcre2grep is
+ an 8-bit program. Neither of these are built if you select only the
+ 16-bit or 32-bit libraries.
+
+
+BUILDING SHARED AND STATIC LIBRARIES
+
+ The Autotools PCRE2 building process uses libtool to build both shared
+ and static libraries by default. You can suppress an unwanted library
+ by adding one of
+
+ --disable-shared
+ --disable-static
+
+ to the configure command. Setting --disable-shared ensures that PCRE2
+ libraries are built as static libraries. The binaries that are then
+ created as part of the build process (for example, pcre2test and
+ pcre2grep) are linked statically with one or more PCRE2 libraries, but
+ may also be dynamically linked with other libraries such as libc. If
+ you want these binaries to be fully statically linked, you can set LD-
+ FLAGS like this:
+
+ LDFLAGS=--static ./configure --disable-shared
+
+ Note the two hyphens in --static. Of course, this works only if static
+ versions of all the relevant libraries are available for linking.
+
+
+UNICODE AND UTF SUPPORT
+
+ By default, PCRE2 is built with support for Unicode and UTF character
+ strings. To build it without Unicode support, add
+
+ --disable-unicode
+
+ to the configure command. This setting applies to all three libraries.
+ It is not possible to build one library with Unicode support and an-
+ other without in the same configuration.
+
+ Of itself, Unicode support does not make PCRE2 treat strings as UTF-8,
+ UTF-16 or UTF-32. To do that, applications that use the library can set
+ the PCRE2_UTF option when they call pcre2_compile() to compile a pat-
+ tern. Alternatively, patterns may be started with (*UTF) unless the
+ application has locked this out by setting PCRE2_NEVER_UTF.
+
+ UTF support allows the libraries to process character code points up to
+ 0x10ffff in the strings that they handle. Unicode support also gives
+ access to the Unicode properties of characters, using pattern escapes
+ such as \P, \p, and \X. Only the general category properties such as Lu
+ and Nd, script names, and some bi-directional and binary properties are
+ supported. Details are given in the pcre2pattern documentation.
+
+ Pattern escapes such as \d and \w do not by default make use of Unicode
+ properties. The application can request that they do by setting the
+ PCRE2_UCP option. Unless the application has set PCRE2_NEVER_UCP, a
+ pattern may also request this by starting with (*UCP).
+
+
+DISABLING THE USE OF \C
+
+ The \C escape sequence, which matches a single code unit, even in a UTF
+ mode, can cause unpredictable behaviour because it may leave the cur-
+ rent matching point in the middle of a multi-code-unit character. The
+ application can lock it out by setting the PCRE2_NEVER_BACKSLASH_C op-
+ tion when calling pcre2_compile(). There is also a build-time option
+
+ --enable-never-backslash-C
+
+ (note the upper case C) which locks out the use of \C entirely.
+
+
+JUST-IN-TIME COMPILER SUPPORT
+
+ Just-in-time (JIT) compiler support is included in the build by speci-
+ fying
+
+ --enable-jit
+
+ This support is available only for certain hardware architectures. If
+ this option is set for an unsupported architecture, a building error
+ occurs. If in doubt, use
+
+ --enable-jit=auto
+
+ which enables JIT only if the current hardware is supported. You can
+ check if JIT is enabled in the configuration summary that is output at
+ the end of a configure run. If you are enabling JIT under SELinux you
+ may also want to add
+
+ --enable-jit-sealloc
+
+ which enables the use of an execmem allocator in JIT that is compatible
+ with SELinux. This has no effect if JIT is not enabled. See the
+ pcre2jit documentation for a discussion of JIT usage. When JIT support
+ is enabled, pcre2grep automatically makes use of it, unless you add
+
+ --disable-pcre2grep-jit
+
+ to the configure command.
+
+
+NEWLINE RECOGNITION
+
+ By default, PCRE2 interprets the linefeed (LF) character as indicating
+ the end of a line. This is the normal newline character on Unix-like
+ systems. You can compile PCRE2 to use carriage return (CR) instead, by
+ adding
+
+ --enable-newline-is-cr
+
+ to the configure command. There is also an --enable-newline-is-lf op-
+ tion, which explicitly specifies linefeed as the newline character.
+
+ Alternatively, you can specify that line endings are to be indicated by
+ the two-character sequence CRLF (CR immediately followed by LF). If you
+ want this, add
+
+ --enable-newline-is-crlf
+
+ to the configure command. There is a fourth option, specified by
+
+ --enable-newline-is-anycrlf
+
+ which causes PCRE2 to recognize any of the three sequences CR, LF, or
+ CRLF as indicating a line ending. A fifth option, specified by
+
+ --enable-newline-is-any
+
+ causes PCRE2 to recognize any Unicode newline sequence. The Unicode
+ newline sequences are the three just mentioned, plus the single charac-
+ ters VT (vertical tab, U+000B), FF (form feed, U+000C), NEL (next line,
+ U+0085), LS (line separator, U+2028), and PS (paragraph separator,
+ U+2029). The final option is
+
+ --enable-newline-is-nul
+
+ which causes NUL (binary zero) to be set as the default line-ending
+ character.
+
+ Whatever default line ending convention is selected when PCRE2 is built
+ can be overridden by applications that use the library. At build time
+ it is recommended to use the standard for your operating system.
+
+
+WHAT \R MATCHES
+
+ By default, the sequence \R in a pattern matches any Unicode newline
+ sequence, independently of what has been selected as the line ending
+ sequence. If you specify
+
+ --enable-bsr-anycrlf
+
+ the default is changed so that \R matches only CR, LF, or CRLF. What-
+ ever is selected when PCRE2 is built can be overridden by applications
+ that use the library.
+
+
+HANDLING VERY LARGE PATTERNS
+
+ Within a compiled pattern, offset values are used to point from one
+ part to another (for example, from an opening parenthesis to an alter-
+ nation metacharacter). By default, in the 8-bit and 16-bit libraries,
+ two-byte values are used for these offsets, leading to a maximum size
+ for a compiled pattern of around 64 thousand code units. This is suffi-
+ cient to handle all but the most gigantic patterns. Nevertheless, some
+ people do want to process truly enormous patterns, so it is possible to
+ compile PCRE2 to use three-byte or four-byte offsets by adding a set-
+ ting such as
+
+ --with-link-size=3
+
+ to the configure command. The value given must be 2, 3, or 4. For the
+ 16-bit library, a value of 3 is rounded up to 4. In these libraries,
+ using longer offsets slows down the operation of PCRE2 because it has
+ to load additional data when handling them. For the 32-bit library the
+ value is always 4 and cannot be overridden; the value of --with-link-
+ size is ignored.
+
+
+LIMITING PCRE2 RESOURCE USAGE
+
+ The pcre2_match() function increments a counter each time it goes round
+ its main loop. Putting a limit on this counter controls the amount of
+ computing resource used by a single call to pcre2_match(). The limit
+ can be changed at run time, as described in the pcre2api documentation.
+ The default is 10 million, but this can be changed by adding a setting
+ such as
+
+ --with-match-limit=500000
+
+ to the configure command. This setting also applies to the
+ pcre2_dfa_match() matching function, and to JIT matching (though the
+ counting is done differently).
+
+ The pcre2_match() function uses heap memory to record backtracking
+ points. The more nested backtracking points there are (that is, the
+ deeper the search tree), the more memory is needed. There is an upper
+ limit, specified in kibibytes (units of 1024 bytes). This limit can be
+ changed at run time, as described in the pcre2api documentation. The
+ default limit (in effect unlimited) is 20 million. You can change this
+ by a setting such as
+
+ --with-heap-limit=500
+
+ which limits the amount of heap to 500 KiB. This limit applies only to
+ interpretive matching in pcre2_match() and pcre2_dfa_match(), which may
+ also use the heap for internal workspace when processing complicated
+ patterns. This limit does not apply when JIT (which has its own memory
+ arrangements) is used.
+
+ You can also explicitly limit the depth of nested backtracking in the
+ pcre2_match() interpreter. This limit defaults to the value that is set
+ for --with-match-limit. You can set a lower default limit by adding,
+ for example,
+
+ --with-match-limit-depth=10000
+
+ to the configure command. This value can be overridden at run time.
+ This depth limit indirectly limits the amount of heap memory that is
+ used, but because the size of each backtracking "frame" depends on the
+ number of capturing parentheses in a pattern, the amount of heap that
+ is used before the limit is reached varies from pattern to pattern.
+ This limit was more useful in versions before 10.30, where function re-
+ cursion was used for backtracking.
+
+ As well as applying to pcre2_match(), the depth limit also controls the
+ depth of recursive function calls in pcre2_dfa_match(). These are used
+ for lookaround assertions, atomic groups, and recursion within pat-
+ terns. The limit does not apply to JIT matching.
+
+
+LIMITING VARIABLE-LENGTH LOOKBEHIND ASSERTIONS
+
+ Lookbehind assertions in which one or more branches can match a vari-
+ able number of characters are supported only if there is a maximum
+ matching length for each top-level branch. There is a limit to this
+ maximum that defaults to 255 characters. You can alter this default by
+ a setting such as
+
+ --with-max-varlookbehind=100
+
+ The limit can be changed at runtime by calling pcre2_set_max_varlookbe-
+ hind(). Lookbehind assertions in which every branch matches a fixed
+ number of characters (not necessarily all the same) are not constrained
+ by this limit.
+
+
+CREATING CHARACTER TABLES AT BUILD TIME
+
+ PCRE2 uses fixed tables for processing characters whose code points are
+ less than 256. By default, PCRE2 is built with a set of tables that are
+ distributed in the file src/pcre2_chartables.c.dist. These tables are
+ for ASCII codes only. If you add
+
+ --enable-rebuild-chartables
+
+ to the configure command, the distributed tables are no longer used.
+ Instead, a program called pcre2_dftables is compiled and run. This out-
+ puts the source for new set of tables, created in the default locale of
+ your C run-time system. This method of replacing the tables does not
+ work if you are cross compiling, because pcre2_dftables needs to be run
+ on the local host and therefore not compiled with the cross compiler.
+
+ If you need to create alternative tables when cross compiling, you will
+ have to do so "by hand". There may also be other reasons for creating
+ tables manually. To cause pcre2_dftables to be built on the local
+ host, run a normal compiling command, and then run the program with the
+ output file as its argument, for example:
+
+ cc src/pcre2_dftables.c -o pcre2_dftables
+ ./pcre2_dftables src/pcre2_chartables.c
+
+ This builds the tables in the default locale of the local host. If you
+ want to specify a locale, you must use the -L option:
+
+ LC_ALL=fr_FR ./pcre2_dftables -L src/pcre2_chartables.c
+
+ You can also specify -b (with or without -L). This causes the tables to
+ be written in binary instead of as source code. A set of binary tables
+ can be loaded into memory by an application and passed to pcre2_com-
+ pile() in the same way as tables created by calling pcre2_maketables().
+ The tables are just a string of bytes, independent of hardware charac-
+ teristics such as endianness. This means they can be bundled with an
+ application that runs in different environments, to ensure consistent
+ behaviour.
+
+
+USING EBCDIC CODE
+
+ PCRE2 assumes by default that it will run in an environment where the
+ character code is ASCII or Unicode, which is a superset of ASCII. This
+ is the case for most computer operating systems. PCRE2 can, however, be
+ compiled to run in an 8-bit EBCDIC environment by adding
+
+ --enable-ebcdic --disable-unicode
+
+ to the configure command. You should only use it if you know that you
+ are in an EBCDIC environment (for example, an IBM mainframe operating
+ system).
+
+ This setting implies --enable-rebuild-chartables, in order to ensure
+ that you have the correct default character tables for your system's
+ codepage. There is an exception when you set --enable-ebcdic-ignoring-
+ compiler (see below), which allows using a default set of EBCDIC 1047
+ character tables rather than forcing use of --enable-rebuild-charta-
+ bles.
+
+ It is not supported to enable both EBCDIC input and either ASCII or
+ UTF-8/16/32 in the same build of the library. When PCRE2 is built with
+ EBCDIC support, it always operates in EBCDIC, and consequently --en-
+ able-unicode and --enable-ebcdic are mutually exclusive.
+
+ The EBCDIC character that corresponds to an ASCII LF is assumed to have
+ the value 0x15 by default. However, in some EBCDIC environments, 0x25
+ is used. In such an environment you should use
+
+ --enable-ebcdic-nl25
+
+ (which implies --enable-ebcdic). The EBCDIC character for CR has the
+ same value as in ASCII, namely, 0x0d. Whichever of 0x15 and 0x25 is not
+ chosen as LF is made to correspond to the Unicode NEL character (which,
+ in Unicode, is 0x85).
+
+ The options that select newline behaviour, such as --enable-newline-is-
+ cr, and equivalent run-time options, refer to these character values in
+ an EBCDIC environment.
+
+ On systems requiring an EBCDIC build of PCRE2, the compiler should be
+ set to use the correct codepage, so that C character literals such as
+ 'z' use the correct numeric value for whichever EBCDIC codpage is in
+ use. (PCRE2 cannot support multiple EBCDIC codepages dynamically.) How-
+ ever, if this not possible, then you can use
+
+ --enable-ebcdic-ignoring-compiler
+
+ in order to disregard the compiler's codepage, and instead force PCRE2
+ to use numeric constants corresponding to the EBCDIC 1047 codepage in-
+ stead. This can be used to build (or test) EBCDIC support on an
+ ASCII/UTF-8 system such as Linux.
+
+
+PCRE2GREP SUPPORT FOR EXTERNAL SCRIPTS
+
+ By default pcre2grep supports the use of callouts with string arguments
+ within the patterns it is matching. There are two kinds: one that gen-
+ erates output using local code, and another that calls an external pro-
+ gram or script. If --disable-pcre2grep-callout-fork is added to the
+ configure command, only the first kind of callout is supported; if
+ --disable-pcre2grep-callout is used, all callouts are completely ig-
+ nored. For more details of pcre2grep callouts, see the pcre2grep docu-
+ mentation.
+
+
+PCRE2GREP OPTIONS FOR COMPRESSED FILE SUPPORT
+
+ By default, pcre2grep reads all files as plain text. You can build it
+ so that it recognizes files whose names end in .gz or .bz2, and reads
+ them with libz or libbz2, respectively, by adding one or both of
+
+ --enable-pcre2grep-libz
+ --enable-pcre2grep-libbz2
+
+ to the configure command. These options naturally require that the rel-
+ evant libraries are installed on your system. Configuration will fail
+ if they are not.
+
+
+PCRE2GREP BUFFER SIZE
+
+ pcre2grep uses an internal buffer to hold a "window" on the file it is
+ scanning, in order to be able to output "before" and "after" lines when
+ it finds a match. The default starting size of the buffer is 20KiB. The
+ buffer itself is three times this size, but because of the way it is
+ used for holding "before" lines, the longest line that is guaranteed to
+ be processable is the notional buffer size. If a longer line is encoun-
+ tered, pcre2grep automatically expands the buffer, up to a specified
+ maximum size, whose default is 1MiB or the starting size, whichever is
+ the larger. You can change the default parameter values by adding, for
+ example,
+
+ --with-pcre2grep-bufsize=51200
+ --with-pcre2grep-max-bufsize=2097152
+
+ to the configure command. The caller of pcre2grep can override these
+ values by using --buffer-size and --max-buffer-size on the command
+ line.
+
+
+PCRE2TEST OPTION FOR LIBREADLINE SUPPORT
+
+ If you add one of
+
+ --enable-pcre2test-libreadline
+ --enable-pcre2test-libedit
+
+ to the configure command, pcre2test is linked with the libreadline or-
+ libedit library, respectively, and when its input is from a terminal,
+ it reads it using the readline() function. This provides line-editing
+ and history facilities. Note that libreadline is GPL-licensed, so if
+ you distribute a binary of pcre2test linked in this way, there may be
+ licensing issues. These can be avoided by linking instead with libedit,
+ which has a BSD licence.
+
+ Setting --enable-pcre2test-libreadline causes the -lreadline option to
+ be added to the pcre2test build. In many operating environments with a
+ system-installed readline library this is sufficient. However, in some
+ environments (e.g. if an unmodified distribution version of readline is
+ in use), some extra configuration may be necessary. The INSTALL file
+ for libreadline says this:
+
+ "Readline uses the termcap functions, but does not link with
+ the termcap or curses library itself, allowing applications
+ which link with readline the to choose an appropriate library."
+
+ If your environment has not been set up so that an appropriate library
+ is automatically included, you may need to add something like
+
+ LIBS="-lncurses"
+
+ immediately before the configure command.
+
+
+INCLUDING DEBUGGING CODE
+
+ If you add
+
+ --enable-debug
+
+ to the configure command, additional debugging code is included in the
+ build. This feature is intended for use by the PCRE2 maintainers.
+
+
+DEBUGGING WITH VALGRIND SUPPORT
+
+ If you add
+
+ --enable-valgrind
+
+ to the configure command, PCRE2 will use valgrind annotations to mark
+ certain memory regions as unaddressable. This allows it to detect in-
+ valid memory accesses, and is mostly useful for debugging PCRE2 itself.
+
+
+CODE COVERAGE REPORTING
+
+ If your C compiler is gcc, you can build a version of PCRE2 that can
+ generate a code coverage report for its test suite. To enable this, you
+ must install lcov version 1.6 or above. Then specify
+
+ --enable-coverage
+
+ to the configure command and build PCRE2 in the usual way.
+
+ Note that using ccache (a caching C compiler) is incompatible with code
+ coverage reporting. If you have configured ccache to run automatically
+ on your system, you must set the environment variable
+
+ CCACHE_DISABLE=1
+
+ before running make to build PCRE2, so that ccache is not used.
+
+ When --enable-coverage is used, the following addition targets are
+ added to the Makefile:
+
+ make coverage
+
+ This creates a fresh coverage report for the PCRE2 test suite. It is
+ equivalent to running "make coverage-reset", "make coverage-baseline",
+ "make check", and then "make coverage-report".
+
+ make coverage-reset
+
+ This zeroes the coverage counters, but does nothing else.
+
+ make coverage-baseline
+
+ This captures baseline coverage information.
+
+ make coverage-report
+
+ This creates the coverage report.
+
+ make coverage-clean-report
+
+ This removes the generated coverage report without cleaning the cover-
+ age data itself.
+
+ make coverage-clean-data
+
+ This removes the captured coverage data without removing the coverage
+ files created at compile time (*.gcno).
+
+ make coverage-clean
+
+ This cleans all coverage data including the generated coverage report.
+ For more information about code coverage, see the gcov and lcov docu-
+ mentation.
+
+
+DISABLING THE Z AND T FORMATTING MODIFIERS
+
+ The C99 standard defines formatting modifiers z and t for size_t and
+ ptrdiff_t values, respectively. By default, PCRE2 uses these modifiers
+ in environments other than old versions of Microsoft Visual Studio when
+ __STDC_VERSION__ is defined and has a value greater than or equal to
+ 199901L (indicating support for C99). However, there is at least one
+ environment that claims to be C99 but does not support these modifiers.
+ If
+
+ --disable-percent-zt
+
+ is specified, no use is made of the z or t modifiers. Instead of %td or
+ %zu, a suitable format is used depending in the size of long for the
+ platform.
+
+
+SUPPORT FOR FUZZERS
+
+ There is a special option for use by people who want to run fuzzing
+ tests on PCRE2:
+
+ --enable-fuzz-support
+
+ At present this applies only to the 8-bit library. If set, it causes an
+ extra library called libpcre2-fuzzsupport.a to be built, but not in-
+ stalled. This contains a single function called LLVMFuzzerTestOneIn-
+ put() whose arguments are a pointer to a string and the length of the
+ string. When called, this function tries to compile the string as a
+ pattern, and if that succeeds, to match it. This is done both with no
+ options and with some random options bits that are generated from the
+ string.
+
+ Setting --enable-fuzz-support also causes a binary called pcre2fuz-
+ zcheck to be created. This is normally run under valgrind or used when
+ PCRE2 is compiled with address sanitizing enabled. It calls the fuzzing
+ function and outputs information about what it is doing. The input
+ strings are specified by arguments: if an argument starts with "=" the
+ rest of it is a literal input string. Otherwise, it is assumed to be a
+ file name, and the contents of the file are the test string.
+
+
+OBSOLETE OPTION
+
+ In versions of PCRE2 prior to 10.30, there were two ways of handling
+ backtracking in the pcre2_match() function. The default was to use the
+ system stack, but if
+
+ --disable-stack-for-recursion
+
+ was set, memory on the heap was used. From release 10.30 onwards this
+ has changed (the stack is no longer used) and this option now does
+ nothing except give a warning.
+
+
+SEE ALSO
+
+ pcre2api(3), pcre2-config(3).
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 17 October 2025
+ Copyright (c) 1997-2024 University of Cambridge.
+
+
+PCRE2 10.48 17 October 2025 PCRE2BUILD(3)
+------------------------------------------------------------------------------
+
+
+PCRE2CALLOUT(3) Library Functions Manual PCRE2CALLOUT(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+
+SYNOPSIS
+
+ #include
+
+ int (*pcre2_callout)(pcre2_callout_block *, void *);
+
+ int pcre2_callout_enumerate(const pcre2_code *code,
+ int (*callback)(pcre2_callout_enumerate_block *, void *),
+ void *user_data);
+
+
+DESCRIPTION
+
+ PCRE2 provides a feature called "callout", which is a means of tem-
+ porarily passing control to the caller of PCRE2 in the middle of pat-
+ tern matching. The caller of PCRE2 provides an external function by
+ putting its entry point in a match context (see pcre2_set_callout() in
+ the pcre2api documentation).
+
+ When using the pcre2_substitute() function, an additional callout fea-
+ ture is available. This does a callout after each change to the subject
+ string and is described in the pcre2api documentation; the rest of this
+ document is concerned with callouts during pattern matching.
+
+ Within a regular expression, (?C) indicates a point at which the
+ external function is to be called. Different callout points can be
+ identified by putting a number less than 256 after the letter C. The
+ default value is zero. Alternatively, the argument may be a delimited
+ string. The starting delimiter must be one of ` ' " ^ % # $ { and the
+ ending delimiter is the same as the start, except for {, where the end-
+ ing delimiter is }. If the ending delimiter is needed within the
+ string, it must be doubled. For example, this pattern has two callout
+ points:
+
+ (?C1)abc(?C"some ""arbitrary"" text")def
+
+ If the PCRE2_AUTO_CALLOUT option bit is set when a pattern is compiled,
+ PCRE2 automatically inserts callouts, all with number 255, before each
+ item in the pattern except for immediately before or after an explicit
+ callout. For example, if PCRE2_AUTO_CALLOUT is used with the pattern
+
+ A(?C3)B
+
+ it is processed as if it were
+
+ (?C255)A(?C3)B(?C255)
+
+ Here is a more complicated example:
+
+ A(\d{2}|--)
+
+ With PCRE2_AUTO_CALLOUT, this pattern is processed as if it were
+
+ (?C255)A(?C255)((?C255)\d{2}(?C255)|(?C255)-(?C255)-(?C255))(?C255)
+
+ Notice that there is a callout before and after each parenthesis and
+ alternation bar. If the pattern contains a conditional group whose con-
+ dition is an assertion, an automatic callout is inserted immediately
+ before the condition. Such a callout may also be inserted explicitly,
+ for example:
+
+ (?(?C9)(?=a)ab|de) (?(?C%text%)(?!=d)ab|de)
+
+ This applies only to assertion conditions (because they are themselves
+ independent groups).
+
+ Callouts can be useful for tracking the progress of pattern matching.
+ The pcre2test program has a pattern qualifier (/auto_callout) that sets
+ automatic callouts. When any callouts are present, the output from
+ pcre2test indicates how the pattern is being matched. This is useful
+ information when you are trying to optimize the performance of a par-
+ ticular pattern.
+
+
+MISSING CALLOUTS
+
+ You should be aware that, because of optimizations in the way PCRE2
+ compiles and matches patterns, callouts sometimes do not happen exactly
+ as you might expect.
+
+ Auto-possessification
+
+ At compile time, PCRE2 "auto-possessifies" repeated items when it knows
+ that what follows cannot be part of the repeat. For example, a+[bc] is
+ compiled as if it were a++[bc]. The pcre2test output when this pattern
+ is compiled with PCRE2_ANCHORED and PCRE2_AUTO_CALLOUT and then applied
+ to the string "aaaa" is:
+
+ --->aaaa
+ +0 ^ a+
+ +2 ^ ^ [bc]
+ No match
+
+ This indicates that when matching [bc] fails, there is no backtracking
+ into a+ (because it is being treated as a++) and therefore the callouts
+ that would be taken for the backtracks do not occur. You can disable
+ the auto-possessify feature by passing PCRE2_NO_AUTO_POSSESS to
+ pcre2_compile(), or starting the pattern with (*NO_AUTO_POSSESS). In
+ this case, the output changes to this:
+
+ --->aaaa
+ +0 ^ a+
+ +2 ^ ^ [bc]
+ +2 ^ ^ [bc]
+ +2 ^ ^ [bc]
+ +2 ^^ [bc]
+ No match
+
+ This time, when matching [bc] fails, the matcher backtracks into a+ and
+ tries again, repeatedly, until a+ itself fails.
+
+ Automatic .* anchoring
+
+ By default, an optimization is applied when .* is the first significant
+ item in a pattern. If PCRE2_DOTALL is set, so that the dot can match
+ any character, the pattern is automatically anchored. If PCRE2_DOTALL
+ is not set, a match can start only after an internal newline or at the
+ beginning of the subject, and pcre2_compile() remembers this. If a pat-
+ tern has more than one top-level branch, automatic anchoring occurs if
+ all branches are anchorable.
+
+ This optimization is disabled, however, if .* is in an atomic group or
+ if there is a backreference to the capture group in which it appears.
+ It is also disabled if the pattern contains (*PRUNE) or (*SKIP). How-
+ ever, the presence of callouts does not affect it.
+
+ For example, if the pattern .*\d is compiled with PCRE2_AUTO_CALLOUT
+ and applied to the string "aa", the pcre2test output is:
+
+ --->aa
+ +0 ^ .*
+ +2 ^ ^ \d
+ +2 ^^ \d
+ +2 ^ \d
+ No match
+
+ This shows that all match attempts start at the beginning of the sub-
+ ject. In other words, the pattern is anchored. You can disable this op-
+ timization by passing PCRE2_NO_DOTSTAR_ANCHOR to pcre2_compile(), or
+ starting the pattern with (*NO_DOTSTAR_ANCHOR). In this case, the out-
+ put changes to:
+
+ --->aa
+ +0 ^ .*
+ +2 ^ ^ \d
+ +2 ^^ \d
+ +2 ^ \d
+ +0 ^ .*
+ +2 ^^ \d
+ +2 ^ \d
+ No match
+
+ This shows more match attempts, starting at the second subject charac-
+ ter. Another optimization, described in the next section, means that
+ there is no subsequent attempt to match with an empty subject.
+
+ Other optimizations
+
+ Other optimizations that provide fast "no match" results also affect
+ callouts. For example, if the pattern is
+
+ ab(?C4)cd
+
+ PCRE2 knows that any matching string must contain the letter "d". If
+ the subject string is "abyz", the lack of "d" means that matching
+ doesn't ever start, and the callout is never reached. However, with
+ "abyd", though the result is still no match, the callout is obeyed.
+
+ For most patterns PCRE2 also knows the minimum length of a matching
+ string, and will immediately give a "no match" return without actually
+ running a match if the subject is not long enough, or, for unanchored
+ patterns, if it has been scanned far enough.
+
+ You can disable these optimizations by passing the PCRE2_NO_START_OPTI-
+ MIZE option to pcre2_compile(), or by starting the pattern with
+ (*NO_START_OPT). This slows down the matching process, but does ensure
+ that callouts such as the example above are obeyed.
+
+
+THE CALLOUT INTERFACE
+
+ During matching, when PCRE2 reaches a callout point, if an external
+ function is provided in the match context, it is called. This applies
+ to both normal, DFA, and JIT matching. The first argument to the call-
+ out function is a pointer to a pcre2_callout block. The second argument
+ is the void * callout data that was supplied when the callout was set
+ up by calling pcre2_set_callout() (see the pcre2api documentation). The
+ callout block structure contains the following fields, not necessarily
+ in this order:
+
+ uint32_t version;
+ uint32_t callout_number;
+ uint32_t capture_top;
+ uint32_t capture_last;
+ uint32_t callout_flags;
+ PCRE2_SIZE *offset_vector;
+ PCRE2_SPTR mark;
+ PCRE2_SPTR subject;
+ PCRE2_SIZE subject_length;
+ PCRE2_SIZE start_match;
+ PCRE2_SIZE current_position;
+ PCRE2_SIZE pattern_position;
+ PCRE2_SIZE next_item_length;
+ PCRE2_SIZE callout_string_offset;
+ PCRE2_SIZE callout_string_length;
+ PCRE2_SPTR callout_string;
+
+ The version field contains the version number of the block format. The
+ current version is 2; the three callout string fields were added for
+ version 1, and the callout_flags field for version 2. If you are writ-
+ ing an application that might use an earlier release of PCRE2, you
+ should check the version number before accessing any of these fields.
+ The version number will increase in future if more fields are added,
+ but the intention is never to remove any of the existing fields.
+
+ Fields for numerical callouts
+
+ For a numerical callout, callout_string is NULL, and callout_number
+ contains the number of the callout, in the range 0-255. This is the
+ number that follows (?C for callouts that part of the pattern; it is
+ 255 for automatically generated callouts.
+
+ Fields for string callouts
+
+ For callouts with string arguments, callout_number is always zero, and
+ callout_string points to the string that is contained within the com-
+ piled pattern. Its length is given by callout_string_length. Duplicated
+ ending delimiters that were present in the original pattern string have
+ been turned into single characters, but there is no other processing of
+ the callout string argument. An additional code unit containing binary
+ zero is present after the string, but is not included in the length.
+ The delimiter that was used to start the string is also stored within
+ the pattern, immediately before the string itself. You can access this
+ delimiter as callout_string[-1] if you need it.
+
+ The callout_string_offset field is the code unit offset to the start of
+ the callout argument string within the original pattern string. This is
+ provided for the benefit of applications such as script languages that
+ might need to report errors in the callout string within the pattern.
+
+ Fields for all callouts
+
+ The remaining fields in the callout block are the same for both kinds
+ of callout.
+
+ The offset_vector field is a pointer to a vector of capturing offsets
+ (the "ovector"). You may read the elements in this vector, but you must
+ not change any of them.
+
+ For calls to pcre2_match(), the offset_vector field is not (since re-
+ lease 10.30) a pointer to the actual ovector that was passed to the
+ matching function in the match data block. Instead it points to an in-
+ ternal ovector of a size large enough to hold all possible captured
+ substrings in the pattern. Note that whenever a recursion or subroutine
+ call within a pattern completes, the capturing state is reset to what
+ it was before.
+
+ The capture_last field contains the number of the most recently cap-
+ tured substring, and the capture_top field contains one more than the
+ number of the highest numbered captured substring so far. If no sub-
+ strings have yet been captured, the value of capture_last is 0 and the
+ value of capture_top is 1. The values of these fields do not always
+ differ by one; for example, when the callout in the pattern
+ ((a)(b))(?C2) is taken, capture_last is 1 but capture_top is 4.
+
+ The contents of ovector[2] to ovector[*2-1] can be in-
+ spected in order to extract substrings that have been matched so far,
+ in the same way as extracting substrings after a match has completed.
+ The values in ovector[0] and ovector[1] are always PCRE2_UNSET because
+ the match is by definition not complete. Substrings that have not been
+ captured but whose numbers are less than capture_top also have both of
+ their ovector slots set to PCRE2_UNSET.
+
+ For DFA matching, the offset_vector field points to the ovector that
+ was passed to the matching function in the match data block for call-
+ outs at the top level, but to an internal ovector during the processing
+ of pattern recursions, lookarounds, and atomic groups. However, these
+ ovectors hold no useful information because pcre2_dfa_match() does not
+ support substring capturing. The value of capture_top is always 1 and
+ the value of capture_last is always 0 for DFA matching.
+
+ The subject and subject_length fields contain copies of the values that
+ were passed to the matching function.
+
+ The start_match field normally contains the offset within the subject
+ at which the current match attempt started. However, if the escape se-
+ quence \K has been encountered, this value is changed to reflect the
+ modified starting point. If the pattern is not anchored, the callout
+ function may be called several times from the same point in the pattern
+ for different starting points in the subject.
+
+ The current_position field contains the offset within the subject of
+ the current match pointer.
+
+ The pattern_position field contains the offset in the pattern string to
+ the next item to be matched.
+
+ The next_item_length field contains the length of the next item to be
+ processed in the pattern string. When the callout is at the end of the
+ pattern, the length is zero. When the callout precedes an opening
+ parenthesis, the length includes meta characters that follow the paren-
+ thesis. For example, in a callout before an assertion such as (?=ab)
+ the length is 3. For an alternation bar or a closing parenthesis, the
+ length is one, unless a closing parenthesis is followed by a quanti-
+ fier, in which case its length is included. (This changed in release
+ 10.23. In earlier releases, before an opening parenthesis the length
+ was that of the entire group, and before an alternation bar or a clos-
+ ing parenthesis the length was zero.)
+
+ The pattern_position and next_item_length fields are intended to help
+ in distinguishing between different automatic callouts, which all have
+ the same callout number. However, they are set for all callouts, and
+ are used by pcre2test to show the next item to be matched when display-
+ ing callout information.
+
+ In callouts from pcre2_match() the mark field contains a pointer to the
+ zero-terminated name of the most recently passed (*MARK), (*PRUNE), or
+ (*THEN) item in the match, or NULL if no such items have been passed.
+ Instances of (*PRUNE) or (*THEN) without a name do not obliterate a
+ previous (*MARK). In callouts from the DFA matching function this field
+ always contains NULL.
+
+ The callout_flags field is always zero in callouts from
+ pcre2_dfa_match() or when JIT is being used. When pcre2_match() without
+ JIT is used, the following bits may be set:
+
+ PCRE2_CALLOUT_STARTMATCH
+
+ This is set for the first callout after the start of matching for each
+ new starting position in the subject.
+
+ PCRE2_CALLOUT_BACKTRACK
+
+ This is set if there has been a matching backtrack since the previous
+ callout, or since the start of matching if this is the first callout
+ from a pcre2_match() run.
+
+ Both bits are set when a backtrack has caused a "bumpalong" to a new
+ starting position in the subject. Output from pcre2test does not indi-
+ cate the presence of these bits unless the callout_extra modifier is
+ set.
+
+ The information in the callout_flags field is provided so that applica-
+ tions can track and tell their users how matching with backtracking is
+ done. This can be useful when trying to optimize patterns, or just to
+ understand how PCRE2 works. There is no support in pcre2_dfa_match()
+ because there is no backtracking in DFA matching, and there is no sup-
+ port in JIT because JIT is all about maximimizing matching performance.
+ In both these cases the callout_flags field is always zero.
+
+
+RETURN VALUES FROM CALLOUTS
+
+ The external callout function returns an integer to PCRE2. If the value
+ is zero, matching proceeds as normal. If the value is greater than
+ zero, matching fails at the current point, but the testing of other
+ matching possibilities goes ahead, just as if a lookahead assertion had
+ failed. If the value is less than zero, the match is abandoned, and the
+ matching function returns the negative value.
+
+ Negative values should normally be chosen from the set of PCRE2_ER-
+ ROR_xxx values. In particular, PCRE2_ERROR_NOMATCH forces a standard
+ "no match" failure. The error number PCRE2_ERROR_CALLOUT is reserved
+ for use by callout functions; it will never be used by PCRE2 itself.
+
+
+CALLOUT ENUMERATION
+
+ int pcre2_callout_enumerate(const pcre2_code *code,
+ int (*callback)(pcre2_callout_enumerate_block *, void *),
+ void *user_data);
+
+ A script language that supports the use of string arguments in callouts
+ might like to scan all the callouts in a pattern before running the
+ match. This can be done by calling pcre2_callout_enumerate(). The first
+ argument is a pointer to a compiled pattern, the second points to a
+ callback function, and the third is arbitrary user data. The callback
+ function is called for every callout in the pattern in the order in
+ which they appear. Its first argument is a pointer to a callout enumer-
+ ation block, and its second argument is the user_data value that was
+ passed to pcre2_callout_enumerate(). The data block contains the fol-
+ lowing fields:
+
+ version Block version number
+ pattern_position Offset to next item in pattern
+ next_item_length Length of next item in pattern
+ callout_number Number for numbered callouts
+ callout_string_offset Offset to string within pattern
+ callout_string_length Length of callout string
+ callout_string Points to callout string or is NULL
+
+ The version number is currently 0. It will increase if new fields are
+ ever added to the block. The remaining fields are the same as their
+ namesakes in the pcre2_callout block that is used for callouts during
+ matching, as described above.
+
+ Note that the value of pattern_position is unique for each callout.
+ However, if a callout occurs inside a group that is quantified with a
+ non-zero minimum or a fixed maximum, the group is replicated inside the
+ compiled pattern. For example, a pattern such as /(a){2}/ is compiled
+ as if it were /(a)(a)/. This means that the callout will be enumerated
+ more than once, but with the same value for pattern_position in each
+ case.
+
+ The callback function should normally return zero. If it returns a non-
+ zero value, scanning the pattern stops, and that value is returned from
+ pcre2_callout_enumerate().
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 26 February 2025
+ Copyright (c) 1997-2024 University of Cambridge.
+
+
+PCRE2 10.48 26 February 2025 PCRE2CALLOUT(3)
+------------------------------------------------------------------------------
+
+
+PCRE2COMPAT(3) Library Functions Manual PCRE2COMPAT(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+
+DIFFERENCES BETWEEN PCRE2 AND PERL
+
+ This document describes some of the known differences in the ways that
+ PCRE2 and Perl handle regular expressions. The differences described
+ here are with respect to Perl version 5.38.0, but as both Perl and
+ PCRE2 are continually changing, the information may at times be out of
+ date.
+
+ 1. When PCRE2_DOTALL (equivalent to Perl's /s qualifier) is not set,
+ the behaviour of the '.' metacharacter differs from Perl. In PCRE2, '.'
+ matches the next character unless it is the start of a newline se-
+ quence. This means that, if the newline setting is CR, CRLF, or NUL,
+ '.' will match the code point LF (0x0A) in ASCII/Unicode environments,
+ and NL (either 0x15 or 0x25) when using EBCDIC. In Perl, '.' appears
+ never to match LF, even when 0x0A is not a newline indicator.
+
+ 2. PCRE2 has only a subset of Perl's Unicode support. Details of what
+ it does have are given in the pcre2unicode page.
+
+ 3. Like Perl, PCRE2 allows repeat quantifiers on parenthesized asser-
+ tions, but they do not mean what you might think. For example, (?!a){3}
+ does not assert that the next three characters are not "a". It just as-
+ serts that the next character is not "a" three times (in principle;
+ PCRE2 optimizes this to run the assertion just once). Perl allows some
+ repeat quantifiers on other assertions, for example, \b* , but these do
+ not seem to have any use. PCRE2 does not allow any kind of quantifier
+ on non-lookaround assertions.
+
+ 4. If a braced quantifier such as {1,2} appears where there is nothing
+ to repeat (for example, at the start of a branch), PCRE2 raises an er-
+ ror whereas Perl treats the quantifier characters as literal. When a
+ braced quantifier (...){min,max} has min > max, Perl treats it as an
+ item which fails to match any portion of the subject (as no number of
+ repetitions can meet the condition), and additionally issues a warning
+ when in warning mode. PCRE2 has no warning features, so it gives an er-
+ ror in this case.
+
+ 5. Capture groups that occur inside negative lookaround assertions are
+ counted, but their entries in the offsets vector are set only when a
+ negative assertion is a condition that has a matching branch (that is,
+ the condition is false). Perl may set such capture groups in other
+ circumstances.
+
+ 6. The following Perl escape sequences are not supported: \F, \l, \L,
+ \u, \U, and \N when followed by a character name. \N on its own, match-
+ ing a non-newline character, and \N{U+dd..}, matching a Unicode code
+ point, are supported. The escapes that modify the case of following
+ letters are implemented by Perl's general string-handling and are not
+ part of its pattern matching engine. If any of these are encountered by
+ PCRE2, an error is generated by default. However, if either of the
+ PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX options is set, \U and \u are
+ interpreted as ECMAScript interprets them.
+
+ 7. The Perl escape sequences \p, \P, and \X are supported only if PCRE2
+ is built with Unicode support (the default). The properties that can be
+ tested with \p and \P are limited to the general category properties
+ such as Lu and Nd, the derived properties Any and Lc (synonym L&),
+ script names such as Greek or Han, Bidi_Class, Bidi_Control, and a few
+ binary properties. Both PCRE2 and Perl support the Cs (surrogate) prop-
+ erty, but in PCRE2 its use is limited. See the pcre2pattern documenta-
+ tion for details. The long synonyms for property names that Perl sup-
+ ports (such as \p{Letter}) are not supported by PCRE2, nor is it per-
+ mitted to prefix any of these properties with "Is".
+
+ 8. PCRE2 supports the \Q...\E escape for quoting substrings. Characters
+ in between are treated as literals. However, this is slightly different
+ from Perl in that $ and @ are also handled as literals inside the
+ quotes. In Perl, they cause variable interpolation (PCRE2 does not have
+ variables). Also, Perl does "double-quotish backslash interpolation" on
+ any backslashes between \Q and \E which, its documentation says, "may
+ lead to confusing results". PCRE2 treats a backslash between \Q and \E
+ just like any other character. Note the following examples:
+
+ Pattern PCRE2 matches Perl matches
+
+ \Qabc$xyz\E abc$xyz abc followed by the
+ contents of $xyz
+ \Qabc\$xyz\E abc\$xyz abc\$xyz
+ \Qabc\E\$\Qxyz\E abc$xyz abc$xyz
+ \QA\B\E A\B A\B
+ \Q\\E \ \\E
+
+ The \Q...\E sequence is recognized both inside and outside character
+ classes by both PCRE2 and Perl. Another difference from Perl is that
+ any appearance of \Q or \E inside what might otherwise be a quantifier
+ causes PCRE2 not to recognize the sequence as a quantifier. Perl recog-
+ nizes a quantifier if (redundantly) either of the numbers is inside
+ \Q...\E, but not if the separating comma is. When not recognized as a
+ quantifier a sequence such as {\Q1\E,2} is treated as the literal
+ string "{1,2}".
+
+ 9. Fairly obviously, PCRE2 does not support the (?{code}) and
+ (??{code}) constructions. However, PCRE2 does have a "callout" feature,
+ which allows an external function to be called during pattern matching.
+ See the pcre2callout documentation for details.
+
+ 10. Subroutine calls (whether recursive or not) were treated as atomic
+ groups up to PCRE2 release 10.23, but from release 10.30 this changed,
+ and backtracking into subroutine calls is now supported, as in Perl.
+
+ 11. In PCRE2, if any of the backtracking control verbs are used in a
+ group that is called as a subroutine (whether or not recursively),
+ their effect is confined to that group; it does not extend to the sur-
+ rounding pattern. This is not always the case in Perl. In particular,
+ if (*THEN) is present in a group that is called as a subroutine, its
+ action is limited to that group, even if the group does not contain any
+ | characters. Note that such groups are processed as anchored at the
+ point where they are tested. PCRE2 also confines all control verbs
+ within atomic assertions, again including (*THEN) in assertions with
+ only one branch.
+
+ 12. If a pattern contains more than one backtracking control verb, the
+ first one that is backtracked onto acts. For example, in the pattern
+ A(*COMMIT)B(*PRUNE)C a failure in B triggers (*COMMIT), but a failure
+ in C triggers (*PRUNE). Perl's behaviour is more complex; in many cases
+ it is the same as PCRE2, but there are cases where it differs.
+
+ 13. There are some differences that are concerned with the settings of
+ captured strings when part of a pattern is repeated. For example,
+ matching "aba" against the pattern /^(a(b)?)+$/ in Perl leaves $2 un-
+ set, but in PCRE2 it is set to "b".
+
+ 14. PCRE2's handling of duplicate capture group numbers and names is
+ not as general as Perl's. This is a consequence of the fact the PCRE2
+ works internally just with numbers, using an external table to trans-
+ late between numbers and names. In particular, a pattern such as
+ (?|(?A)|(?B)), where the two capture groups have the same number
+ but different names, is not supported, and causes an error at compile
+ time. If it were allowed, it would not be possible to distinguish which
+ group matched, because both names map to capture group number 1. To
+ avoid this confusing situation, an error is given at compile time.
+
+ 15. Perl used to recognize comments in some places that PCRE2 does not,
+ for example, between the ( and ? at the start of a group. If the /x
+ modifier is set, Perl allowed white space between ( and ? though the
+ latest Perls give an error (for a while it was just deprecated). There
+ may still be some cases where Perl behaves differently.
+
+ 16. Perl, when in warning mode, gives warnings for character classes
+ such as [A-\d] or [a-[:digit:]]. It then treats the hyphens as liter-
+ als. PCRE2 has no warning features, so it gives an error in these cases
+ because they are almost certainly user mistakes.
+
+ 17. In PCRE2, until release 10.45, the upper/lower case character prop-
+ erties Lu and Ll were not affected when case-independent matching was
+ specified. Perl has changed in this respect, and PCRE2 has now changed
+ to match. When caseless matching is in force, Lu, Ll, and Lt (title
+ case) are all treated as Lc (cased letter).
+
+ 18. From release 5.32.0, Perl locks out the use of \K in lookaround as-
+ sertions. From release 10.38 PCRE2 does the same by default. However,
+ there is an option for re-enabling the previous behaviour. When this
+ option is set, \K is acted on when it occurs in positive assertions,
+ but is ignored in negative assertions.
+
+ 19. PCRE2 provides some extensions to the Perl regular expression fa-
+ cilities. Perl 5.10 included new features that were not in earlier
+ versions of Perl, some of which (such as named parentheses) were in
+ PCRE2 for some time before. This list is with respect to Perl 5.38:
+
+ (a) If PCRE2_DOLLAR_ENDONLY is set and PCRE2_MULTILINE is not set, the
+ $ meta-character matches only at the very end of the string.
+
+ (b) A backslash followed by a letter with no special meaning is
+ faulted. (Perl can be made to issue a warning.)
+
+ (c) If PCRE2_UNGREEDY is set, the greediness of the repetition quanti-
+ fiers is inverted, that is, by default they are not greedy, but if fol-
+ lowed by a question mark they are.
+
+ (d) PCRE2_ANCHORED can be used at matching time to force a pattern to
+ be tried only at the first matching position in the subject string.
+
+ (e) The PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY and
+ PCRE2_NOTEMPTY_ATSTART options have no Perl equivalents.
+
+ (f) The \R escape sequence can be restricted to match only CR, LF, or
+ CRLF by the PCRE2_BSR_ANYCRLF option.
+
+ (g) The callout facility is PCRE2-specific. Perl supports codeblocks
+ and variable interpolation, but not general hooks on every match.
+
+ (h) The partial matching facility is PCRE2-specific.
+
+ (i) The alternative matching function (pcre2_dfa_match()) matches in a
+ different way and is not Perl-compatible.
+
+ (j) PCRE2 recognizes some special sequences such as (*CR) or (*NO_JIT)
+ at the start of a pattern. These set overall options that cannot be
+ changed within the pattern.
+
+ (k) PCRE2 supports non-atomic positive lookaround assertions. This is
+ an extension to the lookaround facilities. The default, Perl-compatible
+ lookarounds are atomic.
+
+ (l) There are three syntactical items in patterns that can refer to a
+ capturing group by number: back references such as \g{2}, subroutine
+ calls such as (?3), and condition references such as (?(4)...). PCRE2
+ supports relative group numbers such as +2 and -4 in all three cases.
+ Perl supports both plus and minus for subroutine calls, but only minus
+ for back references, and no relative numbering at all for conditions.
+
+ (m) The scan substring assertion (syntax (*scs:(n)...)) is a PCRE2 ex-
+ tension that is not available in Perl.
+
+ 20. Perl has different limits than PCRE2. See the pcre2limits documen-
+ tation for details. Perl went with 5.10 from recursion to iteration
+ keeping the intermediate matches on the heap, which is ~10% slower but
+ does not fall into any stack-overflow limit. PCRE2 made a similar
+ change at release 10.30, and also has many build-time and run-time cus-
+ tomizable limits.
+
+ 21. Unlike Perl, PCRE2 doesn't have character set modifiers and spe-
+ cially no way to set characters by context just like Perl's "/d". A
+ regular expression using PCRE2_UTF and PCRE2_UCP will use similar rules
+ to Perl's "/u"; something closer to "/a" could be selected by adding
+ other PCRE2_EXTRA_ASCII* options on top.
+
+ 22. Some recursive patterns that Perl diagnoses as infinite recursions
+ can be handled by PCRE2, either by the interpreter or the JIT. An exam-
+ ple is /(?:|(?0)abcd)(?(R)|\z)/, which matches a sequence of any number
+ of repeated "abcd" substrings at the end of the subject.
+
+ 23. Both PCRE2 and Perl error when \x{ escapes are invalid, but Perl
+ tries to recover and prints a warning if the problem was that an in-
+ valid hexadecimal digit was found. Since PCRE2 doesn't have warnings it
+ returns an error instead. Additionally, Perl accepts \x{} and gener-
+ ates NUL unlike PCRE2.
+
+ 24. From release 10.45, PCRE2 gives an error if \x is not followed by a
+ hexadecimal digit or a curly bracket. It used to interpret this as the
+ NUL character. Perl still generates NUL, but warns when in warning mode
+ in most cases.
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 02 June 2025
+ Copyright (c) 1997-2024 University of Cambridge.
+
+
+PCRE2 10.48 02 June 2025 PCRE2COMPAT(3)
+------------------------------------------------------------------------------
+
+
+PCRE2JIT(3) Library Functions Manual PCRE2JIT(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+
+PCRE2 JUST-IN-TIME COMPILER SUPPORT
+
+ Just-in-time compiling is a heavyweight optimization that can greatly
+ speed up pattern matching. However, it comes at the cost of extra pro-
+ cessing before the match is performed, so it is of most benefit when
+ the same pattern is going to be matched many times. This does not nec-
+ essarily mean many calls of a matching function; if the pattern is not
+ anchored, matching attempts may take place many times at various posi-
+ tions in the subject, even for a single call. Therefore, if the subject
+ string is very long, it may still pay to use JIT even for one-off
+ matches. JIT support is available for all of the 8-bit, 16-bit and
+ 32-bit PCRE2 libraries.
+
+ JIT support applies only to the traditional Perl-compatible matching
+ function. It does not apply when the DFA matching function is being
+ used. The code for JIT support was written by Zoltan Herczeg.
+
+
+AVAILABILITY OF JIT SUPPORT
+
+ JIT support is an optional feature of PCRE2. The "configure" option
+ --enable-jit (or equivalent CMake option) must be set when PCRE2 is
+ built if you want to use JIT. The support is limited to the following
+ hardware platforms:
+
+ ARM 32-bit (v7, and Thumb2)
+ ARM 64-bit
+ IBM s390x 64 bit
+ Intel x86 32-bit and 64-bit
+ LoongArch 64 bit
+ MIPS 32-bit and 64-bit
+ Power PC 32-bit and 64-bit
+ RISC-V 32-bit and 64-bit
+
+ If --enable-jit is set on an unsupported platform, compilation fails.
+
+ A client program can tell if JIT support has been compiled by calling
+ pcre2_config() with the PCRE2_CONFIG_JIT option. The result is one if
+ PCRE2 was built with JIT support, and zero otherwise. However, having
+ the JIT code available does not guarantee that it will be used for any
+ particular match. One reason for this is that there are a number of op-
+ tions and pattern items that are not supported by JIT (see below). An-
+ other reason is that in some environments JIT is unable to get exe-
+ cutable memory in which to build its compiled code. The only guarantee
+ from pcre2_config() is that if it returns zero, JIT will definitely not
+ be used.
+
+ As of release 10.45 there is a more informative way to test for JIT
+ support. If pcre2_compile_jit() is called with the single option
+ PCRE2_JIT_TEST_ALLOC it returns zero if JIT is available and has a
+ working allocator. Otherwise it returns PCRE2_ERROR_NOMEMORY if JIT is
+ available but cannot allocate executable memory, or PCRE2_ERROR_JIT_UN-
+ SUPPORTED if JIT support is not compiled. The code argument is ignored,
+ so it can be a NULL value.
+
+ A simple program does not need to check availability in order to use
+ JIT when possible. The API is implemented in a way that falls back to
+ the interpretive code if JIT is not available or cannot be used for a
+ given match. For programs that need the best possible performance,
+ there is a "fast path" API that is JIT-specific.
+
+
+SIMPLE USE OF JIT
+
+ To make use of the JIT support in the simplest way, all you have to do
+ is to call pcre2_jit_compile() after successfully compiling a pattern
+ with pcre2_compile(). This function has two arguments: the first is the
+ compiled pattern pointer that was returned by pcre2_compile(), and the
+ second is zero or more of the following option bits: PCRE2_JIT_COM-
+ PLETE, PCRE2_JIT_PARTIAL_HARD, or PCRE2_JIT_PARTIAL_SOFT.
+
+ If JIT support is not available, a call to pcre2_jit_compile() does
+ nothing and returns PCRE2_ERROR_JIT_BADOPTION. Otherwise, the compiled
+ pattern is passed to the JIT compiler, which turns it into machine code
+ that executes much faster than the normal interpretive code, but yields
+ exactly the same results. The returned value from pcre2_jit_compile()
+ is zero on success, or a negative error code.
+
+ There is a limit to the size of pattern that JIT supports, imposed by
+ the size of machine stack that it uses. The exact rules are not docu-
+ mented because they may change at any time, in particular, when new op-
+ timizations are introduced. If a pattern is too big, a call to
+ pcre2_jit_compile() returns PCRE2_ERROR_NOMEMORY.
+
+ PCRE2_JIT_COMPLETE requests the JIT compiler to generate code for com-
+ plete matches. If you want to run partial matches using the PCRE2_PAR-
+ TIAL_HARD or PCRE2_PARTIAL_SOFT options of pcre2_match(), you should
+ set one or both of the other options as well as, or instead of
+ PCRE2_JIT_COMPLETE. The JIT compiler generates different optimized code
+ for each of the three modes (normal, soft partial, hard partial). When
+ pcre2_match() is called, the appropriate code is run if it is avail-
+ able. Otherwise, the pattern is matched using interpretive code.
+
+ You can call pcre2_jit_compile() multiple times for the same compiled
+ pattern. It does nothing if it has previously compiled code for any of
+ the option bits. For example, you can call it once with PCRE2_JIT_COM-
+ PLETE and (perhaps later, when you find you need partial matching)
+ again with PCRE2_JIT_COMPLETE and PCRE2_JIT_PARTIAL_HARD. This time it
+ will ignore PCRE2_JIT_COMPLETE and just compile code for partial match-
+ ing. If pcre2_jit_compile() is called with no option bits set, it imme-
+ diately returns zero. This is an alternative way of testing whether JIT
+ support has been compiled.
+
+ At present, it is not possible to free JIT compiled code except when
+ the entire compiled pattern is freed by calling pcre2_code_free().
+
+ In some circumstances you may need to call additional functions. These
+ are described in the section entitled "Controlling the JIT stack" be-
+ low.
+
+ There are some pcre2_match() options that are not supported by JIT, and
+ there are also some pattern items that JIT cannot handle. Details are
+ given below. In both cases, matching automatically falls back to the
+ interpretive code. If you want to know whether JIT was actually used
+ for a particular match, you should arrange for a JIT callback function
+ to be set up as described in the section entitled "Controlling the JIT
+ stack" below, even if you do not need to supply a non-default JIT
+ stack. Such a callback function is called whenever JIT code is about to
+ be obeyed. If the match-time options are not right for JIT execution,
+ the callback function is not obeyed.
+
+ If the JIT compiler finds an unsupported item, no JIT data is gener-
+ ated. You can find out if JIT compilation was successful for a compiled
+ pattern by calling pcre2_pattern_info() with the PCRE2_INFO_JITSIZE op-
+ tion. A non-zero result means that JIT compilation was successful. A
+ result of 0 means that JIT support is not available, or the pattern was
+ not processed by pcre2_jit_compile(), or the JIT compiler was not able
+ to handle the pattern. Successful JIT compilation does not, however,
+ guarantee the use of JIT at match time because there are some match
+ time options that are not supported by JIT.
+
+
+MATCHING SUBJECTS CONTAINING INVALID UTF
+
+ When a pattern is compiled with the PCRE2_UTF option, subject strings
+ are normally expected to be a valid sequence of UTF code units. By de-
+ fault, this is checked at the start of matching and an error is gener-
+ ated if invalid UTF is detected. The PCRE2_NO_UTF_CHECK option can be
+ passed to pcre2_match() to skip the check (for improved performance) if
+ you are sure that a subject string is valid. If this option is used
+ with an invalid string, the result is undefined. The calling program
+ may crash or loop or otherwise misbehave.
+
+ However, a way of running matches on strings that may contain invalid
+ UTF sequences is available. Calling pcre2_compile() with the
+ PCRE2_MATCH_INVALID_UTF option has two effects: it tells the inter-
+ preter in pcre2_match() to support invalid UTF, and, if pcre2_jit_com-
+ pile() is subsequently called, the compiled JIT code also supports in-
+ valid UTF. Details of how this support works, in both the JIT and the
+ interpretive cases, is given in the pcre2unicode documentation.
+
+ There is also an obsolete option for pcre2_jit_compile() called
+ PCRE2_JIT_INVALID_UTF, which currently exists only for backward compat-
+ ibility. It is superseded by the pcre2_compile() option
+ PCRE2_MATCH_INVALID_UTF and should no longer be used. It may be removed
+ in future.
+
+
+UNSUPPORTED OPTIONS AND PATTERN ITEMS
+
+ The pcre2_match() options that are supported for JIT matching are
+ PCRE2_COPY_MATCHED_SUBJECT, PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY,
+ PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and
+ PCRE2_PARTIAL_SOFT. The PCRE2_ANCHORED and PCRE2_ENDANCHORED options
+ are not supported at match time.
+
+ If the PCRE2_NO_JIT option is passed to pcre2_match() it disables the
+ use of JIT, forcing matching by the interpreter code.
+
+ The only unsupported pattern items are \C (match a single data unit)
+ when running in a UTF mode, and a callout immediately before an asser-
+ tion condition in a conditional group.
+
+
+RETURN VALUES FROM JIT MATCHING
+
+ When a pattern is matched using JIT, the return values are the same as
+ those given by the interpretive pcre2_match() code, with the addition
+ of one new error code: PCRE2_ERROR_JIT_STACKLIMIT. This means that the
+ memory used for the JIT stack was insufficient. See "Controlling the
+ JIT stack" below for a discussion of JIT stack usage.
+
+ The error code PCRE2_ERROR_MATCHLIMIT is returned by the JIT code if
+ searching a very large pattern tree goes on for too long, as it is in
+ the same circumstance when JIT is not used, but the details of exactly
+ what is counted are not the same. The PCRE2_ERROR_DEPTHLIMIT error code
+ is never returned when JIT matching is used.
+
+
+CONTROLLING THE JIT STACK
+
+ When the compiled JIT code runs, it needs a block of memory to use as a
+ stack. By default, it uses 32KiB on the machine stack. However, some
+ large or complicated patterns need more than this. The error PCRE2_ER-
+ ROR_JIT_STACKLIMIT is given when there is not enough stack. Three func-
+ tions are provided for managing blocks of memory for use as JIT stacks.
+ There is further discussion about the use of JIT stacks in the section
+ entitled "JIT stack FAQ" below.
+
+ The pcre2_jit_stack_create() function creates a JIT stack. Its argu-
+ ments are a starting size, a maximum size, and a general context (for
+ memory allocation functions, or NULL for standard memory allocation).
+ It returns a pointer to an opaque structure of type pcre2_jit_stack, or
+ NULL if there is an error. The pcre2_jit_stack_free() function is used
+ to free a stack that is no longer needed. If its argument is NULL, this
+ function returns immediately, without doing anything. (For the techni-
+ cally minded: the address space is allocated by mmap or VirtualAlloc.)
+ A maximum stack size of 512KiB to 1MiB should be more than enough for
+ any pattern.
+
+ The pcre2_jit_stack_assign() function specifies which stack JIT code
+ should use. Its arguments are as follows:
+
+ pcre2_match_context *mcontext
+ pcre2_jit_callback callback
+ void *data
+
+ The first argument is a pointer to a match context. When this is subse-
+ quently passed to a matching function, its information determines which
+ JIT stack is used. If this argument is NULL, the function returns imme-
+ diately, without doing anything. There are three cases for the values
+ of the other two options:
+
+ (1) If callback is NULL and data is NULL, an internal 32KiB block
+ on the machine stack is used. This is the default when a match
+ context is created.
+
+ (2) If callback is NULL and data is not NULL, data must be
+ a pointer to a valid JIT stack, the result of calling
+ pcre2_jit_stack_create().
+
+ (3) If callback is not NULL, it must point to a function that is
+ called with data as an argument at the start of matching, in
+ order to set up a JIT stack. If the return from the callback
+ function is NULL, the internal 32KiB stack is used; otherwise the
+ return value must be a valid JIT stack, the result of calling
+ pcre2_jit_stack_create().
+
+ A callback function is obeyed whenever JIT code is about to be run; it
+ is not obeyed when pcre2_match() is called with options that are incom-
+ patible for JIT matching. A callback function can therefore be used to
+ determine whether a match operation was executed by JIT or by the in-
+ terpreter.
+
+ You may safely use the same JIT stack for more than one pattern (either
+ by assigning directly or by callback), as long as the patterns are
+ matched sequentially in the same thread. Currently, the only way to set
+ up non-sequential matches in one thread is to use callouts: if a call-
+ out function starts another match, that match must use a different JIT
+ stack to the one used for currently suspended match(es).
+
+ In a multithread application, if you do not specify a JIT stack, or if
+ you assign or pass back NULL from a callback, that is thread-safe, be-
+ cause each thread has its own machine stack. However, if you assign or
+ pass back a non-NULL JIT stack, this must be a different stack for each
+ thread so that the application is thread-safe.
+
+ Strictly speaking, even more is allowed. You can assign the same non-
+ NULL stack to a match context that is used by any number of patterns,
+ as long as they are not used for matching by multiple threads at the
+ same time. For example, you could use the same stack in all compiled
+ patterns, with a global mutex in the callback to wait until the stack
+ is available for use. However, this is an inefficient solution, and not
+ recommended.
+
+ This is a suggestion for how a multithreaded program that needs to set
+ up non-default JIT stacks might operate:
+
+ During thread initialization
+ thread_local_var = pcre2_jit_stack_create(...)
+
+ During thread exit
+ pcre2_jit_stack_free(thread_local_var)
+
+ Use a one-line callback function
+ return thread_local_var
+
+ All the functions described in this section do nothing if JIT is not
+ available.
+
+
+JIT STACK FAQ
+
+ (1) Why do we need JIT stacks?
+
+ PCRE2 (and JIT) is a recursive, depth-first engine, so it needs a stack
+ where the local data of the current node is pushed before checking its
+ child nodes. Allocating real machine stack on some platforms is diffi-
+ cult. For example, the stack chain needs to be updated every time if we
+ extend the stack on PowerPC. Although it is possible, its updating
+ time overhead decreases performance. So we do the recursion in memory.
+
+ (2) Why don't we simply allocate blocks of memory with malloc()?
+
+ Modern operating systems have a nice feature: they can reserve an ad-
+ dress space instead of allocating memory. We can safely allocate memory
+ pages inside this address space, so the stack could grow without moving
+ memory data (this is important because of pointers). Thus we can allo-
+ cate 1MiB address space, and use only a single memory page (usually
+ 4KiB) if that is enough. However, we can still grow up to 1MiB anytime
+ if needed.
+
+ (3) Who "owns" a JIT stack?
+
+ The owner of the stack is the user program, not the JIT studied pattern
+ or anything else. The user program must ensure that if a stack is being
+ used by pcre2_match(), (that is, it is assigned to a match context that
+ is passed to the pattern currently running), that stack must not be
+ used by any other threads (to avoid overwriting the same memory area).
+ The best practice for multithreaded programs is to allocate a stack for
+ each thread, and return this stack through the JIT callback function.
+
+ (4) When should a JIT stack be freed?
+
+ You can free a JIT stack at any time, as long as it will not be used by
+ pcre2_match() again. When you assign the stack to a match context, only
+ a pointer is set. There is no reference counting or any other magic.
+ You can free compiled patterns, contexts, and stacks in any order, any-
+ time. Just do not call pcre2_match() with a match context pointing to
+ an already freed stack, as that will cause SEGFAULT. (Also, do not free
+ a stack currently used by pcre2_match() in another thread). You can
+ also replace the stack in a context at any time when it is not in use.
+ You should free the previous stack before assigning a replacement.
+
+ (5) Should I allocate/free a stack every time before/after calling
+ pcre2_match()?
+
+ No, because this is too costly in terms of resources. However, you
+ could implement some clever idea which release the stack if it is not
+ used in let's say two minutes. The JIT callback can help to achieve
+ this without keeping a list of patterns.
+
+ (6) OK, the stack is for long term memory allocation. But what happens
+ if a pattern causes stack overflow with a stack of 1MiB? Is that 1MiB
+ kept until the stack is freed?
+
+ Especially on embedded systems, it might be a good idea to release mem-
+ ory sometimes without freeing the stack. There is no API for this at
+ the moment. Probably a function call which returns with the currently
+ allocated memory for any stack and another which allows releasing mem-
+ ory (shrinking the stack) would be a good idea if someone needs this.
+
+ (7) This is too much of a headache. Isn't there any better solution for
+ JIT stack handling?
+
+ No, thanks to Windows. If POSIX threads were used everywhere, we could
+ throw out this complicated API.
+
+
+FREEING JIT SPECULATIVE MEMORY
+
+ void pcre2_jit_free_unused_memory(pcre2_general_context *gcontext);
+
+ The JIT executable allocator does not free all memory when it is possi-
+ ble. It expects new allocations, and keeps some free memory around to
+ improve allocation speed. However, in low memory conditions, it might
+ be better to free all possible memory. You can cause this to happen by
+ calling pcre2_jit_free_unused_memory(). Its argument is a general con-
+ text, for custom memory management, or NULL for standard memory manage-
+ ment.
+
+
+EXAMPLE CODE
+
+ This is a single-threaded example that specifies a JIT stack without
+ using a callback. A real program should include error checking after
+ all the function calls.
+
+ int rc;
+ pcre2_code *re;
+ pcre2_match_data *match_data;
+ pcre2_match_context *mcontext;
+ pcre2_jit_stack *jit_stack;
+
+ re = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED, 0,
+ &errornumber, &erroffset, NULL);
+ rc = pcre2_jit_compile(re, PCRE2_JIT_COMPLETE);
+ mcontext = pcre2_match_context_create(NULL);
+ jit_stack = pcre2_jit_stack_create(32*1024, 512*1024, NULL);
+ pcre2_jit_stack_assign(mcontext, NULL, jit_stack);
+ match_data = pcre2_match_data_create(re, 10);
+ rc = pcre2_match(re, subject, length, 0, 0, match_data, mcontext);
+ /* Process result */
+
+ pcre2_code_free(re);
+ pcre2_match_data_free(match_data);
+ pcre2_match_context_free(mcontext);
+ pcre2_jit_stack_free(jit_stack);
+
+
+JIT FAST PATH API
+
+ Because the API described above falls back to interpreted matching when
+ JIT is not available, it is convenient for programs that are written
+ for general use in many environments. However, calling JIT via
+ pcre2_match() does have a performance impact. Programs that are written
+ for use where JIT is known to be available, and which need the best
+ possible performance, can instead use a "fast path" API to call JIT
+ matching directly instead of calling pcre2_match() (obviously only for
+ patterns that have been successfully processed by pcre2_jit_compile()).
+
+ The fast path function is called pcre2_jit_match(), and it takes ex-
+ actly the same arguments as pcre2_match(). However, the subject string
+ must be specified with a length; PCRE2_ZERO_TERMINATED is not sup-
+ ported. Unsupported option bits (for example, PCRE2_ANCHORED, PCRE2_EN-
+ DANCHORED, and PCRE2_COPY_MATCHED_SUBJECT) are ignored, as is the
+ PCRE2_NO_JIT option. The return values are also the same as for
+ pcre2_match(), plus PCRE2_ERROR_JIT_BADOPTION if a matching mode (par-
+ tial or complete) is requested that was not compiled.
+
+ When you call pcre2_match(), as well as testing for invalid options, a
+ number of other sanity checks are performed on the arguments. For exam-
+ ple, if the subject pointer is NULL but the length is non-zero, an im-
+ mediate error is given. Also, unless PCRE2_NO_UTF_CHECK is set, a UTF
+ subject string is tested for validity. In the interests of speed, these
+ checks do not happen on the JIT fast path. If invalid UTF data is
+ passed when PCRE2_MATCH_INVALID_UTF was not set for pcre2_compile(),
+ the result is undefined. The program may crash or loop or give wrong
+ results. In the absence of PCRE2_MATCH_INVALID_UTF you should call
+ pcre2_jit_match() in UTF mode only if you are sure the subject is
+ valid.
+
+ Bypassing the sanity checks and the pcre2_match() wrapping can give
+ speedups of more than 10%.
+
+
+SEE ALSO
+
+ pcre2api(3), pcre2unicode(3)
+
+
+AUTHOR
+
+ Philip Hazel (FAQ by Zoltan Herczeg)
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 08 August 2026
+ Copyright (c) 1997-2024 University of Cambridge.
+
+
+PCRE2 10.48 08 August 2026 PCRE2JIT(3)
+------------------------------------------------------------------------------
+
+
+PCRE2LIMITS(3) Library Functions Manual PCRE2LIMITS(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+
+SIZE AND OTHER LIMITATIONS
+
+ There are some size limitations in PCRE2 but it is hoped that they will
+ never in practice be relevant.
+
+ The maximum size of a compiled pattern is approximately 64 thousand
+ code units for the 8-bit and 16-bit libraries if PCRE2 is compiled with
+ the default internal linkage size, which is 2 bytes for these li-
+ braries. If you want to process regular expressions that are truly
+ enormous, you can compile PCRE2 with an internal linkage size of 3 or 4
+ (when building the 16-bit library, 3 is rounded up to 4). See the
+ README file in the source distribution and the pcre2build documentation
+ for details. In these cases the limit is substantially larger. How-
+ ever, the speed of execution is slower. In the 32-bit library, the in-
+ ternal linkage size is always 4.
+
+ The maximum length of a source pattern string is essentially unlimited;
+ it is the largest number a PCRE2_SIZE variable can hold. However, the
+ program that calls pcre2_compile() can specify a smaller limit.
+
+ The maximum length (in code units) of a subject string is one less than
+ the largest number a PCRE2_SIZE variable can hold. PCRE2_SIZE is an un-
+ signed integer type, usually defined as size_t. Its maximum value (that
+ is ~(PCRE2_SIZE)0) is reserved as a special indicator for zero-termi-
+ nated strings and unset offsets.
+
+ All values in repeating quantifiers must be less than 65536.
+
+ There are two different limits that apply to branches of lookbehind as-
+ sertions. If every branch in such an assertion matches a fixed number
+ of characters, the maximum length of any branch is 65535 characters. If
+ any branch matches a variable number of characters, then the maximum
+ matching length for every branch is limited. The default limit is set
+ at compile time, defaulting to 255, but can be changed by the calling
+ program.
+
+ There is no limit to the number of parenthesized groups, but there can
+ be no more than 65535 capture groups, and there is a limit to the depth
+ of nesting of parenthesized subpatterns of all kinds. This is imposed
+ in order to limit the amount of system stack used at compile time. The
+ default limit can be specified when PCRE2 is built; if not, the default
+ is set to 250. An application can change this limit by calling
+ pcre2_set_parens_nest_limit() to set the limit in a compile context.
+
+ The maximum length of the name for a named capture group as well as the
+ number of such groups is configurable at build time. The maximum length
+ for the name defaults to 128 code units, and the maximum number of such
+ groups to 10000.
+
+ The maximum length of a name in a (*MARK), (*PRUNE), (*SKIP), or
+ (*THEN) verb is 255 code units for the 8-bit library and 65535 code
+ units for the 16-bit and 32-bit libraries.
+
+ The maximum length of a string argument to a callout is the largest
+ number a 32-bit unsigned integer can hold.
+
+ The maximum amount of heap memory used for matching is controlled by
+ the heap limit, which can be set in a pattern or in a match context.
+ The default is a very large number, effectively unlimited.
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 03 September 2025
+ Copyright (c) 1997-2023 University of Cambridge.
+
+
+PCRE2 10.48 03 September 2025 PCRE2LIMITS(3)
+------------------------------------------------------------------------------
+
+
+PCRE2MATCHING(3) Library Functions Manual PCRE2MATCHING(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+
+PCRE2 MATCHING ALGORITHMS
+
+ This document describes the two different algorithms that are available
+ in PCRE2 for matching a compiled regular expression against a given
+ subject string. The "standard" algorithm is the one provided by the
+ pcre2_match() function. This works in the same way as Perl's matching
+ function, and provides a Perl-compatible matching operation. The just-
+ in-time (JIT) optimization that is described in the pcre2jit documenta-
+ tion is compatible with this function.
+
+ An alternative algorithm is provided by the pcre2_dfa_match() function;
+ it operates in a different way, and is not Perl-compatible. This alter-
+ native has advantages and disadvantages compared with the standard al-
+ gorithm, and these are described below.
+
+ When there is only one possible way in which a given subject string can
+ match a pattern, the two algorithms give the same answer. A difference
+ arises, however, when there are multiple possibilities. For example, if
+ the anchored pattern
+
+ ^<.*>
+
+ is matched against the string
+
+
+
+ there are three possible answers. The standard algorithm finds only one
+ of them, whereas the alternative algorithm finds all three.
+
+
+REGULAR EXPRESSIONS AS TREES
+
+ The set of strings that are matched by a regular expression can be rep-
+ resented as a tree structure. An unlimited repetition in the pattern
+ makes the tree of infinite size, but it is still a tree. Matching the
+ pattern to a given subject string (from a given starting point) can be
+ thought of as a search of the tree. There are two ways to search a
+ tree: depth-first and breadth-first, and these correspond to the two
+ matching algorithms provided by PCRE2.
+
+
+THE STANDARD MATCHING ALGORITHM
+
+ In the terminology of Jeffrey Friedl's book "Mastering Regular Expres-
+ sions", the standard algorithm is an "NFA algorithm". It conducts a
+ depth-first search of the pattern tree. That is, it proceeds along a
+ single path through the tree, checking that the subject matches what is
+ required. When there is a mismatch, the algorithm tries any alterna-
+ tives at the current point, and if they all fail, it backs up to the
+ previous branch point in the tree, and tries the next alternative
+ branch at that level. This often involves backing up (moving to the
+ left) in the subject string as well. The order in which repetition
+ branches are tried is controlled by the greedy or ungreedy nature of
+ the quantifier.
+
+ If a leaf node is reached, a matching string has been found, and at
+ that point the algorithm stops. Thus, if there is more than one possi-
+ ble match, this algorithm returns the first one that it finds. Whether
+ this is the shortest, the longest, or some intermediate length depends
+ on the way the alternations and the greedy or ungreedy repetition quan-
+ tifiers are specified in the pattern.
+
+ Because it ends up with a single path through the tree, it is rela-
+ tively straightforward for this algorithm to keep track of the sub-
+ strings that are matched by portions of the pattern in parentheses.
+ This provides support for capturing parentheses and backreferences.
+
+
+THE ALTERNATIVE MATCHING ALGORITHM
+
+ This algorithm conducts a breadth-first search of the tree. Starting
+ from the first matching point in the subject, it scans the subject
+ string from left to right, once, character by character, and as it does
+ this, it remembers all the paths through the tree that represent valid
+ matches. In Friedl's terminology, this is a kind of "DFA algorithm",
+ though it is not implemented as a traditional finite state machine (it
+ keeps multiple states active simultaneously).
+
+ Although the general principle of this matching algorithm is that it
+ scans the subject string only once, without backtracking, there is one
+ exception: when a lookaround assertion is encountered, the characters
+ following or preceding the current point have to be independently in-
+ spected.
+
+ The scan continues until either the end of the subject is reached, or
+ there are no more unterminated paths. At this point, terminated paths
+ represent the different matching possibilities (if there are none, the
+ match has failed). Thus, if there is more than one possible match,
+ this algorithm finds all of them, and in particular, it finds the
+ longest. The matches are returned in the output vector in decreasing
+ order of length. There is an option to stop the algorithm after the
+ first match (which is necessarily the shortest) is found.
+
+ Note that the size of vector needed to contain all the results depends
+ on the number of simultaneous matches, not on the number of capturing
+ parentheses in the pattern. Using pcre2_match_data_create_from_pat-
+ tern() to create the match data block is therefore not advisable when
+ doing DFA matching.
+
+ Note also that all the matches that are found start at the same point
+ in the subject. If the pattern
+
+ cat(er(pillar)?)?
+
+ is matched against the string "the caterpillar catchment", the result
+ is the three strings "caterpillar", "cater", and "cat" that start at
+ the fifth character of the subject. The algorithm does not automati-
+ cally move on to find matches that start at later positions.
+
+ PCRE2's "auto-possessification" optimization usually applies to charac-
+ ter repeats at the end of a pattern (as well as internally). For exam-
+ ple, the pattern "a\d+" is compiled as if it were "a\d++" because there
+ is no point even considering the possibility of backtracking into the
+ repeated digits. For DFA matching, this means that only one possible
+ match is found. If you really do want multiple matches in such cases,
+ either use an ungreedy repeat ("a\d+?") or set the PCRE2_NO_AUTO_POS-
+ SESS option when compiling.
+
+ There are a number of features of PCRE2 regular expressions that are
+ not supported or behave differently in the alternative matching func-
+ tion. Those that are not supported cause an error if encountered.
+
+ 1. Because the algorithm finds all possible matches, the greedy or un-
+ greedy nature of repetition quantifiers is not relevant (though it may
+ affect auto-possessification, as just described). During matching,
+ greedy and ungreedy quantifiers are treated in exactly the same way.
+ However, possessive quantifiers can make a difference when what follows
+ could also match what is quantified, for example in a pattern like
+ this:
+
+ ^a++\w!
+
+ This pattern matches "aaab!" but not "aaa!", which would be matched by
+ a non-possessive quantifier. Similarly, if an atomic group is present,
+ it is matched as if it were a standalone pattern at the current point,
+ and the longest match is then "locked in" for the rest of the overall
+ pattern.
+
+ 2. When dealing with multiple paths through the tree simultaneously, it
+ is not straightforward to keep track of captured substrings for the
+ different matching possibilities, and PCRE2's implementation of this
+ algorithm does not attempt to do this. This means that no captured sub-
+ strings are available.
+
+ 3. Because no substrings are captured, a number of related features are
+ not available:
+
+ (a) Backreferences;
+
+ (b) Conditional expressions that use a backreference as the condition
+ or test for a specific group recursion;
+
+ (c) Script runs;
+
+ (d) Scan substring assertions.
+
+ 4. Because many paths through the tree may be active, the \K escape se-
+ quence, which resets the start of the match when encountered (but may
+ be on some paths and not on others), is not supported.
+
+ 5. Callouts are supported, but the value of the capture_top field is
+ always 1, and the value of the capture_last field is always 0.
+
+ 6. The \C escape sequence, which (in the standard algorithm) always
+ matches a single code unit, even in a UTF mode, is not supported in UTF
+ modes because the alternative algorithm moves through the subject
+ string one character (not code unit) at a time, for all active paths
+ through the tree.
+
+ 7. Except for (*FAIL), the backtracking control verbs such as (*PRUNE)
+ are not supported. (*FAIL) is supported, and behaves like a failing
+ negative assertion.
+
+ 8. The PCRE2_MATCH_INVALID_UTF option for pcre2_compile() is not sup-
+ ported by pcre2_dfa_match().
+
+
+ADVANTAGES OF THE ALTERNATIVE ALGORITHM
+
+ The main advantage of the alternative algorithm is that all possible
+ matches (at a single point in the subject) are automatically found, and
+ in particular, the longest match is found. To find more than one match
+ at the same point using the standard algorithm, you have to do kludgy
+ things with callouts.
+
+ Partial matching is possible with this algorithm, though it has some
+ limitations. The pcre2partial documentation gives details of partial
+ matching and discusses multi-segment matching.
+
+
+DISADVANTAGES OF THE ALTERNATIVE ALGORITHM
+
+ The alternative algorithm suffers from a number of disadvantages:
+
+ 1. It is substantially slower than the standard algorithm. This is
+ partly because it has to search for all possible matches, but is also
+ because it is less susceptible to optimization.
+
+ 2. Capturing parentheses and other features such as backreferences that
+ rely on them are not supported.
+
+ 3. Matching within invalid UTF strings is not supported.
+
+ 4. Although atomic groups are supported, their use does not provide the
+ performance advantage that it does for the standard algorithm.
+
+ 5. JIT optimization is not supported.
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 22 February 2025
+ Copyright (c) 1997-2024 University of Cambridge.
+
+
+PCRE2 10.48 22 February 2025 PCRE2MATCHING(3)
+------------------------------------------------------------------------------
+
+
+PCRE2PARTIAL(3) Library Functions Manual PCRE2PARTIAL(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+
+PARTIAL MATCHING IN PCRE2
+
+ In normal use of PCRE2, if there is a match up to the end of a subject
+ string, but more characters are needed to match the entire pattern,
+ PCRE2_ERROR_NOMATCH is returned, just like any other failing match.
+ There are circumstances where it might be helpful to distinguish this
+ "partial match" case.
+
+ One example is an application where the subject string is very long,
+ and not all available at once. The requirement here is to be able to do
+ the matching segment by segment, but special action is needed when a
+ matched substring spans the boundary between two segments.
+
+ Another example is checking a user input string as it is typed, to en-
+ sure that it conforms to a required format. Invalid characters can be
+ immediately diagnosed and rejected, giving instant feedback.
+
+ Partial matching is a PCRE2-specific feature; it is not Perl-compati-
+ ble. It is requested by setting one of the PCRE2_PARTIAL_HARD or
+ PCRE2_PARTIAL_SOFT options when calling a matching function. The dif-
+ ference between the two options is whether or not a partial match is
+ preferred to an alternative complete match, though the details differ
+ between the two types of matching function. If both options are set,
+ PCRE2_PARTIAL_HARD takes precedence.
+
+ If you want to use partial matching with just-in-time optimized code,
+ as well as setting a partial match option for the matching function,
+ you must also call pcre2_jit_compile() with one or both of these op-
+ tions:
+
+ PCRE2_JIT_PARTIAL_HARD
+ PCRE2_JIT_PARTIAL_SOFT
+
+ PCRE2_JIT_COMPLETE should also be set if you are going to run non-par-
+ tial matches on the same pattern. Separate code is compiled for each
+ mode. If the appropriate JIT mode has not been compiled, interpretive
+ matching code is used.
+
+ Setting a partial matching option disables two of PCRE2's standard op-
+ timization hints. PCRE2 remembers the last literal code unit in a pat-
+ tern, and abandons matching immediately if it is not present in the
+ subject string. This optimization cannot be used for a subject string
+ that might match only partially. PCRE2 also remembers a minimum length
+ of a matching string, and does not bother to run the matching function
+ on shorter strings. This optimization is also disabled for partial
+ matching.
+
+
+REQUIREMENTS FOR A PARTIAL MATCH
+
+ A possible partial match occurs during matching when the end of the
+ subject string is reached successfully, but either more characters are
+ needed to complete the match, or the addition of more characters might
+ change what is matched.
+
+ Example 1: if the pattern is /abc/ and the subject is "ab", more char-
+ acters are definitely needed to complete a match. In this case both
+ hard and soft matching options yield a partial match.
+
+ Example 2: if the pattern is /ab+/ and the subject is "ab", a complete
+ match can be found, but the addition of more characters might change
+ what is matched. In this case, only PCRE2_PARTIAL_HARD returns a par-
+ tial match; PCRE2_PARTIAL_SOFT returns the complete match.
+
+ On reaching the end of the subject, when PCRE2_PARTIAL_HARD is set, if
+ the next pattern item is \z, \Z, \b, \B, or $ there is always a partial
+ match. Otherwise, for both options, the next pattern item must be one
+ that inspects a character, and at least one of the following must be
+ true:
+
+ (1) At least one character has already been inspected. An inspected
+ character need not form part of the final matched string; lookbehind
+ assertions and the \K escape sequence provide ways of inspecting char-
+ acters before the start of a matched string.
+
+ (2) The pattern contains one or more lookbehind assertions. This condi-
+ tion exists in case there is a lookbehind that inspects characters be-
+ fore the start of the match.
+
+ (3) There is a special case when the whole pattern can match an empty
+ string. When the starting point is at the end of the subject, the
+ empty string match is a possibility, and if PCRE2_PARTIAL_SOFT is set
+ and neither of the above conditions is true, it is returned. However,
+ because adding more characters might result in a non-empty match,
+ PCRE2_PARTIAL_HARD returns a partial match, which in this case means
+ "there is going to be a match at this point, but until some more char-
+ acters are added, we do not know if it will be an empty string or some-
+ thing longer".
+
+
+PARTIAL MATCHING USING pcre2_match()
+
+ When a partial matching option is set, the result of calling
+ pcre2_match() can be one of the following:
+
+ A successful match
+ A complete match has been found, starting and ending within this sub-
+ ject.
+
+ PCRE2_ERROR_NOMATCH
+ No match can start anywhere in this subject.
+
+ PCRE2_ERROR_PARTIAL
+ Adding more characters may result in a complete match that uses one
+ or more characters from the end of this subject.
+
+ When a partial match is returned, the first two elements in the ovector
+ point to the portion of the subject that was matched, but the values in
+ the rest of the ovector are undefined. The appearance of \K in the pat-
+ tern has no effect for a partial match. Consider this pattern:
+
+ /abc\K123/
+
+ If it is matched against "456abc123xyz" the result is a complete match,
+ and the ovector defines the matched string as "123", because \K resets
+ the "start of match" point. However, if a partial match is requested
+ and the subject string is "456abc12", a partial match is found for the
+ string "abc12", because all these characters are needed for a subse-
+ quent re-match with additional characters.
+
+ If there is more than one partial match, the first one that was found
+ provides the data that is returned. Consider this pattern:
+
+ /123\w+X|dogY/
+
+ If this is matched against the subject string "abc123dog", both alter-
+ natives fail to match, but the end of the subject is reached during
+ matching, so PCRE2_ERROR_PARTIAL is returned. The offsets are set to 3
+ and 9, identifying "123dog" as the first partial match. (In this exam-
+ ple, there are two partial matches, because "dog" on its own partially
+ matches the second alternative.)
+
+ How a partial match is processed by pcre2_match()
+
+ What happens when a partial match is identified depends on which of the
+ two partial matching options is set.
+
+ If PCRE2_PARTIAL_HARD is set, PCRE2_ERROR_PARTIAL is returned as soon
+ as a partial match is found, without continuing to search for possible
+ complete matches. This option is "hard" because it prefers an earlier
+ partial match over a later complete match. For this reason, the assump-
+ tion is made that the end of the supplied subject string is not the
+ true end of the available data, which is why \z, \Z, \b, \B, and $ al-
+ ways give a partial match.
+
+ If PCRE2_PARTIAL_SOFT is set, the partial match is remembered, but
+ matching continues as normal, and other alternatives in the pattern are
+ tried. If no complete match can be found, PCRE2_ERROR_PARTIAL is re-
+ turned instead of PCRE2_ERROR_NOMATCH. This option is "soft" because it
+ prefers a complete match over a partial match. All the various matching
+ items in a pattern behave as if the subject string is potentially com-
+ plete; \z, \Z, and $ match at the end of the subject, as normal, and
+ for \b and \B the end of the subject is treated as a non-alphanumeric.
+
+ The difference between the two partial matching options can be illus-
+ trated by a pattern such as:
+
+ /dog(sbody)?/
+
+ This matches either "dog" or "dogsbody", greedily (that is, it prefers
+ the longer string if possible). If it is matched against the string
+ "dog" with PCRE2_PARTIAL_SOFT, it yields a complete match for "dog".
+ However, if PCRE2_PARTIAL_HARD is set, the result is PCRE2_ERROR_PAR-
+ TIAL. On the other hand, if the pattern is made ungreedy the result is
+ different:
+
+ /dog(sbody)??/
+
+ In this case the result is always a complete match because that is
+ found first, and matching never continues after finding a complete
+ match. It might be easier to follow this explanation by thinking of the
+ two patterns like this:
+
+ /dog(sbody)?/ is the same as /dogsbody|dog/
+ /dog(sbody)??/ is the same as /dog|dogsbody/
+
+ The second pattern will never match "dogsbody", because it will always
+ find the shorter match first.
+
+ Example of partial matching using pcre2test
+
+ The pcre2test data modifiers partial_hard (or ph) and partial_soft (or
+ ps) set PCRE2_PARTIAL_HARD and PCRE2_PARTIAL_SOFT, respectively, when
+ calling pcre2_match(). Here is a run of pcre2test using a pattern that
+ matches the whole subject in the form of a date:
+
+ re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
+ data> 25dec3\=ph
+ Partial match: 23dec3
+ data> 3ju\=ph
+ Partial match: 3ju
+ data> 3juj\=ph
+ No match
+
+ This example gives the same results for both hard and soft partial
+ matching options. Here is an example where there is a difference:
+
+ re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
+ data> 25jun04\=ps
+ 0: 25jun04
+ 1: jun
+ data> 25jun04\=ph
+ Partial match: 25jun04
+
+ With PCRE2_PARTIAL_SOFT, the subject is matched completely. For
+ PCRE2_PARTIAL_HARD, however, the subject is assumed not to be complete,
+ so there is only a partial match.
+
+
+MULTI-SEGMENT MATCHING WITH pcre2_match()
+
+ PCRE was not originally designed with multi-segment matching in mind.
+ However, over time, features (including partial matching) that make
+ multi-segment matching possible have been added. A very long string can
+ be searched segment by segment by calling pcre2_match() repeatedly,
+ with the aim of achieving the same results that would happen if the en-
+ tire string was available for searching all the time. Normally, the
+ strings that are being sought are much shorter than each individual
+ segment, and are in the middle of very long strings, so the pattern is
+ normally not anchored.
+
+ Special logic must be implemented to handle a matched substring that
+ spans a segment boundary. PCRE2_PARTIAL_HARD should be used, because it
+ returns a partial match at the end of a segment whenever there is the
+ possibility of changing the match by adding more characters. The
+ PCRE2_NOTBOL option should also be set for all but the first segment.
+
+ When a partial match occurs, the next segment must be added to the cur-
+ rent subject and the match re-run, using the startoffset argument of
+ pcre2_match() to begin at the point where the partial match started.
+ For example:
+
+ re> /\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d/
+ data> ...the date is 23ja\=ph
+ Partial match: 23ja
+ data> ...the date is 23jan19 and on that day...\=offset=15
+ 0: 23jan19
+ 1: jan
+
+ Note the use of the offset modifier to start the new match where the
+ partial match was found. In this example, the next segment was added to
+ the one in which the partial match was found. This is the most
+ straightforward approach, typically using a memory buffer that is twice
+ the size of each segment. After a partial match, the first half of the
+ buffer is discarded, the second half is moved to the start of the
+ buffer, and a new segment is added before repeating the match as in the
+ example above. After a no match, the entire buffer can be discarded.
+
+ If there are memory constraints, you may want to discard text that pre-
+ cedes a partial match before adding the next segment. Unfortunately,
+ this is not at present straightforward. In cases such as the above,
+ where the pattern does not contain any lookbehinds, it is sufficient to
+ retain only the partially matched substring. However, if the pattern
+ contains a lookbehind assertion, characters that precede the start of
+ the partial match may have been inspected during the matching process.
+ When pcre2test displays a partial match, it indicates these characters
+ with '<' if the allusedtext modifier is set:
+
+ re> "(?<=123)abc"
+ data> xx123ab\=ph,allusedtext
+ Partial match: 123ab
+ <<<
+
+ However, the allusedtext modifier is not available for JIT matching,
+ because JIT matching does not record the first (or last) consulted
+ characters. For this reason, this information is not available via the
+ API. It is therefore not possible in general to obtain the exact number
+ of characters that must be retained in order to get the right match re-
+ sult. If you cannot retain the entire segment, you must find some
+ heuristic way of choosing.
+
+ If you know the approximate length of the matching substrings, you can
+ use that to decide how much text to retain. The only lookbehind infor-
+ mation that is currently available via the API is the length of the
+ longest individual lookbehind in a pattern, but this can be misleading
+ if there are nested lookbehinds. The value returned by calling
+ pcre2_pattern_info() with the PCRE2_INFO_MAXLOOKBEHIND option is the
+ maximum number of characters (not code units) that any individual look-
+ behind moves back when it is processed. A pattern such as
+ "(?<=(? /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
+ data> 23ja\=dfa,ps
+ Partial match: 23ja
+ data> n05\=dfa,dfa_restart
+ 0: n05
+
+ The first call has "23ja" as the subject, and requests partial match-
+ ing; the second call has "n05" as the subject for the continued
+ (restarted) match. Notice that when the match is complete, only the
+ last part is shown; PCRE2 does not retain the previously partially-
+ matched string. It is up to the calling program to do that if it needs
+ to. This means that, for an unanchored pattern, if a continued match
+ fails, it is not possible to try again at a new starting point. All
+ this facility is capable of doing is continuing with the previous match
+ attempt. For example, consider this pattern:
+
+ 1234|3789
+
+ If the first part of the subject is "ABC123", a partial match of the
+ first alternative is found at offset 3. There is no partial match for
+ the second alternative, because such a match does not start at the same
+ point in the subject string. Attempting to continue with the string
+ "7890" does not yield a match because only those alternatives that
+ match at one point in the subject are remembered. Depending on the ap-
+ plication, this may or may not be what you want.
+
+ If you do want to allow for starting again at the next character, one
+ way of doing it is to retain some or all of the segment and try a new
+ complete match, as described for pcre2_match() above. Another possibil-
+ ity is to work with two buffers. If a partial match at offset n in the
+ first buffer is followed by "no match" when PCRE2_DFA_RESTART is used
+ on the second buffer, you can then try a new match starting at offset
+ n+1 in the first buffer.
+
+ Therefore, PCRE2_DFA_RESTART does not remove the need to keep earlier
+ subject data. In order to perform a bumpalong and continue matching at
+ the next character, all subject data from the current match start must
+ be retained, together with enough preceding data to satisfy the re-
+ quirements of lookbehind assertions (remembering as above that
+ PCRE2_INFO_MAXLOOKBEHIND only describes the buffer requirement of a
+ single lookbehind, and nested lookbehinds can read back further from
+ the match start). This makes streaming match processing using
+ PCRE2_DFA_RESTART challenging, and the application cannot easily set a
+ bound on the number of chunks to buffer. For multi-segment searching
+ that is intended to produce the same result as searching the whole sub-
+ ject, it is usually simpler to avoid PCRE2_DFA_RESTART and run a fresh
+ match, using either matching function, over the retained text.
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 16 August 2026
+ Copyright (c) 1997-2019 University of Cambridge.
+
+
+PCRE2 10.48 16 August 2026 PCRE2PARTIAL(3)
+------------------------------------------------------------------------------
+
+
+PCRE2PATTERN(3) Library Functions Manual PCRE2PATTERN(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+
+PCRE2 REGULAR EXPRESSION DETAILS
+
+ The syntax and semantics of the regular expressions that are supported
+ by PCRE2 are described in detail below. There is a quick-reference syn-
+ tax summary in the pcre2syntax page. PCRE2 tries to match Perl syntax
+ and semantics as closely as it can. PCRE2 also supports some alterna-
+ tive regular expression syntax that does not conflict with the Perl
+ syntax in order to provide some compatibility with regular expressions
+ in Python, .NET, and Oniguruma. There are in addition some options that
+ enable alternative syntax and semantics that are not the same as in
+ Perl.
+
+ Perl's regular expressions are described in its own documentation, and
+ regular expressions in general are covered in a number of books, some
+ of which have copious examples. Jeffrey Friedl's "Mastering Regular Ex-
+ pressions", published by O'Reilly, covers regular expressions in great
+ detail. This description of PCRE2's regular expressions is intended as
+ reference material.
+
+ This document discusses the regular expression patterns that are sup-
+ ported by PCRE2 when its main matching function, pcre2_match(), is
+ used. PCRE2 also has an alternative matching function,
+ pcre2_dfa_match(), which matches using a different algorithm that is
+ not Perl-compatible. Some of the features discussed below are not
+ available when DFA matching is used. The advantages and disadvantages
+ of the alternative function, and how it differs from the normal func-
+ tion, are discussed in the pcre2matching page.
+
+
+EBCDIC CHARACTER CODES
+
+ Most computers use ASCII or Unicode for encoding characters, and PCRE2
+ assumes this by default. However, it can be compiled to run in an envi-
+ ronment that uses the EBCDIC code, which is the case for some IBM main-
+ frame operating systems. In the sections below, character code values
+ are ASCII or Unicode; in an EBCDIC environment these characters may
+ have different code values, and there are no code points greater than
+ 255. Differences in behaviour when PCRE2 is running in an EBCDIC envi-
+ ronment are described in the section "EBCDIC environments" below, which
+ you can ignore unless you really are in an EBCDIC environment.
+
+
+SPECIAL START-OF-PATTERN ITEMS
+
+ A number of options that can be passed to pcre2_compile() can also be
+ set by special items at the start of a pattern. These are not Perl-com-
+ patible, but are provided to make these options accessible to pattern
+ writers who are not able to change the program that processes the pat-
+ tern. Any number of these items may appear, but they must all be to-
+ gether right at the start of the pattern string, and the letters must
+ be in upper case.
+
+ UTF support
+
+ In the 8-bit and 16-bit PCRE2 libraries, characters may be coded either
+ as single code units, or as multiple UTF-8 or UTF-16 code units. UTF-32
+ can be specified for the 32-bit library, in which case it constrains
+ the character values to valid Unicode code points. To process UTF
+ strings, PCRE2 must be built to include Unicode support (which is the
+ default). When using UTF strings you must either call the compiling
+ function with one or both of the PCRE2_UTF or PCRE2_MATCH_INVALID_UTF
+ options, or the pattern must start with the special sequence (*UTF),
+ which is equivalent to setting the relevant PCRE2_UTF. How setting a
+ UTF mode affects pattern matching is mentioned in several places below.
+ There is also a summary of features in the pcre2unicode page.
+
+ Some applications that allow their users to supply patterns may wish to
+ restrict them to non-UTF data for security reasons. If the
+ PCRE2_NEVER_UTF option is passed to pcre2_compile(), (*UTF) is not al-
+ lowed, and its appearance in a pattern causes an error.
+
+ Unicode property support
+
+ Another special sequence that may appear at the start of a pattern is
+ (*UCP). This has the same effect as setting the PCRE2_UCP option: it
+ causes sequences such as \d and \w to use Unicode properties to deter-
+ mine character types, instead of recognizing only characters with codes
+ less than 256 via a lookup table. If also causes upper/lower casing op-
+ erations to use Unicode properties for characters with code points
+ greater than 127, even when UTF is not set. These behaviours can be
+ changed within the pattern; see the section entitled "Internal Option
+ Setting" below.
+
+ Some applications that allow their users to supply patterns may wish to
+ restrict them for security reasons. If the PCRE2_NEVER_UCP option is
+ passed to pcre2_compile(), (*UCP) is not allowed, and its appearance in
+ a pattern causes an error.
+
+ Locking out empty string matching
+
+ Starting a pattern with (*NOTEMPTY) or (*NOTEMPTY_ATSTART) has the same
+ effect as passing the PCRE2_NOTEMPTY or PCRE2_NOTEMPTY_ATSTART option
+ to whichever matching function is subsequently called to match the pat-
+ tern. These options lock out the matching of empty strings, either en-
+ tirely, or only at the start of the subject.
+
+ Disabling auto-possessification
+
+ If a pattern starts with (*NO_AUTO_POSSESS), it has the same effect as
+ setting the PCRE2_NO_AUTO_POSSESS option, or calling pcre2_set_opti-
+ mize() with a PCRE2_AUTO_POSSESS_OFF directive. This stops PCRE2 from
+ making quantifiers possessive when what follows cannot match the re-
+ peated item. For example, by default a+b is treated as a++b. For more
+ details, see the pcre2api documentation.
+
+ Disabling start-up optimizations
+
+ If a pattern starts with (*NO_START_OPT), it has the same effect as
+ setting the PCRE2_NO_START_OPTIMIZE option, or calling pcre2_set_opti-
+ mize() with a PCRE2_START_OPTIMIZE_OFF directive. This disables several
+ optimizations for quickly reaching "no match" results. For more de-
+ tails, see the pcre2api documentation.
+
+ Disabling automatic anchoring
+
+ If a pattern starts with (*NO_DOTSTAR_ANCHOR), it has the same effect
+ as setting the PCRE2_NO_DOTSTAR_ANCHOR option, or calling pcre2_set_op-
+ timize() with a PCRE2_DOTSTAR_ANCHOR_OFF directive. This disables op-
+ timizations that apply to patterns whose top-level branches all start
+ with .* (match any number of arbitrary characters). For more details,
+ see the pcre2api documentation.
+
+ Disabling JIT compilation
+
+ If a pattern that starts with (*NO_JIT) is successfully compiled, an
+ attempt by the application to apply the JIT optimization by calling
+ pcre2_jit_compile() is ignored.
+
+ Setting match resource limits
+
+ The pcre2_match() function contains a counter that is incremented every
+ time it goes round its main loop. The caller of pcre2_match() can set a
+ limit on this counter, which therefore limits the amount of computing
+ resource used for a match. The maximum depth of nested backtracking can
+ also be limited; this indirectly restricts the amount of heap memory
+ that is used, but there is also an explicit memory limit that can be
+ set.
+
+ These facilities are provided to catch runaway matches that are pro-
+ voked by patterns with huge matching trees. A common example is a pat-
+ tern with nested unlimited repeats applied to a long string that does
+ not match. When one of these limits is reached, pcre2_match() gives an
+ error return. The limits can also be set by items at the start of the
+ pattern of the form
+
+ (*LIMIT_HEAP=d)
+ (*LIMIT_MATCH=d)
+ (*LIMIT_DEPTH=d)
+
+ where d is any number of decimal digits. However, the value of the set-
+ ting must be less than the value set (or defaulted) by the caller of
+ pcre2_match() for it to have any effect. In other words, the pattern
+ writer can lower the limits set by the programmer, but not raise them.
+ If there is more than one setting of one of these limits, the lower
+ value is used. The heap limit is specified in kibibytes (units of 1024
+ bytes).
+
+ Prior to release 10.30, LIMIT_DEPTH was called LIMIT_RECURSION. This
+ name is still recognized for backwards compatibility.
+
+ The heap limit applies only when the pcre2_match() or pcre2_dfa_match()
+ interpreters are used for matching. It does not apply to JIT. The match
+ limit is used (but in a different way) when JIT is being used, or when
+ pcre2_dfa_match() is called, to limit computing resource usage by those
+ matching functions. The depth limit is ignored by JIT but is relevant
+ for DFA matching, which uses function recursion for recursions within
+ the pattern and for lookaround assertions and atomic groups. In this
+ case, the depth limit controls the depth of such recursion.
+
+ Newline conventions
+
+ PCRE2 supports six different conventions for indicating line breaks in
+ strings: a single CR (carriage return) character, a single LF (line-
+ feed) character, the two-character sequence CRLF, any of the three pre-
+ ceding, any Unicode newline sequence, or the NUL character (binary
+ zero). The pcre2api page has further discussion about newlines, and
+ shows how to set the newline convention when calling pcre2_compile().
+
+ It is also possible to specify a newline convention by starting a pat-
+ tern string with one of the following sequences:
+
+ (*CR) carriage return
+ (*LF) linefeed
+ (*CRLF) carriage return, followed by linefeed
+ (*ANYCRLF) any of the three above
+ (*ANY) all Unicode newline sequences
+ (*NUL) the NUL character (binary zero)
+
+ These override the default and the options given to the compiling func-
+ tion. For example, on a Unix system where LF is the default newline se-
+ quence, the pattern
+
+ (*CR)a.b
+
+ changes the convention to CR. That pattern matches "a\nb" because LF is
+ no longer a newline. If more than one of these settings is present, the
+ last one is used.
+
+ The newline convention affects where the circumflex and dollar asser-
+ tions are true. It also affects the interpretation of the dot metachar-
+ acter when PCRE2_DOTALL is not set, and the behaviour of \N when not
+ followed by an opening brace. However, it does not affect what the \R
+ escape sequence matches. By default, this is any Unicode newline se-
+ quence, for Perl compatibility. However, this can be changed; see the
+ next section and the description of \R in the section entitled "Newline
+ sequences" below. A change of \R setting can be combined with a change
+ of newline convention.
+
+ Specifying what \R matches
+
+ It is possible to restrict \R to match only CR, LF, or CRLF (instead of
+ the complete set of Unicode line endings) by setting the option
+ PCRE2_BSR_ANYCRLF at compile time. This effect can also be achieved by
+ starting a pattern with (*BSR_ANYCRLF). For completeness, (*BSR_UNI-
+ CODE) is also recognized, corresponding to PCRE2_BSR_UNICODE.
+
+
+CHARACTERS AND METACHARACTERS
+
+ A regular expression is a pattern that is matched against a subject
+ string from left to right. Most characters stand for themselves in a
+ pattern, and match the corresponding characters in the subject. As a
+ trivial example, the pattern
+
+ The quick brown fox
+
+ matches a portion of a subject string that is identical to itself. When
+ caseless matching is specified (the PCRE2_CASELESS option or (?i)
+ within the pattern), letters are matched independently of case. Note
+ that there are two ASCII characters, K and S, that, in addition to
+ their lower case ASCII equivalents, are case-equivalent with Unicode
+ U+212A (Kelvin sign) and U+017F (long S) respectively when either
+ PCRE2_UTF or PCRE2_UCP is set, unless the PCRE2_EXTRA_CASELESS_RESTRICT
+ option is in force (either passed to pcre2_compile() or set by (*CASE-
+ LESS_RESTRICT) or (?r) within the pattern). If the PCRE2_EXTRA_TURK-
+ ISH_CASING option is in force (either passed to pcre2_compile() or set
+ by (*TURKISH_CASING) within the pattern), then the 'i' letters are
+ matched according to Turkish and Azeri languages.
+
+ The power of regular expressions comes from the ability to include wild
+ cards, character classes, alternatives, and repetitions in the pattern.
+ These are encoded in the pattern by the use of metacharacters, which do
+ not stand for themselves but instead are interpreted in some special
+ way.
+
+ There are two different sets of metacharacters: those that are recog-
+ nized anywhere in the pattern except within square brackets, and those
+ that are recognized within square brackets. Outside square brackets,
+ the metacharacters are as follows:
+
+ \ general escape character with several uses
+ ^ assert start of string (or line, in multiline mode)
+ $ assert end of string (or line, in multiline mode)
+ . match any character except newline (by default)
+ [ start character class definition
+ | start of alternative branch
+ ( start group or control verb
+ ) end group or control verb
+ * 0 or more quantifier
+ + 1 or more quantifier; also "possessive quantifier"
+ ? 0 or 1 quantifier; also quantifier minimizer
+ { potential start of min/max quantifier
+
+ Brace characters { and } are also used to enclose data for construc-
+ tions such as \g{2} or \k{name}. In almost all uses of braces, space
+ and/or horizontal tab characters that follow { or precede } are allowed
+ and are ignored. In the case of quantifiers, they may also appear be-
+ fore or after the comma. The exception to this is \u{...} which is an
+ ECMAScript compatibility feature that is recognized only when the
+ PCRE2_EXTRA_ALT_BSUX option is set. ECMAScript does not ignore such
+ white space; it causes the item to be interpreted as literal.
+
+ Part of a pattern that is in square brackets is called a "character
+ class". In a character class the only metacharacters are:
+
+ \ general escape character
+ ^ negate the class, but only if the first character
+ - indicates character range
+ [ POSIX character class (if followed by POSIX syntax)
+ ] terminates the character class
+
+ If a pattern is compiled with the PCRE2_EXTENDED option, most white
+ space in the pattern, other than in a character class, within a \Q...\E
+ sequence, or between a # outside a character class and the next new-
+ line, inclusive, is ignored. An escaping backslash can be used to in-
+ clude a white space or a # character as part of the pattern. If the
+ PCRE2_EXTENDED_MORE option is set, the same applies, but in addition
+ unescaped space and horizontal tab characters are ignored inside a
+ character class. Note: only these two characters are ignored, not the
+ full set of pattern white space characters that are ignored outside a
+ character class. Option settings can be changed within a pattern; see
+ the section entitled "Internal Option Setting" below.
+
+ The following sections describe the use of each of the metacharacters.
+
+
+BACKSLASH
+
+ The backslash character has several uses. Firstly, if it is followed by
+ a character that is not a digit or a letter, it takes away any special
+ meaning that character may have. This use of backslash as an escape
+ character applies both inside and outside character classes.
+
+ For example, if you want to match a * character, you must write \* in
+ the pattern. This escaping action applies whether or not the following
+ character would otherwise be interpreted as a metacharacter, so it is
+ always safe to precede a non-alphanumeric with backslash to specify
+ that it stands for itself. In particular, if you want to match a back-
+ slash, you write \\.
+
+ Only ASCII digits and letters have any special meaning after a back-
+ slash. All other characters (in particular, those whose code points are
+ greater than 127) are treated as literals.
+
+ If you want to treat all characters in a sequence as literals, you can
+ do so by putting them between \Q and \E. Note that this includes white
+ space even when the PCRE2_EXTENDED option is set so that most other
+ white space is ignored. The behaviour is different from Perl in that $
+ and @ are handled as literals in \Q...\E sequences in PCRE2, whereas in
+ Perl, $ and @ cause variable interpolation. Also, Perl does "double-
+ quotish backslash interpolation" on any backslashes between \Q and \E
+ which, its documentation says, "may lead to confusing results". PCRE2
+ treats a backslash between \Q and \E just like any other character.
+ Note the following examples:
+
+ Pattern PCRE2 matches Perl matches
+
+ \Qabc$xyz\E abc$xyz abc followed by the
+ contents of $xyz
+ \Qabc\$xyz\E abc\$xyz abc\$xyz
+ \Qabc\E\$\Qxyz\E abc$xyz abc$xyz
+ \QA\B\E A\B A\B
+ \Q\\E \ \\E
+
+ The \Q...\E sequence is recognized both inside and outside character
+ classes. An isolated \E that is not preceded by \Q is ignored. If \Q
+ is not followed by \E later in the pattern, the literal interpretation
+ continues to the end of the pattern (that is, \E is assumed at the
+ end). If the isolated \Q is inside a character class, this causes an
+ error, because the character class is then not terminated by a closing
+ square bracket.
+
+ Another difference from Perl is that any appearance of \Q or \E inside
+ what might otherwise be a quantifier causes PCRE2 not to recognize the
+ sequence as a quantifier. Perl recognizes a quantifier if (redundantly)
+ either of the numbers is inside \Q...\E, but not if the separating
+ comma is. When not recognized as a quantifier a sequence such as
+ {\Q1\E,2} is treated as the literal string "{1,2}".
+
+ Non-printing characters
+
+ A second use of backslash provides a way of encoding non-printing char-
+ acters in patterns in a visible manner. There is no restriction on the
+ appearance of non-printing characters in a pattern, but when a pattern
+ is being prepared by text editing, it is often easier to use one of the
+ following escape sequences instead of the binary character it repre-
+ sents. In an ASCII or Unicode environment, these escapes are as fol-
+ lows:
+
+ \a alarm, that is, the BEL character (hex 07)
+ \cx "control-x", where x is a non-control ASCII character
+ \e escape (hex 1B)
+ \f form feed (hex 0C)
+ \n linefeed (hex 0A)
+ \r carriage return (hex 0D) (but see below)
+ \t tab (hex 09)
+ \0dd character with octal code 0dd
+ \ddd character with octal code ddd, or back reference
+ \o{ddd..} character with octal code ddd..
+ \xhh character with hex code hh
+ \x{hhh..} character with hex code hhh..
+ \N{U+hhh..} character with Unicode hex code point hhh..
+
+ A description of how back references work is given later, following the
+ discussion of parenthesized groups.
+
+ By default, after \x that is not followed by {, one or two hexadecimal
+ digits are read (letters can be in upper or lower case). If the charac-
+ ter that follows \x is neither { nor a hexadecimal digit, an error oc-
+ curs. This is different from Perl's default behaviour, which generates
+ a NUL character, but is in line with the behaviour of Perl's 'strict'
+ mode in re.
+
+ Any number of hexadecimal digits may appear between \x{ and }. If a
+ character other than a hexadecimal digit appears between \x{ and }, or
+ if there is no terminating }, an error occurs.
+
+ Characters whose code points are less than 256 can be defined by either
+ of the two syntaxes for \x or by an octal sequence. There is no differ-
+ ence in the way they are handled. For example, \xdc is exactly the same
+ as \x{dc} or \334. However, using the braced versions does make such
+ sequences easier to read.
+
+ Support is available for some ECMAScript (aka JavaScript) escape se-
+ quences via two compile-time options. If PCRE2_ALT_BSUX is set, the se-
+ quence \x followed by { is not recognized. Only if \x is followed by
+ two hexadecimal digits is it recognized as a character escape. Other-
+ wise it is interpreted as a literal "x" character. In this mode, sup-
+ port for code points greater than 256 is provided by \u, which must be
+ followed by four hexadecimal digits; otherwise it is interpreted as a
+ literal "u" character.
+
+ PCRE2_EXTRA_ALT_BSUX has the same effect as PCRE2_ALT_BSUX and, in ad-
+ dition, \u{hhh..} is recognized as the character specified by hexadeci-
+ mal code point. There may be any number of hexadecimal digits, but un-
+ like other places that also use curly brackets, spaces are not allowed
+ and would result in the string being interpreted as a literal. This
+ syntax is from ECMAScript 6.
+
+ The \N{U+hhh..} escape sequence is recognized only when PCRE2 is oper-
+ ating in UTF mode. Perl also uses \N{name} to specify characters by
+ Unicode name; PCRE2 does not support this. Note that when \N is not
+ followed by an opening brace (curly bracket) it has an entirely differ-
+ ent meaning, matching any character that is not a newline.
+
+ There are some legacy applications where the escape sequence \r is ex-
+ pected to match a newline. If the PCRE2_EXTRA_ESCAPED_CR_IS_LF option
+ is set, \r in a pattern is converted to \n so that it matches a LF
+ (linefeed) instead of a CR (carriage return) character.
+
+ An error occurs if \c is not followed by a character whose ASCII code
+ point is in the range 32 to 126. The precise effect of \cx is as fol-
+ lows: if x is a lower case letter, it is converted to upper case. Then
+ bit 6 of the character (hex 40) is inverted. Thus \cA to \cZ become hex
+ 01 to hex 1A (A is 41, Z is 5A), but \c{ becomes hex 3B ({ is 7B), and
+ \c; becomes hex 7B (; is 3B). If the code unit following \c has a code
+ point less than 32 or greater than 126, a compile-time error occurs.
+
+ For differences in the way some escapes behave in EBCDIC environments,
+ see section "EBCDIC environments" below.
+
+ Octal escapes and back references
+
+ The escape \o must be followed by a sequence of octal digits, enclosed
+ in braces. An error occurs if this is not the case. This escape pro-
+ vides a way of specifying character code points as octal numbers
+ greater than 0777, and it also allows octal numbers and backreferences
+ to be unambiguously distinguished.
+
+ If braces are not used, after \0 up to two further octal digits are
+ read. However, if the PCRE2_EXTRA_NO_BS0 option is set, at least one
+ more octal digit must follow \0 (use \00 to generate a NUL character).
+ Make sure you supply two digits after the initial zero if the pattern
+ character that follows is itself an octal digit.
+
+ Inside a character class, when a backslash is followed by any octal
+ digit, up to three octal digits are read to generate a code point. Any
+ subsequent digits stand for themselves. The sequences \8 and \9 are
+ treated as the literal characters "8" and "9".
+
+ Outside a character class, Perl's handling of a backslash followed by a
+ digit other than 0 is complicated by ambiguity, and Perl has changed
+ over time, causing PCRE2 also to change. From PCRE2 release 10.45 there
+ is an option called PCRE2_EXTRA_PYTHON_OCTAL that causes PCRE2 to use
+ Python's unambiguous rules. The next two subsections describe the two
+ sets of rules.
+
+ For greater clarity and unambiguity, it is best to avoid following \ by
+ a digit greater than zero. Instead, use \o{...} or \x{...} to specify
+ numerical character code points, and \g{...} to specify backreferences.
+
+ Perl rules for non-class backslash 1-9
+
+ All the digits that follow the backslash are read as a decimal number.
+ If the number is less than 10, begins with the digit 8 or 9, or if
+ there are at least that many previous capture groups in the expression,
+ the entire sequence is taken as a back reference. Otherwise, up to
+ three octal digits are read to form a character code. For example:
+
+ \040 is another way of writing an ASCII space
+ \40 is the same, provided there are fewer than 40
+ previous capture groups
+ \7 is always a backreference
+ \11 might be a backreference, or another way of
+ writing a tab
+ \011 is always a tab
+ \0113 is a tab followed by the character "3"
+ \113 might be a backreference, otherwise the
+ character with octal code 113
+ \377 might be a backreference, otherwise
+ the value 255 (decimal)
+ \81 is always a backreference
+
+ Note that octal values of 100 or greater that are specified using this
+ syntax must not be introduced by a leading zero, because no more than
+ three octal digits are ever read.
+
+ Python rules for non_class backslash 1-9
+
+ If there are at least three octal digits after the backslash, exactly
+ three are read as an octal code point number, but the value must be no
+ greater than \377, even in modes where higher code point values are
+ supported. Any subsequent digits stand for themselves. If there are
+ fewer than three octal digits, the sequence is taken as a decimal back
+ reference. Thus, for example, \12 is always a back reference, indepen-
+ dent of how many captures there are in the pattern. An error is gener-
+ ated for a reference to a non-existent capturing group.
+
+ Constraints on character values
+
+ Characters that are specified using octal or hexadecimal numbers are
+ limited to certain values, as follows:
+
+ 8-bit non-UTF mode no greater than 0xff
+ 16-bit non-UTF mode no greater than 0xffff
+ 32-bit non-UTF mode no greater than 0xffffffff
+ All UTF modes no greater than 0x10ffff and a valid code point
+
+ Invalid Unicode code points are all those in the range 0xd800 to 0xdfff
+ (the so-called "surrogate" code points). The check for these can be
+ disabled by the caller of pcre2_compile() by setting the option
+ PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES. However, this is possible only in
+ UTF-8 and UTF-32 modes, because these values are not representable in
+ UTF-16.
+
+ Escape sequences in character classes
+
+ All the sequences that define a single character value can be used both
+ inside and outside character classes. In addition, inside a character
+ class, \b is interpreted as the backspace character (hex 08).
+
+ When not followed by an opening brace, \N is not allowed in a character
+ class. \B, \R, and \X are not special inside a character class. Like
+ other unrecognized alphabetic escape sequences, they cause an error.
+ Outside a character class, these sequences have different meanings.
+
+ Unsupported escape sequences
+
+ In Perl, the sequences \F, \l, \L, \u, and \U are recognized by its
+ string handler and used to modify the case of following characters. By
+ default, PCRE2 does not support these escape sequences in patterns.
+ However, if either of the PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX op-
+ tions is set, \U matches a "U" character, and \u can be used to define
+ a character by code point, as described above.
+
+ Absolute and relative backreferences
+
+ The sequence \g followed by a signed or unsigned number, optionally en-
+ closed in braces, is an absolute or relative backreference. A named
+ backreference can be coded as \g{name}. Backreferences are discussed
+ later, following the discussion of parenthesized groups.
+
+ Absolute and relative subroutine calls
+
+ For compatibility with Oniguruma, the non-Perl syntax \g followed by a
+ name or a number enclosed either in angle brackets or single quotes, is
+ an alternative syntax for referencing a capture group as a subroutine.
+ Details are discussed later. Note that \g{...} (Perl syntax) and
+ \g<...> (Oniguruma syntax) are not synonymous. The former is a backref-
+ erence; the latter is a subroutine call.
+
+ Generic character types
+
+ Another use of backslash is for specifying generic character types:
+
+ \d any decimal digit
+ \D any character that is not a decimal digit
+ \h any horizontal white space character
+ \H any character that is not a horizontal white space character
+ \N any character that is not a newline
+ \s any white space character
+ \S any character that is not a white space character
+ \v any vertical white space character
+ \V any character that is not a vertical white space character
+ \w any "word" character
+ \W any "non-word" character
+
+ The \N escape sequence has the same meaning as the "." metacharacter
+ when PCRE2_DOTALL is not set, but setting PCRE2_DOTALL does not change
+ the meaning of \N. Note that when \N is followed by an opening brace it
+ has a different meaning. See the section entitled "Non-printing charac-
+ ters" above for details. Perl also uses \N{name} to specify characters
+ by Unicode name; PCRE2 does not support this.
+
+ Each pair of lower and upper case escape sequences partitions the com-
+ plete set of characters into two disjoint sets. Any given character
+ matches one, and only one, of each pair. The sequences can appear both
+ inside and outside character classes. They each match one character of
+ the appropriate type. If the current matching point is at the end of
+ the subject string, all of them fail, because there is no character to
+ match.
+
+ The default \s characters are HT (9), LF (10), VT (11), FF (12), CR
+ (13), and space (32), which are defined as white space in the "C" lo-
+ cale. This list may vary if locale-specific matching is taking place.
+ For example, in some locales the "non-breaking space" character (\xA0)
+ is recognized as white space, and in others the VT character is not.
+
+ A "word" character is an underscore or any character that is a letter
+ or digit. By default, the definition of letters and digits is con-
+ trolled by PCRE2's low-valued character tables, and may vary if locale-
+ specific matching is taking place (see "Locale support" in the pcre2api
+ page). For example, in a French locale such as "fr_FR" in Unix-like
+ systems, or "french" in Windows, some character codes greater than 127
+ are used for accented letters, and these are then matched by \w. The
+ use of locales with Unicode is discouraged.
+
+ By default, characters whose code points are greater than 127 never
+ match \d, \s, or \w, and always match \D, \S, and \W, although this may
+ be different for characters in the range 128-255 when locale-specific
+ matching is happening. These escape sequences retain their original
+ meanings from before Unicode support was available, mainly for effi-
+ ciency reasons. If the PCRE2_UCP option is set, the behaviour is
+ changed so that Unicode properties are used to determine character
+ types, as follows:
+
+ \d any character that matches \p{Nd} (decimal digit)
+ \s any character that matches \p{Z} or \h or \v
+ \w any character that matches \p{L}, \p{N}, \p{Mn}, or \p{Pc}
+
+ The addition of \p{Mn} (non-spacing mark) and the replacement of an ex-
+ plicit test for underscore with a test for \p{Pc} (connector punctua-
+ tion) happened in PCRE2 release 10.43. This brings PCRE2 into line with
+ Perl.
+
+ The upper case escapes match the inverse sets of characters. Note that
+ \d matches only decimal digits, whereas \w matches any Unicode digit,
+ as well as other character categories. Note also that PCRE2_UCP affects
+ \b, and \B because they are defined in terms of \w and \W. Matching
+ these sequences is noticeably slower when PCRE2_UCP is set.
+
+ The effect of PCRE2_UCP on any one of these escape sequences can be
+ negated by the options PCRE2_EXTRA_ASCII_BSD, PCRE2_EXTRA_ASCII_BSS,
+ and PCRE2_EXTRA_ASCII_BSW, respectively. These options can be set and
+ reset within a pattern by means of an internal option setting (see be-
+ low).
+
+ The sequences \h, \H, \v, and \V, in contrast to the other sequences,
+ which match only ASCII characters by default, always match a specific
+ list of code points, whether or not PCRE2_UCP is set. The horizontal
+ space characters are:
+
+ U+0009 Horizontal tab (HT)
+ U+0020 Space
+ U+00A0 Non-break space
+ U+1680 Ogham space mark
+ U+180E Mongolian vowel separator
+ U+2000 En quad
+ U+2001 Em quad
+ U+2002 En space
+ U+2003 Em space
+ U+2004 Three-per-em space
+ U+2005 Four-per-em space
+ U+2006 Six-per-em space
+ U+2007 Figure space
+ U+2008 Punctuation space
+ U+2009 Thin space
+ U+200A Hair space
+ U+202F Narrow no-break space
+ U+205F Medium mathematical space
+ U+3000 Ideographic space
+
+ The vertical space characters are:
+
+ U+000A Linefeed (LF)
+ U+000B Vertical tab (VT)
+ U+000C Form feed (FF)
+ U+000D Carriage return (CR)
+ U+0085 Next line (NEL)
+ U+2028 Line separator
+ U+2029 Paragraph separator
+
+ In 8-bit, non-UTF-8 mode, only the characters with code points less
+ than 256 are relevant.
+
+ Newline sequences
+
+ Outside a character class, by default, the escape sequence \R matches
+ any Unicode newline sequence. In 8-bit non-UTF-8 mode \R is equivalent
+ to the following:
+
+ (?>\r\n|\n|\x0b|\f|\r|\x85)
+
+ This is an example of an "atomic group", details of which are given be-
+ low. This particular group matches either the two-character sequence
+ CR followed by LF, or one of the single characters LF (linefeed,
+ U+000A), VT (vertical tab, U+000B), FF (form feed, U+000C), CR (car-
+ riage return, U+000D), or NEL (next line, U+0085). Because this is an
+ atomic group, the two-character sequence is treated as a single unit
+ that cannot be split.
+
+ In other modes, two additional characters whose code points are greater
+ than 255 are added: LS (line separator, U+2028) and PS (paragraph sepa-
+ rator, U+2029). Unicode support is not needed for these characters to
+ be recognized.
+
+ It is possible to restrict \R to match only CR, LF, or CRLF (instead of
+ the complete set of Unicode line endings) by setting the option
+ PCRE2_BSR_ANYCRLF at compile time. (BSR is an abbreviation for "back-
+ slash R".) This can be made the default when PCRE2 is built; if this is
+ the case, the other behaviour can be requested via the PCRE2_BSR_UNI-
+ CODE option. It is also possible to specify these settings by starting
+ a pattern string with one of the following sequences:
+
+ (*BSR_ANYCRLF) CR, LF, or CRLF only
+ (*BSR_UNICODE) any Unicode newline sequence
+
+ These override the default and the options given to the compiling func-
+ tion. Note that these special settings, which are not Perl-compatible,
+ are recognized only at the very start of a pattern, and that they must
+ be in upper case. If more than one of them is present, the last one is
+ used. They can be combined with a change of newline convention; for ex-
+ ample, a pattern can start with:
+
+ (*ANY)(*BSR_ANYCRLF)
+
+ They can also be combined with the (*UTF) or (*UCP) special sequences.
+ Inside a character class, \R is treated as an unrecognized escape se-
+ quence, and causes an error.
+
+ Unicode character properties
+
+ When PCRE2 is built with Unicode support (the default), three addi-
+ tional escape sequences that match characters with specific properties
+ are available. They can be used in any mode, though in 8-bit and 16-bit
+ non-UTF modes these sequences are of course limited to testing charac-
+ ters whose code points are less than U+0100 or U+10000, respectively.
+ In 32-bit non-UTF mode, code points greater than 0x10ffff (the Unicode
+ limit) may be encountered. These are all treated as being in the Un-
+ known script and with an unassigned type.
+
+ Matching characters by Unicode property is not fast, because PCRE2 has
+ to do a multistage table lookup in order to find a character's prop-
+ erty. That is why the traditional escape sequences such as \d and \w do
+ not use Unicode properties in PCRE2 by default, though you can make
+ them do so by setting the PCRE2_UCP option or by starting the pattern
+ with (*UCP).
+
+ The extra escape sequences that provide property support are:
+
+ \p{xx} a character with the xx property
+ \P{xx} a character without the xx property
+ \X a Unicode extended grapheme cluster
+
+ For compatibility with Perl, negation can be specified by including a
+ circumflex between the opening brace and the property. For example,
+ \p{^Lu} is the same as \P{Lu}.
+
+ In accordance with Unicode's "loose matching" rules, ASCII white space
+ characters, hyphens, and underscores are ignored in the properties rep-
+ resented by xx above. As well as the space character, ASCII white space
+ can be tab, linefeed, vertical tab, formfeed, or carriage return.
+
+ Some properties are specified as a name only; others as a name and a
+ value, separated by a colon or an equals sign. The names and values
+ consist of ASCII letters and digits (with one Perl-specific exception,
+ see below). They are not case sensitive. Note, however, that the es-
+ capes themselves, \p and \P, are case sensitive. There are abbrevia-
+ tions for many names. The following examples are all equivalent:
+
+ \p{bidiclass=al}
+ \p{BC=al}
+ \p{ Bidi_Class : AL }
+ \p{ Bi-di class = Al }
+ \P{ ^ Bi-di class = Al }
+
+ There is support for Unicode script names, Unicode general category
+ properties, "Any", which matches any character (including newline),
+ Bidi_Class, a number of binary (yes/no) properties, and some special
+ PCRE2 properties (described below). Certain other Perl properties such
+ as "InMusicalSymbols" are not supported by PCRE2. Note that \P{Any}
+ does not match any characters, so always causes a match failure.
+
+ Script properties for \p and \P
+
+ There are three different syntax forms for matching a script. Each Uni-
+ code character has a basic script and, optionally, a list of other
+ scripts ("Script Extensions") with which it is commonly used. Using the
+ Adlam script as an example, \p{sc:Adlam} matches characters whose basic
+ script is Adlam, whereas \p{scx:Adlam} matches, in addition, characters
+ that have Adlam in their extensions list. The full names "script" and
+ "script extensions" for the property types are recognized and, as for
+ all property specifications, an equals sign is an alternative to the
+ colon. If a script name is given without a property type, for example,
+ \p{Adlam}, it is treated as \p{scx:Adlam}. Perl changed to this inter-
+ pretation at release 5.26 and PCRE2 changed at release 10.40.
+
+ Unassigned characters (and in non-UTF 32-bit mode, characters with code
+ points greater than 0x10FFFF) are assigned the "Unknown" script. Others
+ that are not part of an identified script are lumped together as "Com-
+ mon". The current list of recognized script names and their 4-character
+ abbreviations can be obtained by running this command:
+
+ pcre2test -LS
+
+
+ The general category property for \p and \P
+
+ Each character has exactly one Unicode general category property, spec-
+ ified by a two-letter abbreviation. If only one letter is specified
+ with \p or \P, it includes all the general category properties that
+ start with that letter. In this case, in the absence of negation, the
+ curly brackets in the escape sequence are optional; these two examples
+ have the same effect:
+
+ \p{L}
+ \pL
+
+ The following general category property codes are supported:
+
+ C Other
+ Cc Control
+ Cf Format
+ Cn Unassigned
+ Co Private use
+ Cs Surrogate
+
+ L Letter
+ Lc Cased letter
+ Ll Lower case letter
+ Lm Modifier letter
+ Lo Other letter
+ Lt Title case letter
+ Lu Upper case letter
+
+ M Mark
+ Mc Spacing mark
+ Me Enclosing mark
+ Mn Non-spacing mark
+
+ N Number
+ Nd Decimal number
+ Nl Letter number
+ No Other number
+
+ P Punctuation
+ Pc Connector punctuation
+ Pd Dash punctuation
+ Pe Close punctuation
+ Pf Final punctuation
+ Pi Initial punctuation
+ Po Other punctuation
+ Ps Open punctuation
+
+ S Symbol
+ Sc Currency symbol
+ Sk Modifier symbol
+ Sm Mathematical symbol
+ So Other symbol
+
+ Z Separator
+ Zl Line separator
+ Zp Paragraph separator
+ Zs Space separator
+
+ Perl originally used the name L& for the Lc property. This is still
+ supported by Perl, but discouraged. PCRE2 also still supports it. This
+ property matches any character that has the Lu, Ll, or Lt property, in
+ other words, any letter that is not classified as a modifier or
+ "other". From release 10.45 of PCRE2 the properties Lu, Ll, and Lt are
+ all treated as Lc when case-independent matching is set by the
+ PCRE2_CASELESS option or (?i) within the pattern. The other properties
+ are not affected by caseless matching.
+
+ The Cs (Surrogate) property applies only to characters whose code
+ points are in the range U+D800 to U+DFFF. These characters are no dif-
+ ferent to any other character when PCRE2 is not in UTF mode (using the
+ 16-bit or 32-bit library). However, they are not valid in Unicode
+ strings and so cannot be tested by PCRE2 in UTF mode, unless UTF valid-
+ ity checking has been turned off (see the discussion of
+ PCRE2_NO_UTF_CHECK in the pcre2api page).
+
+ The long synonyms for property names that Perl supports (such as
+ \p{Letter}) are not supported by PCRE2, nor is it permitted to prefix
+ any of these properties with "Is".
+
+ No character that is in the Unicode table has the Cn (unassigned) prop-
+ erty. Instead, this property is assumed for any code point that is not
+ in the Unicode table.
+
+ Binary (yes/no) properties for \p and \P
+
+ Unicode defines a number of binary properties, that is, properties
+ whose only values are true or false. You can obtain a list of those
+ that are recognized by \p and \P, along with their abbreviations, by
+ running this command:
+
+ pcre2test -LP
+
+
+ The Bidi_Class property for \p and \P
+
+ \p{Bidi_Class:} matches a character with the given class
+ \p{BC:} matches a character with the given class
+
+ The recognized classes are:
+
+ AL Arabic letter
+ AN Arabic number
+ B paragraph separator
+ BN boundary neutral
+ CS common separator
+ EN European number
+ ES European separator
+ ET European terminator
+ FSI first strong isolate
+ L left-to-right
+ LRE left-to-right embedding
+ LRI left-to-right isolate
+ LRO left-to-right override
+ NSM non-spacing mark
+ ON other neutral
+ PDF pop directional format
+ PDI pop directional isolate
+ R right-to-left
+ RLE right-to-left embedding
+ RLI right-to-left isolate
+ RLO right-to-left override
+ S segment separator
+ WS white space
+
+ As in all property specifications, an equals sign may be used instead
+ of a colon and the class names are case-insensitive. Only the short
+ names listed above are recognized; PCRE2 does not at present support
+ any long alternatives.
+
+ Extended grapheme clusters
+
+ The \X escape matches any number of Unicode characters that form an
+ "extended grapheme cluster", and treats the sequence as an atomic group
+ (see below). Unicode supports various kinds of composite character by
+ giving each character a grapheme breaking property, and having rules
+ that use these properties to define the boundaries of extended grapheme
+ clusters. The rules are defined in Unicode Standard Annex 29, "Unicode
+ Text Segmentation". Unicode 11.0.0 abandoned the use of some previous
+ properties that had been used for emojis. Instead it introduced vari-
+ ous emoji-specific properties. PCRE2 uses only the Extended Picto-
+ graphic property.
+
+ \X always matches at least one character. Then it decides whether to
+ add additional characters according to the following rules for ending a
+ cluster:
+
+ 1. End at the end of the subject string.
+
+ 2. Do not end between CR and LF; otherwise end after any control char-
+ acter.
+
+ 3. Do not break Hangul (a Korean script) syllable sequences. Hangul
+ characters are of five types: L, V, T, LV, and LVT. An L character may
+ be followed by an L, V, LV, or LVT character; an LV or V character may
+ be followed by a V or T character; an LVT or T character may be fol-
+ lowed only by a T character.
+
+ 4. Do not end before extending characters or spacing marks or the zero-
+ width joiner (ZWJ) character. Characters with the "mark" property al-
+ ways have the "extend" grapheme breaking property.
+
+ 5. Do not end after prepend characters.
+
+ 6. Do not end within emoji modifier sequences or emoji ZWJ (zero-width
+ joiner) sequences. An emoji ZWJ sequence consists of a character with
+ the Extended_Pictographic property, optionally followed by one or more
+ characters with the Extend property, followed by the ZWJ character,
+ followed by another Extended_Pictographic character.
+
+ 7. Do not break within emoji flag sequences. That is, do not break be-
+ tween regional indicator (RI) characters if there are an odd number of
+ RI characters before the break point.
+
+ 8. Otherwise, end the cluster.
+
+ PCRE2's additional properties
+
+ As well as the standard Unicode properties described above, PCRE2 sup-
+ ports four more that make it possible to convert traditional escape se-
+ quences such as \w and \s to use Unicode properties. PCRE2 uses these
+ non-standard, non-Perl properties internally when PCRE2_UCP is set.
+ However, they may also be used explicitly. These properties are:
+
+ Xan Any alphanumeric character
+ Xps Any POSIX space character
+ Xsp Any Perl space character
+ Xwd Any Perl "word" character
+
+ Xan matches characters that have either the L (letter) or the N (num-
+ ber) property. Xps matches the characters tab, linefeed, vertical tab,
+ form feed, or carriage return, and any other character that has the Z
+ (separator) property (this includes the space character). Xsp is the
+ same as Xps; in PCRE1 it used to exclude vertical tab, for Perl compat-
+ ibility, but Perl changed. Xwd matches the same characters as Xan, plus
+ those that match Mn (non-spacing mark) or Pc (connector punctuation,
+ which includes underscore).
+
+ There is another non-standard property, Xuc, which matches any charac-
+ ter that can be represented by a Universal Character Name in C++ and
+ other programming languages. These are the characters $, @, ` (grave
+ accent), and all characters with Unicode code points greater than or
+ equal to U+00A0, except for the surrogates U+D800 to U+DFFF. Note that
+ most base (ASCII) characters are excluded. (Universal Character Names
+ are of the form \uHHHH or \UHHHHHHHH where H is a hexadecimal digit.
+ Note that the Xuc property does not match these sequences but the char-
+ acters that they represent.)
+
+ Resetting the match start
+
+ In normal use, the escape sequence \K causes any previously matched
+ characters not to be included in the final matched sequence that is re-
+ turned. For example, the pattern:
+
+ foo\Kbar
+
+ matches "foobar", but reports that it has matched "bar". \K does not
+ interact with anchoring in any way. The pattern:
+
+ ^foo\Kbar
+
+ matches only when the subject begins with "foobar" (in single line
+ mode), though it again reports the matched string as "bar". This fea-
+ ture is similar to a lookbehind assertion (described below), but the
+ part of the pattern that precedes \K is not constrained to match a lim-
+ ited number of characters, as is required for a lookbehind assertion.
+ The use of \K does not interfere with the setting of captured sub-
+ strings. For example, when the pattern
+
+ (foo)\Kbar
+
+ matches "foobar", the first substring is still set to "foo".
+
+ From version 5.32.0 Perl forbids the use of \K in lookaround asser-
+ tions. From release 10.38 PCRE2 also forbids this by default. However,
+ the PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK option can be used when calling
+ pcre2_compile() to re-enable the previous behaviour. When this option
+ is set, \K is acted upon when it occurs inside positive assertions, but
+ is ignored in negative assertions. Note that when a pattern such as
+ (?=ab\K) matches, the reported start of the match can be greater than
+ the end of the match. Using \K in a lookbehind assertion at the start
+ of a pattern can also lead to odd effects. For example, consider this
+ pattern:
+
+ (?<=\Kfoo)bar
+
+ If the subject is "foobar", a call to pcre2_match() with a starting
+ offset of 3 succeeds and reports the matching string as "foobar", that
+ is, the start of the reported match is earlier than where the match
+ started.
+
+ Simple assertions
+
+ The final use of backslash is for certain simple assertions. An asser-
+ tion specifies a condition that has to be met at a particular point in
+ a match, without consuming any characters from the subject string. The
+ use of groups for more complicated assertions is described below. The
+ backslashed assertions are:
+
+ \b matches at a word boundary
+ \B matches when not at a word boundary
+ \A matches at the start of the subject
+ \Z matches at the end of the subject
+ also matches before a newline at the end of the subject
+ \z matches only at the end of the subject
+ \G matches at the first matching position in the subject
+
+ Inside a character class, \b has a different meaning; it matches the
+ backspace character. If any other of these assertions appears in a
+ character class, an "invalid escape sequence" error is generated.
+
+ A word boundary is a position in the subject string where the current
+ character and the previous character do not both match \w or \W (i.e.
+ one matches \w and the other matches \W), or the start or end of the
+ string if the first or last character matches \w, respectively. When
+ PCRE2 is built with Unicode support, the meanings of \w and \W can be
+ changed by setting the PCRE2_UCP option. When this is done, it also af-
+ fects \b and \B. Neither PCRE2 nor Perl has a separate "start of word"
+ or "end of word" metasequence. However, whatever follows \b normally
+ determines which it is. For example, the fragment \ba matches "a" at
+ the start of a word.
+
+ The \A, \Z, and \z assertions differ from the traditional circumflex
+ and dollar (described in the next section) in that they only ever match
+ at the very start and end of the subject string, whatever options are
+ set. Thus, they are independent of multiline mode. These three asser-
+ tions are not affected by the PCRE2_NOTBOL or PCRE2_NOTEOL options,
+ which affect only the behaviour of the circumflex and dollar metachar-
+ acters. However, if the startoffset argument of pcre2_match() is non-
+ zero, indicating that matching is to start at a point other than the
+ beginning of the subject, \A can never match. The difference between
+ \Z and \z is that \Z matches before a newline at the end of the string
+ as well as at the very end, whereas \z matches only at the end.
+
+ The \G assertion is true only when the current matching position is at
+ the start point of the matching process, as specified by the startoff-
+ set argument of pcre2_match(). It differs from \A when the value of
+ startoffset is non-zero. By calling pcre2_match() multiple times with
+ appropriate arguments, you can mimic Perl's /g option, and it is in
+ this kind of implementation where \G can be useful.
+
+ Note, however, that PCRE2's implementation of \G, being true at the
+ starting character of the matching process, is subtly different from
+ Perl's, which defines it as true at the end of the previous match. In
+ Perl, these can be different when the previously matched string was
+ empty. Because PCRE2 does just one match at a time, it cannot reproduce
+ this behaviour.
+
+ If all the alternatives of a pattern begin with \G, the expression is
+ anchored to the starting match position, and the "anchored" flag is set
+ in the compiled regular expression.
+
+
+CIRCUMFLEX AND DOLLAR
+
+ The circumflex and dollar metacharacters are zero-width assertions.
+ That is, they test for a particular condition being true without con-
+ suming any characters from the subject string. These two metacharacters
+ are concerned with matching the starts and ends of lines. If the new-
+ line convention is set so that only the two-character sequence CRLF is
+ recognized as a newline, isolated CR and LF characters are treated as
+ ordinary data characters, and are not recognized as newlines.
+
+ Outside a character class, in the default matching mode, the circumflex
+ character is an assertion that is true only if the current matching
+ point is at the start of the subject string. If the startoffset argu-
+ ment of pcre2_match() is non-zero, or if PCRE2_NOTBOL is set, circum-
+ flex can never match if the PCRE2_MULTILINE option is unset. Inside a
+ character class, circumflex has an entirely different meaning (see be-
+ low).
+
+ Circumflex need not be the first character of the pattern if a number
+ of alternatives are involved, but it should be the first thing in each
+ alternative in which it appears if the pattern is ever to match that
+ branch. If all possible alternatives start with a circumflex, that is,
+ if the pattern is constrained to match only at the start of the sub-
+ ject, it is said to be an "anchored" pattern. (There are also other
+ constructs that can cause a pattern to be anchored.)
+
+ The dollar character is an assertion that is true only if the current
+ matching point is at the end of the subject string, or immediately be-
+ fore a newline at the end of the string (by default), unless PCRE2_NO-
+ TEOL is set. Note, however, that it does not actually match the new-
+ line. Dollar need not be the last character of the pattern if a number
+ of alternatives are involved, but it should be the last item in any
+ branch in which it appears. Dollar has no special meaning in a charac-
+ ter class.
+
+ The meaning of dollar can be changed so that it matches only at the
+ very end of the string, by setting the PCRE2_DOLLAR_ENDONLY option at
+ compile time. This does not affect the \Z assertion.
+
+ The meanings of the circumflex and dollar metacharacters are changed if
+ the PCRE2_MULTILINE option is set. When this is the case, a dollar
+ character matches before any newlines in the string, as well as at the
+ very end, and a circumflex matches immediately after internal newlines
+ as well as at the start of the subject string. It does not match after
+ a newline that ends the string, for compatibility with Perl. However,
+ this can be changed by setting the PCRE2_ALT_CIRCUMFLEX option.
+
+ For example, the pattern /^abc$/ matches the subject string "def\nabc"
+ (where \n represents a newline) in multiline mode, but not otherwise.
+ Consequently, patterns that are anchored in single line mode because
+ all branches start with ^ are not anchored in multiline mode, and a
+ match for circumflex is possible when the startoffset argument of
+ pcre2_match() is non-zero. The PCRE2_DOLLAR_ENDONLY option is ignored
+ if PCRE2_MULTILINE is set.
+
+ When the newline convention (see "Newline conventions" below) recog-
+ nizes the two-character sequence CRLF as a newline, this is preferred,
+ even if the single characters CR and LF are also recognized as new-
+ lines. For example, if the newline convention is "any", a multiline
+ mode circumflex matches before "xyz" in the string "abc\r\nxyz" rather
+ than after CR, even though CR on its own is a valid newline. (It also
+ matches at the very start of the string, of course.)
+
+ Note that the sequences \A, \Z, and \z can be used to match the start
+ and end of the subject in both modes, and if all branches of a pattern
+ start with \A it is always anchored, whether or not PCRE2_MULTILINE is
+ set.
+
+
+FULL STOP (PERIOD, DOT) AND \N
+
+ Outside a character class, a dot in the pattern matches any one charac-
+ ter in the subject string except (by default) a character that signi-
+ fies the end of a line. One or more characters may be specified as line
+ terminators (see "Newline conventions" above).
+
+ Dot never matches a single line-ending character. When the two-charac-
+ ter sequence CRLF is the only line ending, dot does not match CR if it
+ is immediately followed by LF, but otherwise it matches all characters
+ (including isolated CRs and LFs). When ANYCRLF is selected for line
+ endings, no occurrences of CR of LF match dot. When all Unicode line
+ endings are being recognized, dot does not match CR or LF or any of the
+ other line ending characters.
+
+ The behaviour of dot with regard to newlines can be changed. If the
+ PCRE2_DOTALL option is set, a dot matches any one character, without
+ exception. If the two-character sequence CRLF is present in the sub-
+ ject string, it takes two dots to match it.
+
+ The handling of dot is entirely independent of the handling of circum-
+ flex and dollar, the only relationship being that they both involve
+ newlines. Dot has no special meaning in a character class.
+
+ The escape sequence \N when not followed by an opening brace behaves
+ like a dot, except that it is not affected by the PCRE2_DOTALL option.
+ In other words, it matches any character except one that signifies the
+ end of a line.
+
+ When \N is followed by an opening brace it has a different meaning. See
+ the section entitled "Non-printing characters" above for details. Perl
+ also uses \N{name} to specify characters by Unicode name; PCRE2 does
+ not support this.
+
+
+MATCHING A SINGLE CODE UNIT
+
+ Outside a character class, the escape sequence \C matches any one code
+ unit, whether or not a UTF mode is set. In the 8-bit library, one code
+ unit is one byte; in the 16-bit library it is a 16-bit unit; in the
+ 32-bit library it is a 32-bit unit. Unlike a dot, \C always matches
+ line-ending characters. The feature is provided in Perl in order to
+ match individual bytes in UTF-8 mode, but it is unclear how it can use-
+ fully be used.
+
+ Because \C breaks up characters into individual code units, matching
+ one unit with \C in UTF-8 or UTF-16 mode means that the rest of the
+ string may start with a malformed UTF character. This has undefined re-
+ sults, because PCRE2 assumes that it is matching character by character
+ in a valid UTF string (by default it checks the subject string's valid-
+ ity at the start of processing unless the PCRE2_NO_UTF_CHECK or
+ PCRE2_MATCH_INVALID_UTF option is used).
+
+ An application can lock out the use of \C by setting the
+ PCRE2_NEVER_BACKSLASH_C option when compiling a pattern. It is also
+ possible to build PCRE2 with the use of \C permanently disabled.
+
+ PCRE2 does not allow \C to appear in lookbehind assertions (described
+ below) in UTF-8 or UTF-16 modes, because this would make it impossible
+ to calculate the length of the lookbehind. Neither the alternative
+ matching function pcre2_dfa_match() nor the JIT optimizer support \C in
+ these UTF modes. The former gives a match-time error; the latter fails
+ to optimize and so the match is always run using the interpreter.
+
+ In the 32-bit library, however, \C is always supported (when not ex-
+ plicitly locked out) because it always matches a single code unit,
+ whether or not UTF-32 is specified.
+
+ In general, the \C escape sequence is best avoided. However, one way of
+ using it that avoids the problem of malformed UTF-8 or UTF-16 charac-
+ ters is to use a lookahead to check the length of the next character,
+ as in this pattern, which could be used with a UTF-8 string (ignore
+ white space and line breaks):
+
+ (?| (?=[\x00-\x7f])(\C) |
+ (?=[\x80-\x{7ff}])(\C)(\C) |
+ (?=[\x{800}-\x{ffff}])(\C)(\C)(\C) |
+ (?=[\x{10000}-\x{1fffff}])(\C)(\C)(\C)(\C))
+
+ In this example, a group that starts with (?| resets the capturing
+ parentheses numbers in each alternative (see "Duplicate Group Numbers"
+ below). The assertions at the start of each branch check the next UTF-8
+ character for values whose encoding uses 1, 2, 3, or 4 bytes, respec-
+ tively. The character's individual bytes are then captured by the ap-
+ propriate number of \C groups.
+
+
+SQUARE BRACKETS AND CHARACTER CLASSES
+
+ An opening square bracket introduces a character class, terminated by a
+ closing square bracket. A closing square bracket on its own is not spe-
+ cial by default. If a closing square bracket is required as a member
+ of the class, it should be the first data character in the class (after
+ an initial circumflex, if present) or escaped with a backslash. This
+ means that, by default, an empty class cannot be defined. However, if
+ the PCRE2_ALLOW_EMPTY_CLASS option is set, a closing square bracket at
+ the start does end the (empty) class.
+
+ A character class matches a single character in the subject. A matched
+ character must be in the set of characters defined by the class, unless
+ the first character in the class definition is a circumflex, in which
+ case the subject character must not be in the set defined by the class.
+ If a circumflex is actually required as a member of the class, ensure
+ it is not the first character, or escape it with a backslash.
+
+ For example, the character class [aeiou] matches any lower case English
+ vowel, whereas [^aeiou] matches all other characters. Note that a cir-
+ cumflex is just a convenient notation for specifying the characters
+ that are in the class by enumerating those that are not. A class that
+ starts with a circumflex is not an assertion; it still consumes a char-
+ acter from the subject string, and therefore it fails to match if the
+ current pointer is at the end of the string.
+
+ Characters in a class may be specified by their code points using \o,
+ \x, or \N{U+hh..} in the usual way. When caseless matching is set, any
+ letters in a class represent both their upper case and lower case ver-
+ sions, so for example, a caseless [aeiou] matches "A" as well as "a",
+ and a caseless [^aeiou] does not match "A", whereas a caseful version
+ would. Note that there are two ASCII characters, K and S, that, in ad-
+ dition to their lower case ASCII equivalents, are case-equivalent with
+ Unicode U+212A (Kelvin sign) and U+017F (long S) respectively when ei-
+ ther PCRE2_UTF or PCRE2_UCP is set. If you do not want these ASCII/non-
+ ASCII case equivalences, you can suppress them by setting PCRE2_EX-
+ TRA_CASELESS_RESTRICT, either as an option in a compile context, or by
+ including (*CASELESS_RESTRICT) or (?r) within a pattern.
+
+ Characters that might indicate line breaks are never treated in any
+ special way when matching character classes, whatever line-ending se-
+ quence is in use, and whatever setting of the PCRE2_DOTALL and
+ PCRE2_MULTILINE options is used. A class such as [^a] always matches
+ one of these characters.
+
+ The generic character type escape sequences \d, \D, \h, \H, \p, \P, \s,
+ \S, \v, \V, \w, and \W may appear in a character class, and add the
+ characters that they match to the class. For example, [\dABCDEF]
+ matches any hexadecimal digit. In UTF modes, the PCRE2_UCP option af-
+ fects the meanings of \d, \s, \w and their upper case partners, just as
+ it does when they appear outside a character class, as described in the
+ section entitled "Generic character types" above. The escape sequence
+ \b has a different meaning inside a character class; it matches the
+ backspace character. The sequences \B, \R, and \X are not special in-
+ side a character class. Like any other unrecognized escape sequences,
+ they cause an error. The same is true for \N when not followed by an
+ opening brace.
+
+ The minus (hyphen) character can be used to specify a range of charac-
+ ters in a character class. For example, [d-m] matches any letter be-
+ tween d and m, inclusive. If a minus character is required in a class,
+ it must be escaped with a backslash or appear in a position where it
+ cannot be interpreted as indicating a range, typically as the first or
+ last character in the class, or immediately after a range. For example,
+ [b-d-z] matches letters in the range b to d, a hyphen character, or z.
+
+ There is some special treatment for alphabetic ranges in EBCDIC envi-
+ ronments; see the section "EBCDIC environments" below.
+
+ Perl treats a hyphen as a literal if it appears before or after a POSIX
+ class (see below) or before or after a character type escape such as \d
+ or \H. However, unless the hyphen is the last character in the class,
+ Perl outputs a warning in its warning mode, as this is most likely a
+ user error. As PCRE2 has no facility for warning, an error is given in
+ these cases.
+
+ It is not possible to have the literal character "]" as the end charac-
+ ter of a range. A pattern such as [W-]46] is interpreted as a class of
+ two characters ("W" and "-") followed by a literal string "46]", so it
+ would match "W46]" or "-46]". However, if the "]" is escaped with a
+ backslash it is interpreted as the end of a range, so [W-\]46] is in-
+ terpreted as a class containing a range and two other characters. The
+ octal or hexadecimal representation of "]" can also be used to end a
+ range.
+
+ Ranges normally include all code points between the start and end char-
+ acters, inclusive. They can also be used for code points specified nu-
+ merically, for example [\000-\037]. Ranges can include any characters
+ that are valid for the current mode. In any UTF mode, the so-called
+ "surrogate" characters (those whose code points lie between 0xd800 and
+ 0xdfff inclusive) may not be specified explicitly by default (the
+ PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES option disables this check). How-
+ ever, ranges such as [\x{d7ff}-\x{e000}], which include the surrogates,
+ are always permitted.
+
+ If a range that includes letters is used when caseless matching is set,
+ it matches the letters in either case. For example, [W-c] is equivalent
+ to [][\\^_`wxyzabc], matched caselessly, and in a non-UTF mode, if
+ character tables for a French locale are in use, [\xc8-\xcb] matches
+ accented E characters in both cases.
+
+ A circumflex can conveniently be used with the upper case character
+ types to specify a more restricted set of characters than the matching
+ lower case type. For example, the class [^\W_] matches any letter or
+ digit, but not underscore, whereas [\w] includes underscore. A positive
+ character class should be read as "something OR something OR ..." and a
+ negative class as "NOT something AND NOT something AND NOT ...".
+
+ The metacharacters that are recognized in character classes are back-
+ slash, hyphen (when it can be interpreted as specifying a range), cir-
+ cumflex (only at the start), and the terminating closing square
+ bracket. An opening square bracket is also special when it can be in-
+ terpreted as introducing a POSIX class (see "Posix character classes"
+ below), or a special compatibility feature (see "Compatibility feature
+ for word boundaries" below. Escaping any non-alphanumeric character in
+ a class turns it into a literal, whether or not it would otherwise be a
+ metacharacter.
+
+
+PERL EXTENDED CHARACTER CLASSES
+
+ From release 10.45 PCRE2 supports Perl's (?[...]) extended character
+ class syntax. This can be used to perform set operations such as inter-
+ section on character classes.
+
+ The syntax permitted within (?[...]) is quite different to ordinary
+ character classes. Inside the extended class, there is an expression
+ syntax consisting of "atoms", operators, and ordinary parentheses "()"
+ used for grouping. Such classes always have the Perl /xx modifier
+ (PCRE2 option PCRE2_EXTENDED_MORE) turned on within them. This means
+ that literal space and tab characters are ignored everywhere in the
+ class.
+
+ The allowed atoms are individual characters specified by escape se-
+ quences such as \n or \x{123}, character types such as \d, POSIX
+ classes such as [:alpha:], and nested ordinary (non-extended) character
+ classes. For example, in (?[\d & [...]]) the nested class [...] follows
+ the usual rules for ordinary character classes, in which parentheses
+ are not metacharacters, and character literals and ranges are permit-
+ ted.
+
+ Character literals and ranges may not appear outside a nested ordinary
+ character class because they are not atoms in the extended syntax. The
+ extended syntax does not introduce any additional escape sequences, so
+ (?[\y]) is an unknown escape, as it would be in [\y].
+
+ In the extended syntax, ^ does not negate a class (except within an or-
+ dinary class nested inside an extended class); it is instead a binary
+ operator.
+
+ The binary operators are "&" (intersection), "|" or "+" (union), "-"
+ (subtraction) and "^" (symmetric difference). These are left-associa-
+ tive and "&" has higher (tighter) precedence, while the others have
+ equal lower precedence. The one prefix unary operator is "!" (comple-
+ ment), with highest precedence.
+
+
+UTS#18 EXTENDED CHARACTER CLASSES
+
+ The PCRE2_ALT_EXTENDED_CLASS option enables an alternative to Perl's
+ (?[...]) syntax, allowing instead extended class behaviour inside or-
+ dinary [...] character classes. This altered syntax for [...] classes
+ is loosely described by the Unicode standard UTS#18. The PCRE2_ALT_EX-
+ TENDED_CLASS option does not prevent use of (?[...]) classes; it just
+ changes the meaning of all [...] classes that are not nested inside a
+ Perl (?[...]) class.
+
+ Firstly, in ordinary Perl [...] syntax, an expression such as "[a[]" is
+ a character class with two literal characters "a" and "[", but in
+ UTS#18 extended classes the "[" character becomes an additional
+ metacharacter within classes, denoting the start of a nested class, so
+ a literal "[" must be escaped as "\[".
+
+ Secondly, within the UTS#18 extended syntax, there are operators "||",
+ "&&", "--" and "~~" which denote character class union, intersection,
+ subtraction, and symmetric difference respectively. In standard Perl
+ syntax, these would simply be needlessly-repeated literals (except for
+ "--" which could be the start or end of a range). In UTS#18 extended
+ classes these operators can be used in constructs such as [\p{L}--[QW]]
+ for "Unicode letters, other than Q and W". A literal "-" at the start
+ or end of a range must be escaped, so while "[--1]" in Perl syntax is
+ the range from hyphen to "1", it must be escaped as "[\--1]" in UTS#18
+ extended classes.
+
+ Unlike Perl's (?[...]) extended classes, the PCRE2_EXTENDED_MORE option
+ to ignore space and tab characters is not automatically enabled for
+ UTS#18 extended classes, but it is honoured if set.
+
+ Extended UTS#18 classes can be nested, and nested classes are them-
+ selves extended classes (unlike Perl, where nested classes must be sim-
+ ple classes). For example, [\p{L}&&[\p{Thai}||\p{Greek}]] matches any
+ letter that is in the Thai or Greek scripts. Note that this means that
+ no special grouping characters (such as the parentheses used in Perl's
+ (?[...]) class syntax) are needed.
+
+ Individual class items (literal characters, literal ranges, properties
+ such as \d or \p{...}, and nested classes) can be combined by juxtapo-
+ sition or by an operator. Juxtaposition is the implicit union operator,
+ and binds more tightly than any explicit operator. Thus a sequence of
+ literals and/or ranges behaves as if it is enclosed in square brackets.
+ For example, [A-Z0-9&&[^E8]] is the same as [[A-Z0-9]&&[^E8]], which
+ matches any upper case alphanumeric character except "E" or "8".
+
+ Precedence between the explicit operators is not defined, so mixing op-
+ erators is a syntax error. For example, [A&&B--C] is an error, but
+ [A&&[B--C]] is valid.
+
+ This is an emerging syntax which is being adopted gradually across the
+ regex ecosystem: for example JavaScript adopted the "/v" flag in EC-
+ MAScript 2024; Python's "re" module reserves the syntax for future use
+ with a FutureWarning for unescaped use of "[" as a literal within char-
+ acter classes. Due to UTS#18 providing insufficient guidance, engines
+ interpret the syntax differently. Rust's "regex" crate and Python's
+ "regex" PyPi module both implement UTS#18 extended classes, but with
+ slight incompatibilities ([A||B&&C] is parsed as [A||[B&&C]] in
+ Python's "regex" but as [[A||B]&&C] in Rust's "regex").
+
+ PCRE2's syntax adds syntax restrictions similar to ECMASCript's /v
+ flag, so that all the UTS#18 extended classes accepted as valid by
+ PCRE2 have the property that they are interpreted either with the same
+ behaviour, or as invalid, by all other major engines. Please file an
+ issue if you are aware of cross-engine differences in behaviour between
+ PCRE2 and another major engine.
+
+
+POSIX CHARACTER CLASSES
+
+ Perl supports the POSIX notation for character classes. This uses names
+ enclosed by [: and :] within the enclosing square brackets. PCRE2 also
+ supports this notation, in both ordinary and extended classes. For ex-
+ ample,
+
+ [01[:alpha:]%]
+
+ matches "0", "1", any alphabetic character, or "%". The supported class
+ names are:
+
+ alnum letters and digits
+ alpha letters
+ ascii character codes 0 - 127
+ blank space or tab only
+ cntrl control characters
+ digit decimal digits (same as \d)
+ graph printing characters, excluding space
+ lower lower case letters
+ print printing characters, including space
+ punct printing characters, excluding letters and digits and space
+ space white space (the same as \s from PCRE2 8.34)
+ upper upper case letters
+ word "word" characters (same as \w)
+ xdigit hexadecimal digits
+
+ The default "space" characters are HT (9), LF (10), VT (11), FF (12),
+ CR (13), and space (32). If locale-specific matching is taking place,
+ the list of space characters may be different; there may be fewer or
+ more of them. "Space" and \s match the same set of characters, as do
+ "word" and \w.
+
+ The name "word" is a Perl extension, and "blank" is a GNU extension
+ from Perl 5.8. Another Perl extension is negation, which is indicated
+ by a ^ character after the colon. For example,
+
+ [12[:^digit:]]
+
+ matches "1", "2", or any non-digit. PCRE2 (and Perl) also recognize the
+ POSIX syntax [.ch.] and [=ch=] where "ch" is a "collating element", but
+ these are not supported, and an error is given if they are encountered.
+
+ By default, characters with values greater than 127 do not match any of
+ the POSIX character classes, although this may be different for charac-
+ ters in the range 128-255 when locale-specific matching is happening.
+ However, in UCP mode, unless certain options are set (see below), some
+ of the classes are changed so that Unicode character properties are
+ used. This is achieved by replacing POSIX classes with other sequences,
+ as follows:
+
+ [:alnum:] becomes \p{Xan}
+ [:alpha:] becomes \p{L}
+ [:blank:] becomes \h
+ [:cntrl:] becomes \p{Cc}
+ [:digit:] becomes \p{Nd}
+ [:lower:] becomes \p{Ll}
+ [:space:] becomes \p{Xps}
+ [:upper:] becomes \p{Lu}
+ [:word:] becomes \p{Xwd}
+
+ Negated versions, such as [:^alpha:] use \P instead of \p. Four other
+ POSIX classes are handled specially in UCP mode:
+
+ [:graph:] This matches characters that have glyphs that mark the page
+ when printed. In Unicode property terms, it matches all char-
+ acters with the L, M, N, P, S, or Cf properties, except for:
+
+ U+061C Arabic Letter Mark
+ U+180E Mongolian Vowel Separator
+ U+2066 - U+2069 Various "isolate"s
+
+
+ [:print:] This matches the same characters as [:graph:] plus space
+ characters that are not controls, that is, characters with
+ the Zs property.
+
+ [:punct:] This matches all characters that have the Unicode P (punctua-
+ tion) property, plus those characters with code points less
+ than 256 that have the S (Symbol) property.
+
+ [:xdigit:]
+ In addition to the ASCII hexadecimal digits, this also
+ matches the "fullwidth" versions of those characters, whose
+ Unicode code points start at U+FF10. This is a change that
+ was made in PCRE2 release 10.43 for Perl compatibility.
+
+ The other POSIX classes are unchanged by PCRE2_UCP, and match only
+ characters with code points less than 256.
+
+ There are two options that can be used to restrict the POSIX classes to
+ ASCII characters when PCRE2_UCP is set. The option PCRE2_EX-
+ TRA_ASCII_DIGIT affects just [:digit:] and [:xdigit:]. Within a pat-
+ tern, this can be set and unset by (?aT) and (?-aT). The PCRE2_EX-
+ TRA_ASCII_POSIX option disables UCP processing for all POSIX classes,
+ including [:digit:] and [:xdigit:]. Within a pattern, (?aP) and (?-aP)
+ set and unset both these options for consistency.
+
+
+COMPATIBILITY FEATURE FOR WORD BOUNDARIES
+
+ In the POSIX.2 compliant library that was included in 4.4BSD Unix, the
+ ugly syntax [[:<:]] and [[:>:]] is used for matching "start of word"
+ and "end of word". PCRE2 treats these items as follows:
+
+ [[:<:]] is converted to \b(?=\w)
+ [[:>:]] is converted to \b(?<=\w)
+
+ Only these exact character sequences are recognized. A sequence such as
+ [a[:<:]b] provokes error for an unrecognized POSIX class name. This
+ support is not compatible with Perl. It is provided to help migrations
+ from other environments, and is best not used in any new patterns. Note
+ that \b matches at the start and the end of a word (see "Simple asser-
+ tions" above), and in a Perl-style pattern the preceding or following
+ character normally shows which is wanted, without the need for the as-
+ sertions that are used above in order to give exactly the POSIX behav-
+ iour. Note also that the PCRE2_UCP option changes the meaning of \w
+ (and therefore \b) by default, so it also affects these POSIX se-
+ quences.
+
+
+VERTICAL BAR
+
+ Vertical bar characters are used to separate alternative patterns. For
+ example, the pattern
+
+ gilbert|sullivan
+
+ matches either "gilbert" or "sullivan". Any number of alternatives may
+ appear, and an empty alternative is permitted (matching the empty
+ string). The matching process tries each alternative in turn, from left
+ to right, and the first one that succeeds is used. If the alternatives
+ are within a group (defined below), "succeeds" means matching the rest
+ of the main pattern as well as the alternative in the group.
+
+
+INTERNAL OPTION SETTING
+
+ The settings of several options can be changed within a pattern by a
+ sequence of letters enclosed between "(?" and ")". The following are
+ Perl-compatible, and are described in detail in the pcre2api documenta-
+ tion. The option letters are:
+
+ i for PCRE2_CASELESS
+ m for PCRE2_MULTILINE
+ n for PCRE2_NO_AUTO_CAPTURE
+ s for PCRE2_DOTALL
+ x for PCRE2_EXTENDED
+ xx for PCRE2_EXTENDED_MORE
+
+ For example, (?im) sets caseless, multiline matching. It is also possi-
+ ble to unset these options by preceding the relevant letters with a hy-
+ phen, for example (?-im). The two "extended" options are not indepen-
+ dent; unsetting either one cancels the effects of both of them.
+
+ A combined setting and unsetting such as (?im-sx), which sets
+ PCRE2_CASELESS and PCRE2_MULTILINE while unsetting PCRE2_DOTALL and
+ PCRE2_EXTENDED, is also permitted. Only one hyphen may appear in the
+ options string. If a letter appears both before and after the hyphen,
+ the option is unset. An empty options setting "(?)" is allowed. Need-
+ less to say, it has no effect.
+
+ If the first character following (? is a circumflex, it causes all of
+ the above options to be unset. Letters may follow the circumflex to
+ cause some options to be re-instated, but a hyphen may not appear.
+
+ Some PCRE2-specific options can be changed by the same mechanism using
+ these pairs or individual letters:
+
+ aD for PCRE2_EXTRA_ASCII_BSD
+ aS for PCRE2_EXTRA_ASCII_BSS
+ aW for PCRE2_EXTRA_ASCII_BSW
+ aP for PCRE2_EXTRA_ASCII_POSIX and PCRE2_EXTRA_ASCII_DIGIT
+ aT for PCRE2_EXTRA_ASCII_DIGIT
+ r for PCRE2_EXTRA_CASELESS_RESTRICT
+ J for PCRE2_DUPNAMES
+ U for PCRE2_UNGREEDY
+
+ However, except for 'r', these are not unset by (?^), which is equiva-
+ lent to (?-imnrsx). If 'a' is not followed by any of the upper case
+ letters shown above, it sets (or unsets) all the ASCII options.
+
+ PCRE2_EXTRA_ASCII_DIGIT has no additional effect when PCRE2_EX-
+ TRA_ASCII_POSIX is set, but including it in (?aP) means that (?-aP)
+ suppresses all ASCII restrictions for POSIX classes.
+
+ When one of these option changes occurs at top level (that is, not in-
+ side group parentheses), the change applies until a subsequent change,
+ or the end of the pattern. An option change within a group (see below
+ for a description of groups) affects only that part of the group that
+ follows it. At the end of the group these options are reset to the
+ state they were before the group. For example,
+
+ (a(?i)b)c
+
+ matches abc and aBc and no other strings (assuming PCRE2_CASELESS is
+ not set externally). Any changes made in one alternative do carry on
+ into subsequent branches within the same group. For example,
+
+ (a(?i)b|c)
+
+ matches "ab", "aB", "c", and "C", even though when matching "C" the
+ first branch is abandoned before the option setting. This is because
+ the effects of option settings happen at compile time. There would be
+ some very weird behaviour otherwise.
+
+ As a convenient shorthand, if any option settings are required at the
+ start of a non-capturing group (see the next section), the option let-
+ ters may appear between the "?" and the ":". Thus the two patterns
+
+ (?i:saturday|sunday)
+ (?:(?i)saturday|sunday)
+
+ match exactly the same set of strings.
+
+ Note: There are other PCRE2-specific options, applying to the whole
+ pattern, which can be set by the application when the compiling func-
+ tion is called. In addition, the pattern can contain special leading
+ sequences such as (*CRLF) to override what the application has set or
+ what has been defaulted. Details are given in the section entitled
+ "Newline sequences" above. There are also the (*UTF) and (*UCP) leading
+ sequences that can be used to set UTF and Unicode property modes; they
+ are equivalent to setting the PCRE2_UTF and PCRE2_UCP options, respec-
+ tively. However, the application can set the PCRE2_NEVER_UTF or
+ PCRE2_NEVER_UCP options, which lock out the use of the (*UTF) and
+ (*UCP) sequences.
+
+
+GROUPS
+
+ Groups are delimited by parentheses (round brackets), which can be
+ nested. Turning part of a pattern into a group does two things:
+
+ 1. It localizes a set of alternatives. For example, the pattern
+
+ cat(aract|erpillar|)
+
+ matches "cataract", "caterpillar", or "cat". Without the parentheses,
+ it would match "cataract", "erpillar" or an empty string.
+
+ 2. It creates a "capture group". This means that, when the whole pat-
+ tern matches, the portion of the subject string that matched the group
+ is passed back to the caller, separately from the portion that matched
+ the whole pattern. (This applies only to the traditional matching
+ function; the DFA matching function does not support capturing.)
+
+ Opening parentheses are counted from left to right (starting from 1) to
+ obtain numbers for capture groups. For example, if the string "the red
+ king" is matched against the pattern
+
+ the ((red|white) (king|queen))
+
+ the captured substrings are "red king", "red", and "king", and are num-
+ bered 1, 2, and 3, respectively.
+
+ The fact that plain parentheses fulfil two functions is not always
+ helpful. There are often times when grouping is required without cap-
+ turing. If an opening parenthesis is followed by a question mark and a
+ colon, the group does not do any capturing, and is not counted when
+ computing the number of any subsequent capture groups. For example, if
+ the string "the white queen" is matched against the pattern
+
+ the ((?:red|white) (king|queen))
+
+ the captured substrings are "white queen" and "queen", and are numbered
+ 1 and 2. The maximum number of capture groups is 65535.
+
+ As a convenient shorthand, if any option settings are required at the
+ start of a non-capturing group, the option letters may appear between
+ the "?" and the ":". Thus the two patterns
+
+ (?i:saturday|sunday)
+ (?:(?i)saturday|sunday)
+
+ match exactly the same set of strings. Because alternative branches are
+ tried from left to right, and options are not reset until the end of
+ the group is reached, an option setting in one branch does affect sub-
+ sequent branches, so the above patterns match "SUNDAY" as well as "Sat-
+ urday".
+
+
+DUPLICATE GROUP NUMBERS
+
+ Perl 5.10 introduced a feature whereby each alternative in a group uses
+ the same numbers for its capturing parentheses. Such a group starts
+ with (?| and is itself a non-capturing group. For example, consider
+ this pattern:
+
+ (?|(Sat)ur|(Sun))day
+
+ Because the two alternatives are inside a (?| group, both sets of cap-
+ turing parentheses are numbered one. Thus, when the pattern matches,
+ you can look at captured substring number one, whichever alternative
+ matched. This construct is useful when you want to capture part, but
+ not all, of one of a number of alternatives. Inside a (?| group, paren-
+ theses are numbered as usual, but the number is reset at the start of
+ each branch. The numbers of any capturing parentheses that follow the
+ whole group start after the highest number used in any branch. The fol-
+ lowing example is taken from the Perl documentation. The numbers under-
+ neath show in which buffer the captured content will be stored.
+
+ # before ---------------branch-reset----------- after
+ / ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x
+ # 1 2 2 3 2 3 4
+
+ A backreference to a capture group uses the most recent value that is
+ set for the group. The following pattern matches "abcabc" or "defdef":
+
+ /(?|(abc)|(def))\1/
+
+ In contrast, a subroutine call to a capture group always refers to the
+ first one in the pattern with the given number. The following pattern
+ matches "abcabc" or "defabc":
+
+ /(?|(abc)|(def))(?1)/
+
+ A relative reference such as (?-1) is no different: it is just a conve-
+ nient way of computing an absolute group number.
+
+ If a condition test for a group's having matched refers to a non-unique
+ number, the test is true if any group with that number has matched.
+
+ An alternative approach to using this "branch reset" feature is to use
+ duplicate named groups, as described in the next section.
+
+
+NAMED CAPTURE GROUPS
+
+ Identifying capture groups by number is simple, but it can be very hard
+ to keep track of the numbers in complicated patterns. Furthermore, if
+ an expression is modified, the numbers may change. To help with this
+ difficulty, PCRE2 supports the naming of capture groups. This feature
+ was not added to Perl until release 5.10. Python had the feature ear-
+ lier, and PCRE1 introduced it at release 4.0, using the Python syntax.
+ PCRE2 supports both the Perl and the Python syntax.
+
+ In PCRE2, a capture group can be named in one of three ways:
+ (?...) or (?'name'...) as in Perl, or (?P...) as in Python.
+ Names may be up to 128 code units long. When PCRE2_UTF is not set, they
+ may contain only ASCII alphanumeric characters and underscores, but
+ must start with a non-digit. When PCRE2_UTF is set, the syntax of group
+ names is extended to allow any Unicode letter or Unicode decimal digit.
+ In other words, group names must match one of these patterns:
+
+ ^[_A-Za-z][_A-Za-z0-9]*\z when PCRE2_UTF is not set
+ ^[_\p{L}][_\p{L}\p{Nd}]*\z when PCRE2_UTF is set
+
+ References to capture groups from other parts of the pattern, such as
+ backreferences, recursion, and conditions, can all be made by name as
+ well as by number.
+
+ Named capture groups are allocated numbers as well as names, exactly as
+ if the names were not present. In both PCRE2 and Perl, capture groups
+ are primarily identified by numbers; any names are just aliases for
+ these numbers. The PCRE2 API provides function calls for extracting the
+ complete name-to-number translation table from a compiled pattern, as
+ well as convenience functions for extracting captured substrings by
+ name.
+
+ Warning: When more than one capture group has the same number, as de-
+ scribed in the previous section, a name given to one of them applies to
+ all of them. Perl allows identically numbered groups to have different
+ names. Consider this pattern, where there are two capture groups, both
+ numbered 1:
+
+ (?|(?aa)|(?bb))
+
+ Perl allows this, with both names AA and BB as aliases of group 1.
+ Thus, after a successful match, both names yield the same value (either
+ "aa" or "bb").
+
+ In an attempt to reduce confusion, PCRE2 does not allow the same group
+ number to be associated with more than one name. The example above pro-
+ vokes a compile-time error. However, there is still scope for confu-
+ sion. Consider this pattern:
+
+ (?|(?aa)|(bb))
+
+ Although the second group number 1 is not explicitly named, the name AA
+ is still an alias for any group 1. Whether the pattern matches "aa" or
+ "bb", a reference by name to group AA yields the matched string.
+
+ By default, a name must be unique within a pattern, except that dupli-
+ cate names are permitted for groups with the same number, for example:
+
+ (?|(?aa)|(?bb))
+
+ The duplicate name constraint can be disabled by setting the PCRE2_DUP-
+ NAMES option at compile time, or by the use of (?J) within the pattern,
+ as described in the section entitled "Internal Option Setting" above.
+
+ Duplicate names can be useful for patterns where only one instance of
+ the named capture group can match. Suppose you want to match the name
+ of a weekday, either as a 3-letter abbreviation or as the full name,
+ and in both cases you want to extract the abbreviation. This pattern
+ (ignoring the line breaks) does the job:
+
+ (?J)
+ (?Mon|Fri|Sun)(?:day)?|
+ (?Tue)(?:sday)?|
+ (?Wed)(?:nesday)?|
+ (?Thu)(?:rsday)?|
+ (?Sat)(?:urday)?
+
+ There are five capture groups, but only one is ever set after a match.
+ The convenience functions for extracting the data by name returns the
+ substring for the first (and in this example, the only) group of that
+ name that matched. This saves searching to find which numbered group it
+ was. (An alternative way of solving this problem is to use a "branch
+ reset" group, as described in the previous section.)
+
+ If you make a backreference to a non-unique named group from elsewhere
+ in the pattern, the groups to which the name refers are checked in the
+ order in which they appear in the overall pattern. The first one that
+ is set is used for the reference. For example, this pattern matches
+ both "foofoo" and "barbar" but not "foobar" or "barfoo":
+
+ (?J)(?:(?foo)|(?bar))\k
+
+
+ If you make a subroutine call to a non-unique named group, the one that
+ corresponds to the first occurrence of the name is used. In the absence
+ of duplicate numbers this is the one with the lowest number.
+
+ If you use a named reference in a condition test (see the section about
+ conditions below), either to check whether a capture group has matched,
+ or to check for recursion, all groups with the same name are tested. If
+ the condition is true for any one of them, the overall condition is
+ true. This is the same behaviour as testing by number. For further de-
+ tails of the interfaces for handling named capture groups, see the
+ pcre2api documentation.
+
+
+REPETITION
+
+ Repetition is specified by quantifiers, which may follow any one of
+ these items:
+
+ a literal data character
+ the dot metacharacter
+ the \C escape sequence
+ the \R escape sequence
+ the \X escape sequence
+ any escape sequence that matches a single character
+ a character class
+ a backreference
+ a parenthesized group (including lookaround assertions)
+ a subroutine call (recursive or otherwise)
+
+ If a quantifier does not follow a repeatable item, an error occurs. The
+ general repetition quantifier specifies a minimum and maximum number of
+ permitted matches by giving two numbers in curly brackets (braces),
+ separated by a comma. The numbers must be less than 65536, and the
+ first must be less than or equal to the second. For example,
+
+ z{2,4}
+
+ matches "zz", "zzz", or "zzzz". A closing brace on its own is not a
+ special character. If the second number is omitted, but the comma is
+ present, there is no upper limit; if the second number and the comma
+ are both omitted, the quantifier specifies an exact number of required
+ matches. Thus
+
+ [aeiou]{3,}
+
+ matches at least 3 successive vowels, but may match many more, whereas
+
+ \d{8}
+
+ matches exactly 8 digits. If the first number is omitted, the lower
+ limit is taken as zero; in this case the upper limit must be present.
+
+ X{,4} is interpreted as X{0,4}
+
+ This is a change in behaviour that happened in Perl 5.34.0 and PCRE2
+ 10.43. In earlier versions such a sequence was not interpreted as a
+ quantifier. Other regular expression engines may behave either way.
+
+ If the characters that follow an opening brace do not match the syntax
+ of a quantifier, the brace is taken as a literal character. In particu-
+ lar, this means that {,} is a literal string of three characters.
+
+ Note that not every opening brace is potentially the start of a quanti-
+ fier because braces are used in other items such as \N{U+345} or
+ \k{name}.
+
+ In UTF modes, quantifiers apply to characters rather than to individual
+ code units. Thus, for example, \x{100}{2} matches two characters, each
+ of which is represented by a two-byte sequence in a UTF-8 string. Simi-
+ larly, \X{3} matches three Unicode extended grapheme clusters, each of
+ which may be several code units long (and they may be of different
+ lengths).
+
+ The quantifier {0} is permitted, causing the expression to behave as if
+ the previous item and the quantifier were not present. This may be use-
+ ful for capture groups that are referenced as subroutines from else-
+ where in the pattern (but see also the section entitled "Defining cap-
+ ture groups for use by reference only" below). Except for parenthesized
+ groups, items that have a {0} quantifier are omitted from the compiled
+ pattern.
+
+ For convenience, the three most common quantifiers have single-charac-
+ ter abbreviations:
+
+ * is equivalent to {0,}
+ + is equivalent to {1,}
+ ? is equivalent to {0,1}
+
+ It is possible to construct infinite loops by following a group that
+ can match no characters with a quantifier that has no upper limit, for
+ example:
+
+ (a?)*
+
+ Earlier versions of Perl and PCRE1 used to give an error at compile
+ time for such patterns. However, because there are cases where this can
+ be useful, such patterns are now accepted, but whenever an iteration of
+ such a group matches no characters, matching moves on to the next item
+ in the pattern instead of repeatedly matching an empty string. This
+ does not prevent backtracking into any of the iterations if a subse-
+ quent item fails to match.
+
+ By default, quantifiers are "greedy", that is, they match as much as
+ possible (up to the maximum number of permitted repetitions), without
+ causing the rest of the pattern to fail. The classic example of where
+ this gives problems is in trying to match comments in C programs. These
+ appear between /* and */ and within the comment, individual * and /
+ characters may appear. An attempt to match C comments by applying the
+ pattern
+
+ /\*.*\*/
+
+ to the string
+
+ /* first comment */ not comment /* second comment */
+
+ fails, because it matches the entire string owing to the greediness of
+ the .* item. However, if a quantifier is followed by a question mark,
+ it ceases to be greedy, and instead matches the minimum number of times
+ possible, so the pattern
+
+ /\*.*?\*/
+
+ does the right thing with C comments. The meaning of the various quan-
+ tifiers is not otherwise changed, just the preferred number of matches.
+ Do not confuse this use of question mark with its use as a quantifier
+ in its own right. Because it has two uses, it can sometimes appear
+ doubled, as in
+
+ \d??\d
+
+ which matches one digit by preference, but can match two if that is the
+ only way the rest of the pattern matches.
+
+ If the PCRE2_UNGREEDY option is set (an option that is not available in
+ Perl), the quantifiers are not greedy by default, but individual ones
+ can be made greedy by following them with a question mark. In other
+ words, it inverts the default behaviour.
+
+ When a parenthesized group is quantified with a minimum repeat count
+ that is greater than 1 or with a limited maximum, more memory is re-
+ quired for the compiled pattern, in proportion to the size of the mini-
+ mum or maximum.
+
+ If a pattern starts with .* or .{0,} and the PCRE2_DOTALL option
+ (equivalent to Perl's /s) is set, thus allowing the dot to match new-
+ lines, the pattern is implicitly anchored, because whatever follows
+ will be tried against every character position in the subject string,
+ so there is no point in retrying the overall match at any position af-
+ ter the first. PCRE2 normally treats such a pattern as though it were
+ preceded by \A.
+
+ In cases where it is known that the subject string contains no new-
+ lines, it is worth setting PCRE2_DOTALL in order to obtain this opti-
+ mization, or alternatively, using ^ to indicate anchoring explicitly.
+
+ However, there are some cases where the optimization cannot be used.
+ When .* is inside capturing parentheses that are the subject of a
+ backreference elsewhere in the pattern, a match at the start may fail
+ where a later one succeeds. Consider, for example:
+
+ (.*)abc\1
+
+ If the subject is "xyz123abc123" the match point is the fourth charac-
+ ter. For this reason, such a pattern is not implicitly anchored.
+
+ Another case where implicit anchoring is not applied is when the lead-
+ ing .* is inside an atomic group. Once again, a match at the start may
+ fail where a later one succeeds. Consider this pattern:
+
+ (?>.*?a)b
+
+ It matches "ab" in the subject "aab". The use of the backtracking con-
+ trol verbs (*PRUNE) and (*SKIP) also disable this optimization. To do
+ so explicitly, either pass the compile option PCRE2_NO_DOTSTAR_ANCHOR,
+ or call pcre2_set_optimize() with a PCRE2_DOTSTAR_ANCHOR_OFF directive.
+
+ When a capture group is repeated, the value captured is the substring
+ that matched the final iteration. For example, after
+
+ (tweedle[dume]{3}\s*)+
+
+ has matched "tweedledum tweedledee" the value of the captured substring
+ is "tweedledee". However, if there are nested capture groups, the cor-
+ responding captured values may have been set in previous iterations.
+ For example, after
+
+ (a|(b))+
+
+ matches "aba" the value of the second captured substring is "b".
+
+
+ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS
+
+ With both maximizing ("greedy") and minimizing ("ungreedy" or "lazy")
+ repetition, failure of what follows normally causes the repeated item
+ to be re-evaluated to see if a different number of repeats allows the
+ rest of the pattern to match. Sometimes it is useful to prevent this,
+ either to change the nature of the match, or to cause it fail earlier
+ than it otherwise might, when the author of the pattern knows there is
+ no point in carrying on.
+
+ Consider, for example, the pattern \d+foo when applied to the subject
+ line
+
+ 123456bar
+
+ After matching all 6 digits and then failing to match "foo", the normal
+ action of the matcher is to try again with only 5 digits matching the
+ \d+ item, and then with 4, and so on, before ultimately failing.
+ "Atomic grouping" (a term taken from Jeffrey Friedl's book) provides
+ the means for specifying that once a group has matched, it is not to be
+ re-evaluated in this way.
+
+ If we use atomic grouping for the previous example, the matcher gives
+ up immediately on failing to match "foo" the first time. The notation
+ is a kind of special parenthesis, starting with (?> as in this example:
+
+ (?>\d+)foo
+
+ Perl 5.28 introduced an experimental alphabetic form starting with (*
+ which may be easier to remember:
+
+ (*atomic:\d+)foo
+
+ This kind of parenthesized group "locks up" the part of the pattern it
+ contains once it has matched, and a failure further into the pattern is
+ prevented from backtracking into it. Backtracking past it to previous
+ items, however, works as normal.
+
+ An alternative description is that a group of this type matches exactly
+ the string of characters that an identical standalone pattern would
+ match, if anchored at the current point in the subject string.
+
+ Atomic groups are not capture groups. Simple cases such as the above
+ example can be thought of as a maximizing repeat that must swallow
+ everything it can. So, while both \d+ and \d+? are prepared to adjust
+ the number of digits they match in order to make the rest of the pat-
+ tern match, (?>\d+) can only match an entire sequence of digits.
+
+ Atomic groups in general can of course contain arbitrarily complicated
+ expressions, and can be nested. However, when the contents of an atomic
+ group is just a single repeated item, as in the example above, a sim-
+ pler notation, called a "possessive quantifier" can be used. This con-
+ sists of an additional + character following a quantifier. Using this
+ notation, the previous example can be rewritten as
+
+ \d++foo
+
+ Note that a possessive quantifier can be used with an entire group, for
+ example:
+
+ (abc|xyz){2,3}+
+
+ Possessive quantifiers are always greedy; the setting of the PCRE2_UN-
+ GREEDY option is ignored. They are a convenient notation for the sim-
+ pler forms of atomic group. However, there is no difference in the
+ meaning of a possessive quantifier and the equivalent atomic group,
+ though there may be a performance difference; possessive quantifiers
+ should be slightly faster.
+
+ The possessive quantifier syntax is an extension to the Perl 5.8 syn-
+ tax. Jeffrey Friedl originated the idea (and the name) in the first
+ edition of his book. Mike McCloskey liked it, so implemented it when he
+ built Sun's Java package, and PCRE1 copied it from there. It found its
+ way into Perl at release 5.10.
+
+ PCRE2 has an optimization that automatically "possessifies" certain
+ simple pattern constructs. For example, the sequence A+B is treated as
+ A++B because there is no point in backtracking into a sequence of A's
+ when B must follow. This feature can be disabled by the
+ PCRE2_NO_AUTO_POSSESS option, by calling pcre2_set_optimize() with a
+ PCRE2_AUTO_POSSESS_OFF directive, or by starting the pattern with
+ (*NO_AUTO_POSSESS).
+
+ When a pattern contains an unlimited repeat inside a group that can it-
+ self be repeated an unlimited number of times, the use of an atomic
+ group is the only way to avoid some failing matches taking a very long
+ time indeed. The pattern
+
+ (\D+|<\d+>)*[!?]
+
+ matches an unlimited number of substrings that either consist of non-
+ digits, or digits enclosed in <>, followed by either ! or ?. When it
+ matches, it runs quickly. However, if it is applied to
+
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+
+ it takes a long time before reporting failure. This is because the
+ string can be divided between the internal \D+ repeat and the external
+ * repeat in a large number of ways, and all have to be tried. (The ex-
+ ample uses [!?] rather than a single character at the end, because both
+ PCRE2 and Perl have an optimization that allows for fast failure when a
+ single character is used. They remember the last single character that
+ is required for a match, and fail early if it is not present in the
+ string.) If the pattern is changed so that it uses an atomic group,
+ like this:
+
+ ((?>\D+)|<\d+>)*[!?]
+
+ sequences of non-digits cannot be broken, and failure happens quickly.
+
+
+BACKREFERENCES
+
+ Outside a character class, a backslash followed by a digit greater than
+ 0 (and possibly further digits) is a backreference to a capture group
+ earlier (that is, to its left) in the pattern, provided there have been
+ that many previous capture groups.
+
+ However, if the decimal number following the backslash is less than 8,
+ it is always taken as a backreference, and causes an error only if
+ there are not that many capture groups in the entire pattern. In other
+ words, the group that is referenced need not be to the left of the ref-
+ erence for numbers less than 8. A "forward backreference" of this type
+ can make sense when a repetition is involved and the group to the right
+ has participated in an earlier iteration.
+
+ It is not possible to have a numerical "forward backreference" to a
+ group whose number is 8 or more using this syntax because a sequence
+ such as \50 is interpreted as a character defined in octal. See the
+ subsection entitled "Non-printing characters" above for further details
+ of the handling of digits following a backslash. Other forms of back-
+ referencing do not suffer from this restriction. In particular, there
+ is no problem when named capture groups are used (see below).
+
+ Another way of avoiding the ambiguity inherent in the use of digits
+ following a backslash is to use the \g escape sequence. This escape
+ must be followed by a signed or unsigned number, optionally enclosed in
+ braces. These examples are all identical:
+
+ (ring), \1
+ (ring), \g1
+ (ring), \g{1}
+
+ An unsigned number specifies an absolute reference without the ambigu-
+ ity that is present in the older syntax. It is also useful when literal
+ digits follow the reference. A signed number is a relative reference.
+ Consider this example:
+
+ (abc(def)ghi)\g{-1}
+
+ The sequence \g{-1} is a reference to the capture group whose number is
+ one less than the number of the next group to be started, so in this
+ example (where the next group would be numbered 3) is it equivalent to
+ \2, and \g{-2} would be equivalent to \1. Note that if this construct
+ is inside a capture group, that group is included in the count, so in
+ this example \g{-2} also refers to group 1:
+
+ (A)(\g{-2}B)
+
+ The use of relative references can be helpful in long patterns, and
+ also in patterns that are created by joining together fragments that
+ contain references within themselves.
+
+ The sequence \g{+1} is a reference to the next capture group that is
+ started after this item, and \g{+2} refers to the one after that, and
+ so on. This kind of forward reference can be useful in patterns that
+ repeat. Perl does not support the use of + in this way.
+
+ A backreference matches whatever actually most recently matched the
+ capture group in the current subject string, rather than anything at
+ all that matches the group (see "Groups as subroutines" below for a way
+ of doing that). So the pattern
+
+ (sens|respons)e and \1ibility
+
+ matches "sense and sensibility" and "response and responsibility", but
+ not "sense and responsibility". If caseful matching is in force at the
+ time of the backreference, the case of letters is relevant. For exam-
+ ple,
+
+ ((?i)rah)\s+\1
+
+ matches "rah rah" and "RAH RAH", but not "RAH rah", even though the
+ original capture group is matched caselessly.
+
+ There are several different ways of writing backreferences to named
+ capture groups. The .NET syntax is \k{name}, the Python syntax is
+ (?=name), and the original Perl syntax is \k or \k'name'. All of
+ these are now supported by both Perl and PCRE2. Perl 5.10's unified
+ backreference syntax, in which \g can be used for both numeric and
+ named references, is also supported by PCRE2. We could rewrite the
+ above example in any of the following ways:
+
+ (?(?i)rah)\s+\k
+ (?'p1'(?i)rah)\s+\k{p1}
+ (?P(?i)rah)\s+(?P=p1)
+ (?(?i)rah)\s+\g{p1}
+
+ A capture group that is referenced by name may appear in the pattern
+ before or after the reference.
+
+ There may be more than one backreference to the same group. If a group
+ has not actually been used in a particular match, backreferences to it
+ always fail by default. For example, the pattern
+
+ (a|(bc))\2
+
+ always fails if it starts to match "a" rather than "bc". However, if
+ the PCRE2_MATCH_UNSET_BACKREF option is set at compile time, a backref-
+ erence to an unset value matches an empty string.
+
+ Because there may be many capture groups in a pattern, all digits fol-
+ lowing a backslash are taken as part of a potential backreference num-
+ ber. If the pattern continues with a digit character, some delimiter
+ must be used to terminate the backreference. If the PCRE2_EXTENDED or
+ PCRE2_EXTENDED_MORE option is set, this can be white space. Otherwise,
+ the \g{} syntax or an empty comment (see "Comments" below) can be used.
+
+ Recursive backreferences
+
+ A backreference that occurs inside the group to which it refers fails
+ when the group is first used, so, for example, (a\1) never matches.
+ However, such references can be useful inside repeated groups. For ex-
+ ample, the pattern
+
+ (a|b\1)+
+
+ matches any number of "a"s and also "aba", "ababbaa" etc. At each iter-
+ ation of the group, the backreference matches the character string cor-
+ responding to the previous iteration. In order for this to work, the
+ pattern must be such that the first iteration does not need to match
+ the backreference. This can be done using alternation, as in the exam-
+ ple above, or by a quantifier with a minimum of zero.
+
+ For versions of PCRE2 less than 10.25, backreferences of this type used
+ to cause the group that they reference to be treated as an atomic
+ group. This restriction no longer applies, and backtracking into such
+ groups can occur as normal.
+
+
+ASSERTIONS
+
+ An assertion is a test that does not consume any characters. The test
+ must succeed for the match to continue. The simple assertions coded as
+ \b, \B, \A, \G, \Z, \z, ^ and $ are described above.
+
+ More complicated assertions are coded as parenthesized groups. If
+ matching such a group succeeds, matching continues after it, but with
+ the matching position in the subject string reset to what it was before
+ the assertion was processed.
+
+ A special kind of assertion, called a "scan substring" assertion,
+ matches a subpattern against a previously captured substring. This is
+ described in the section entitled "Scan substring assertions" below. It
+ is a PCRE2 extension, not compatible with Perl.
+
+ The other goup-based assertions are of two kinds: those that look ahead
+ of the current position in the subject string, and those that look be-
+ hind it, and in each case an assertion may be positive (must match for
+ the assertion to be true) or negative (must not match for the assertion
+ to be true).
+
+ The Perl-compatible lookaround assertions are atomic. If an assertion
+ is true, but there is a subsequent matching failure, there is no back-
+ tracking into the assertion. However, there are some cases where non-
+ atomic assertions can be useful. PCRE2 has some support for these, de-
+ scribed in the section entitled "Non-atomic assertions" below, but they
+ are not Perl-compatible.
+
+ A lookaround assertion may appear as the condition in a conditional
+ group (see below). In this case, the result of matching the assertion
+ determines which branch of the condition is followed.
+
+ Assertion groups are not capture groups. If an assertion contains cap-
+ ture groups within it, these are counted for the purposes of numbering
+ the capture groups in the whole pattern. Within each branch of an as-
+ sertion, locally captured substrings may be referenced in the usual
+ way. For example, a sequence such as (.)\g{-1} can be used to check
+ that two adjacent characters are the same.
+
+ When a branch within an assertion fails to match, any substrings that
+ were captured are discarded (as happens with any pattern branch that
+ fails to match). A negative assertion is true only when all its
+ branches fail to match; this means that no captured substrings are ever
+ retained after a successful negative assertion. When an assertion con-
+ tains a matching branch, what happens depends on the type of assertion.
+
+ For a positive assertion, internally captured substrings in the suc-
+ cessful branch are retained, and matching continues with the next pat-
+ tern item after the assertion. For a negative assertion, a matching
+ branch means that the assertion is not true. If such an assertion is
+ being used as a condition in a conditional group (see below), captured
+ substrings are retained, because matching continues with the "no"
+ branch of the condition. For other failing negative assertions, control
+ passes to the previous backtracking point, thus discarding any captured
+ strings within the assertion.
+
+ Most assertion groups may be repeated; though it makes no sense to as-
+ sert the same thing several times, the side effect of capturing in pos-
+ itive assertions may occasionally be useful. However, an assertion that
+ forms the condition for a conditional group may not be quantified.
+ PCRE2 used to restrict the repetition of assertions, but from release
+ 10.35 the only restriction is that an unlimited maximum repetition is
+ changed to be one more than the minimum. For example, {3,} is treated
+ as {3,4}.
+
+ Alphabetic assertion names
+
+ Traditionally, symbolic sequences such as (?= and (?<= have been used
+ to specify lookaround assertions. Perl 5.28 introduced some experimen-
+ tal alphabetic alternatives which might be easier to remember. They all
+ start with (* instead of (? and must be written using lower case let-
+ ters. PCRE2 supports the following synonyms:
+
+ (*positive_lookahead: or (*pla: is the same as (?=
+ (*negative_lookahead: or (*nla: is the same as (?!
+ (*positive_lookbehind: or (*plb: is the same as (?<=
+ (*negative_lookbehind: or (*nlb: is the same as (? .*? \b\1\b ){2}
+
+ For a subject such as "word1 word2 word3 word2 word3 word4" the result
+ is "word3". How does it work? At the start, ^(?x) anchors the pattern
+ and sets the "x" option, which causes white space (introduced for read-
+ ability) to be ignored. Inside the assertion, the greedy .* at first
+ consumes the entire string, but then has to backtrack until the rest of
+ the assertion can match a word, which is captured by group 1. In other
+ words, when the assertion first succeeds, it captures the right-most
+ word in the string.
+
+ The current matching point is then reset to the start of the subject,
+ and the rest of the pattern match checks for two occurrences of the
+ captured word, using an ungreedy .*? to scan from the left. If this
+ succeeds, we are done, but if the last word in the string does not oc-
+ cur twice, this part of the pattern fails. If a traditional atomic
+ lookahead (?= or (*pla: had been used, the assertion could not be re-
+ entered, and the whole match would fail. The pattern would succeed only
+ if the very last word in the subject was found twice.
+
+ Using a non-atomic lookahead, however, means that when the last word
+ does not occur twice in the string, the lookahead can backtrack and
+ find the second-last word, and so on, until either the match succeeds,
+ or all words have been tested.
+
+ Two conditions must be met for a non-atomic assertion to be useful: the
+ contents of one or more capturing groups must change after a backtrack
+ into the assertion, and there must be a backreference to a changed
+ group later in the pattern. If this is not the case, the rest of the
+ pattern match fails exactly as before because nothing has changed, so
+ using a non-atomic assertion just wastes resources.
+
+ There is one exception to backtracking into a non-atomic assertion. If
+ an (*ACCEPT) control verb is triggered, the assertion succeeds atomi-
+ cally. That is, a subsequent match failure cannot backtrack into the
+ assertion.
+
+ Non-atomic assertions are not supported by the alternative matching
+ function pcre2_dfa_match(). They are supported by JIT, but only if they
+ do not contain any control verbs such as (*ACCEPT). (This may change in
+ future). Note that assertions that appear as conditions for conditional
+ groups (see below) must be atomic.
+
+
+SCAN SUBSTRING ASSERTIONS
+
+ A special kind of assertion, not compatible with Perl, makes it possi-
+ ble to check the contents of a captured substring by matching it with a
+ subpattern. Because this involves capturing, this feature is not sup-
+ ported by pcre2_dfa_match().
+
+ A scan substring assertion starts with the sequence (*scan_substring:
+ or (*scs: which is followed by a list of substring numbers (absolute or
+ relative) and/or substring names enclosed in single quotes or angle
+ brackets, all within parentheses. The rest of the item is the subpat-
+ tern that is applied to the substring, as shown in these examples:
+
+ (*scan_substring:(1)...)
+ (*scs:(-2)...)
+ (*scs:('AB')...)
+ (*scs:(1,'AB',-2)...)
+
+ The list of groups is checked in the order they are given, and it is
+ the contents of the first one that is found to be set that are scanned.
+ When PCRE2_DUPNAMES is set and there are ambiguous group names, all
+ groups with the same name are checked in numerical order. A scan sub-
+ string assertion fails if none of the groups it references have been
+ set.
+
+ The pattern match on the substring is always anchored, that is, it must
+ match from the start of the substring. There is no "bumpalong" if it
+ does not match at the start. The end of the subject is temporarily re-
+ set to be the end of the substring, so \Z, \z, and $ will match there.
+ However, the start of the subject is not reset. This means that ^
+ matches only if the substring is actually at the start of the main sub-
+ ject, but it also means that lookbehind assertions into what precedes
+ the substring are possible.
+
+ Here is a very simple example: find a word that contains the rare (in
+ English) sequence of letters "rh" not at the start:
+
+ \b(\w++)(*scs:(1).+rh)
+
+ The first group captures a word which is then scanned by the second
+ group. This example does not actually need this heavyweight feature;
+ the same match can be achieved with:
+
+ \b\w+?rh\w*\b
+
+ When things are more complicated, however, scanning a captured sub-
+ string can be a useful way to describe the required match. For exmple,
+ there is a rather complicated pattern in the PCRE2 test data that
+ checks an entire subject string for a palindrome, that is, the sequence
+ of letters is the same in both directions. Suppose you want to search
+ for individual words of two or more characters such as "level" that are
+ palindromes:
+
+ (\b\w{2,}+\b)(*scs:(1)...palindrome-matching-pattern...)
+
+ Within a substring scanning subpattern, references to other groups work
+ as normal. Capturing groups may appear, and will retain their values
+ during ongoing matching if the assertion succeeds.
+
+
+SCRIPT RUNS
+
+ In concept, a script run is a sequence of characters that are all from
+ the same Unicode script such as Latin or Greek. However, because some
+ scripts are commonly used together, and because some diacritical and
+ other marks are used with multiple scripts, it is not that simple.
+ There is a full description of the rules that PCRE2 uses in the section
+ entitled "Script Runs" in the pcre2unicode documentation.
+
+ If part of a pattern is enclosed between (*script_run: or (*sr: and a
+ closing parenthesis, it fails if the sequence of characters that it
+ matches are not a script run. After a failure, normal backtracking oc-
+ curs. Script runs can be used to detect spoofing attacks using charac-
+ ters that look the same, but are from different scripts. The string
+ "paypal.com" is an infamous example, where the letters could be a mix-
+ ture of Latin and Cyrillic. This pattern ensures that the matched char-
+ acters in a sequence of non-spaces that follow white space are a script
+ run:
+
+ \s+(*sr:\S+)
+
+ To be sure that they are all from the Latin script (for example), a
+ lookahead can be used:
+
+ \s+(?=\p{Latin})(*sr:\S+)
+
+ This works as long as the first character is expected to be a character
+ in that script, and not (for example) punctuation, which is allowed
+ with any script. If this is not the case, a more creative lookahead is
+ needed. For example, if digits, underscore, and dots are permitted at
+ the start:
+
+ \s+(?=[0-9_.]*\p{Latin})(*sr:\S+)
+
+
+ In many cases, backtracking into a script run pattern fragment is not
+ desirable. The script run can employ an atomic group to prevent this.
+ Because this is a common requirement, a shorthand notation is provided
+ by (*atomic_script_run: or (*asr:
+
+ (*asr:...) is the same as (*sr:(?>...))
+
+ Note that the atomic group is inside the script run. Putting it outside
+ would not prevent backtracking into the script run pattern.
+
+ Support for script runs is not available if PCRE2 is compiled without
+ Unicode support. A compile-time error is given if any of the above con-
+ structs is encountered. Script runs are not supported by the alternate
+ matching function, pcre2_dfa_match() because they use the same mecha-
+ nism as capturing parentheses.
+
+ Warning: The (*ACCEPT) control verb (see below) should not be used
+ within a script run group, because it causes an immediate exit from the
+ group, bypassing the script run checking.
+
+
+CONDITIONAL GROUPS
+
+ It is possible to cause the matching process to obey a pattern fragment
+ conditionally or to choose between two alternative fragments, depending
+ on the result of an assertion, or whether a specific capture group has
+ already been matched. The two possible forms of conditional group are:
+
+ (?(condition)yes-pattern)
+ (?(condition)yes-pattern|no-pattern)
+
+ If the condition is satisfied, the yes-pattern is used; otherwise the
+ no-pattern (if present) is used. An absent no-pattern is equivalent to
+ an empty string (it always matches). If there are more than two alter-
+ natives in the group, a compile-time error occurs. Each of the two al-
+ ternatives may itself contain nested groups of any form, including con-
+ ditional groups; the restriction to two alternatives applies only at
+ the level of the condition itself. This pattern fragment is an example
+ where the alternatives are complex:
+
+ (?(1) (A|B|C) | (D | (?(2)E|F) | E) )
+
+
+ There are five kinds of condition: references to capture groups, refer-
+ ences to recursion, two pseudo-conditions called DEFINE and VERSION,
+ and assertions.
+
+ Checking for a used capture group by number
+
+ If the text between the parentheses consists of a sequence of digits,
+ the condition is true if a capture group of that number has previously
+ matched. If there is more than one capture group with the same number
+ (see the earlier section about duplicate group numbers), the condition
+ is true if any of them have matched. An alternative notation, which is
+ a PCRE2 extension, not supported by Perl, is to precede the digits with
+ a plus or minus sign. In this case, the group number is relative rather
+ than absolute. The most recently opened capture group (which could be
+ enclosing this condition) can be referenced by (?(-1), the next most
+ recent by (?(-2), and so on. Inside loops it can also make sense to re-
+ fer to subsequent groups. The next capture group to be opened can be
+ referenced as (?(+1), and so on. The value zero in any of these forms
+ is not used; it provokes a compile-time error.
+
+ Consider the following pattern, which contains non-significant white
+ space to make it more readable (assume the PCRE2_EXTENDED option) and
+ to divide it into three parts for ease of discussion:
+
+ ( \( )? [^()]+ (?(1) \) )
+
+ The first part matches an optional opening parenthesis, and if that
+ character is present, sets it as the first captured substring. The sec-
+ ond part matches one or more characters that are not parentheses. The
+ third part is a conditional group that tests whether or not the first
+ capture group matched. If it did, that is, if subject started with an
+ opening parenthesis, the condition is true, and so the yes-pattern is
+ executed and a closing parenthesis is required. Otherwise, since no-
+ pattern is not present, the conditional group matches nothing. In other
+ words, this pattern matches a sequence of non-parentheses, optionally
+ enclosed in parentheses.
+
+ If you were embedding this pattern in a larger one, you could use a
+ relative reference:
+
+ ...other stuff... ( \( )? [^()]+ (?(-1) \) ) ...
+
+ This makes the fragment independent of the parentheses in the larger
+ pattern.
+
+ Checking for a used capture group by name
+
+ Perl uses the syntax (?()...) or (?('name')...) to test for a
+ used capture group by name. For compatibility with earlier versions of
+ PCRE1, which had this facility before Perl, the syntax (?(name)...) is
+ also recognized. Note, however, that undelimited names consisting of
+ the letter R followed by digits are ambiguous (see the following sec-
+ tion). Rewriting the above example to use a named group gives this:
+
+ (? \( )? [^()]+ (?() \) )
+
+ If the name used in a condition of this kind is a duplicate, the test
+ is applied to all groups of the same name, and is true if any one of
+ them has matched.
+
+ Checking for pattern recursion
+
+ "Recursion" in this sense refers to any subroutine-like call from one
+ part of the pattern to another, whether or not it is actually recur-
+ sive. See the sections entitled "Recursive patterns" and "Groups as
+ subroutines" below for details of recursion and subroutine calls.
+
+ If a condition is the string (R), and there is no capture group with
+ the name R, the condition is true if matching is currently in a recur-
+ sion or subroutine call to the whole pattern or any capture group. If
+ digits follow the letter R, and there is no group with that name, the
+ condition is true if the most recent call is into a group with the
+ given number, which must exist somewhere in the overall pattern. This
+ is a contrived example that is equivalent to a+b:
+
+ ((?(R1)a+|(?1)b))
+
+ However, in both cases, if there is a capture group with a matching
+ name, the condition tests for its being set, as described in the sec-
+ tion above, instead of testing for recursion. For example, creating a
+ group with the name R1 by adding (?) to the above pattern com-
+ pletely changes its meaning.
+
+ If a name preceded by ampersand follows the letter R, for example:
+
+ (?(R&name)...)
+
+ the condition is true if the most recent recursion is into a group of
+ that name (which must exist within the pattern).
+
+ This condition does not check the entire recursion stack. It tests only
+ the current level. If the name used in a condition of this kind is a
+ duplicate, the test is applied to all groups of the same name, and is
+ true if any one of them is the most recent recursion.
+
+ At "top level", all these recursion test conditions are false.
+
+ Defining capture groups for use by reference only
+
+ If the condition is the string (DEFINE), the condition is always false,
+ even if there is a group with the name DEFINE. In this case, there may
+ be only one alternative in the rest of the conditional group. It is al-
+ ways skipped if control reaches this point in the pattern; the idea of
+ DEFINE is that it can be used to define subroutines that can be refer-
+ enced from elsewhere. (The use of subroutines is described below.) For
+ example, a pattern to match an IPv4 address such as "192.168.23.245"
+ could be written like this (ignore white space and line breaks):
+
+ (?(DEFINE) (? 2[0-4]\d | 25[0-5] | 1\d\d | [1-9]?\d) )
+ \b (?&byte) (\.(?&byte)){3} \b
+
+ The first part of the pattern is a DEFINE group inside which another
+ group named "byte" is defined. This matches an individual component of
+ an IPv4 address (a number less than 256). When matching takes place,
+ this part of the pattern is skipped because DEFINE acts like a false
+ condition. The rest of the pattern uses references to the named group
+ to match the four dot-separated components of an IPv4 address, insist-
+ ing on a word boundary at each end.
+
+ Checking the PCRE2 version
+
+ Programs that link with a PCRE2 library can check the version by call-
+ ing pcre2_config() with appropriate arguments. Users of applications
+ that do not have access to the underlying code cannot do this. A spe-
+ cial "condition" called VERSION exists to allow such users to discover
+ which version of PCRE2 they are dealing with by using this condition to
+ match a string such as "yesno". VERSION must be followed either by "="
+ or ">=" and a version number. For example:
+
+ (?(VERSION>=10.4)yes|no)
+
+ This pattern matches "yes" if the PCRE2 version is greater or equal to
+ 10.4, or "no" otherwise. The fractional part of the version number
+ could be ommited.
+
+ Assertion conditions
+
+ If the condition is not in any of the above formats, it must be a
+ parenthesized assertion. This may be a positive or negative lookahead
+ or lookbehind assertion. However, it must be a traditional atomic as-
+ sertion, not one of the non-atomic assertions.
+
+ Consider this pattern, again containing non-significant white space,
+ and with the two alternatives on the second line:
+
+ (?(?=[^a-z]*[a-z])
+ \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} )
+
+ The condition is a positive lookahead assertion that matches an op-
+ tional sequence of non-letters followed by a letter. In other words, it
+ tests for the presence of at least one letter in the subject. If a let-
+ ter is found, the subject is matched against the first alternative;
+ otherwise it is matched against the second. This pattern matches
+ strings in one of the two forms dd-aaa-dd or dd-dd-dd, where aaa are
+ letters and dd are digits.
+
+ When an assertion that is a condition contains capture groups, any cap-
+ turing that occurs in a matching branch is retained afterwards, for
+ both positive and negative assertions, because matching always contin-
+ ues after the assertion, whether it succeeds or fails. (Compare non-
+ conditional assertions, for which captures are retained only for posi-
+ tive assertions that succeed.)
+
+
+COMMENTS
+
+ There are two ways of including comments in patterns that are processed
+ by PCRE2. In both cases, the start of the comment must not be in a
+ character class, nor in the middle of any other sequence of related
+ characters such as (?: or a group name or number or a Unicode property
+ name. The characters that make up a comment play no part in the pattern
+ matching.
+
+ The sequence (?# marks the start of a comment that continues up to the
+ next closing parenthesis. Nested parentheses are not permitted. If the
+ PCRE2_EXTENDED or PCRE2_EXTENDED_MORE option is set, an unescaped #
+ character also introduces a comment, which in this case continues to
+ immediately after the next newline character or character sequence in
+ the pattern. Which characters are interpreted as newlines is controlled
+ by an option passed to the compiling function or by a special sequence
+ at the start of the pattern, as described in the section entitled "New-
+ line conventions" above. Note that the end of this type of comment is a
+ literal newline sequence in the pattern; escape sequences that happen
+ to represent a newline do not count. For example, consider this pattern
+ when PCRE2_EXTENDED is set, and the default newline convention (a sin-
+ gle linefeed character) is in force:
+
+ abc #comment \n still comment
+
+ On encountering the # character, pcre2_compile() skips along, looking
+ for a newline in the pattern. The sequence \n is still literal at this
+ stage, so it does not terminate the comment. Only an actual character
+ with the code value 0x0a (the default newline) does so.
+
+
+RECURSIVE PATTERNS
+
+ Consider the problem of matching a string in parentheses, allowing for
+ unlimited nested parentheses. Without the use of recursion, the best
+ that can be done is to use a pattern that matches up to some fixed
+ depth of nesting. It is not possible to handle an arbitrary nesting
+ depth.
+
+ For some time, Perl has provided a facility that allows regular expres-
+ sions to recurse (amongst other things). It does this by interpolating
+ Perl code in the expression at run time, and the code can refer to the
+ expression itself. A Perl pattern using code interpolation to solve the
+ parentheses problem can be created like this:
+
+ $re = qr{\( (?: (?>[^()]+) | (?p{$re}) )* \)}x;
+
+ The (?p{...}) item interpolates Perl code at run time, and in this case
+ refers recursively to the pattern in which it appears.
+
+ Obviously, PCRE2 cannot support the interpolation of Perl code. In-
+ stead, it supports special syntax for recursion of the entire pattern,
+ and also for individual capture group recursion. After its introduction
+ in PCRE1 and Python, this kind of recursion was subsequently introduced
+ into Perl at release 5.10.
+
+ A special item that consists of (? followed by a number greater than
+ zero and a closing parenthesis is a recursive subroutine call of the
+ capture group of the given number, provided that it occurs inside that
+ group. (If not, it is a non-recursive subroutine call, which is de-
+ scribed in the next section.) The special item (?R) or (?0) is a recur-
+ sive call of the entire regular expression.
+
+ This PCRE2 pattern solves the nested parentheses problem (assume the
+ PCRE2_EXTENDED option is set so that white space is ignored):
+
+ \( ( [^()]++ | (?R) )* \)
+
+ First it matches an opening parenthesis. Then it matches any number of
+ substrings which can either be a sequence of non-parentheses, or a re-
+ cursive match of the pattern itself (that is, a correctly parenthesized
+ substring). Finally there is a closing parenthesis. Note the use of a
+ possessive quantifier to avoid backtracking into sequences of non-
+ parentheses.
+
+ If this were part of a larger pattern, you would not want to recurse
+ the entire pattern, so instead you could use this:
+
+ ( \( ( [^()]++ | (?1) )* \) )
+
+ We have put the pattern into parentheses, and caused the recursion to
+ refer to them instead of the whole pattern.
+
+ In a larger pattern, keeping track of parenthesis numbers can be
+ tricky. This is made easier by the use of relative references. Instead
+ of (?1) in the pattern above you can write (?-2) to refer to the second
+ most recently opened parentheses preceding the recursion. In other
+ words, a negative number counts capturing parentheses leftwards from
+ the point at which it is encountered.
+
+ Be aware however, that if duplicate capture group numbers are in use,
+ relative references refer to the earliest group with the appropriate
+ number. Consider, for example:
+
+ (?|(a)|(b)) (c) (?-2)
+
+ The first two capture groups (a) and (b) are both numbered 1, and group
+ (c) is number 2. When the reference (?-2) is encountered, the second
+ most recently opened parentheses has the number 1, but it is the first
+ such group (the (a) group) to which the recursion refers. This would be
+ the same if an absolute reference (?1) was used. In other words, rela-
+ tive references are just a shorthand for computing a group number.
+
+ It is also possible to refer to subsequent capture groups, by writing
+ references such as (?+2). However, these cannot be recursive because
+ the reference is not inside the parentheses that are referenced. They
+ are always non-recursive subroutine calls, as described in the next
+ section.
+
+ An alternative approach is to use named parentheses. The Perl syntax
+ for this is (?&name); PCRE1's earlier syntax (?P>name) is also sup-
+ ported. We could rewrite the above example as follows:
+
+ (? \( ( [^()]++ | (?&pn) )* \) )
+
+ If there is more than one group with the same name, the earliest one is
+ used.
+
+ The example pattern that we have been looking at contains nested unlim-
+ ited repeats, and so the use of a possessive quantifier for matching
+ strings of non-parentheses is important when applying the pattern to
+ strings that do not match. For example, when this pattern is applied to
+
+ (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
+
+ it yields "no match" quickly. However, if a possessive quantifier is
+ not used, the match runs for a very long time indeed because there are
+ so many different ways the + and * repeats can carve up the subject,
+ and all have to be tested before failure can be reported.
+
+ At the end of a match, the values of capturing parentheses are those
+ from the outermost level. If you want to obtain intermediate values, a
+ callout function can be used (see below and the pcre2callout documenta-
+ tion). If the pattern above is matched against
+
+ (ab(cd)ef)
+
+ the value for the inner capturing parentheses (numbered 2) is "ef",
+ which is the last value taken on at the top level. If a capture group
+ is not matched at the top level, its final captured value is unset,
+ even if it was (temporarily) set at a deeper level during the matching
+ process.
+
+ Do not confuse the (?R) item with the condition (R), which tests for
+ recursion. Consider this pattern, which matches text in angle brack-
+ ets, allowing for arbitrary nesting. Only digits are allowed in nested
+ brackets (that is, when recursing), whereas any characters are permit-
+ ted at the outer level.
+
+ < (?: (?(R) \d++ | [^<>]*+) | (?R)) * >
+
+ In this pattern, (?(R) is the start of a conditional group, with two
+ different alternatives for the recursive and non-recursive cases. The
+ (?R) item is the actual recursive call.
+
+ Differences in recursion processing between PCRE2 and Perl
+
+ Some former differences between PCRE2 and Perl no longer exist.
+
+ Before release 10.30, recursion processing in PCRE2 differed from Perl
+ in that a recursive subroutine call was always treated as an atomic
+ group. That is, once it had matched some of the subject string, it was
+ never re-entered, even if it contained untried alternatives and there
+ was a subsequent matching failure. (Historical note: PCRE implemented
+ recursion before Perl did.)
+
+ Starting with release 10.30, recursive subroutine calls are no longer
+ treated as atomic. That is, they can be re-entered to try unused alter-
+ natives if there is a matching failure later in the pattern. This is
+ now compatible with the way Perl works. If you want a subroutine call
+ to be atomic, you must explicitly enclose it in an atomic group.
+
+ Supporting backtracking into recursions simplifies certain types of re-
+ cursive pattern. For example, this pattern matches palindromic strings:
+
+ ^((.)(?1)\2|.?)$
+
+ The second branch in the group matches a single central character in
+ the palindrome when there are an odd number of characters, or nothing
+ when there are an even number of characters, but in order to work it
+ has to be able to try the second case when the rest of the pattern
+ match fails. If you want to match typical palindromic phrases, the pat-
+ tern has to ignore all non-word characters, which can be done like
+ this:
+
+ ^\W*+((.)\W*+(?1)\W*+\2|\W*+.?)\W*+$
+
+ If run with the PCRE2_CASELESS option, this pattern matches phrases
+ such as "A man, a plan, a canal: Panama!". Note the use of the posses-
+ sive quantifier *+ to avoid backtracking into sequences of non-word
+ characters. Without this, PCRE2 takes a great deal longer (ten times or
+ more) to match typical phrases, and Perl takes so long that you think
+ it has gone into a loop.
+
+ Another way in which PCRE2 and Perl used to differ in their recursion
+ processing is in the handling of captured values. Formerly in Perl,
+ when a group was called recursively or as a subroutine (see the next
+ section), it had no access to any values that were captured outside the
+ recursion, whereas in PCRE2 these values can be referenced. Consider
+ this pattern:
+
+ ^(.)(\1|a(?2))
+
+ This pattern matches "bab". The first capturing parentheses match "b",
+ then in the second group, when the backreference \1 fails to match "b",
+ the second alternative matches "a" and then recurses. In the recursion,
+ \1 does now match "b" and so the whole match succeeds. This match used
+ to fail in Perl, but in later versions (I tried 5.024) it now works.
+
+ Groups as subroutines
+
+ If the syntax for a recursive group call (either by number or by name)
+ is used outside the parentheses to which it refers, it operates a bit
+ like a subroutine in a programming language. More accurately, PCRE2
+ treats the referenced group as an independent subpattern which it tries
+ to match at the current matching position. The called group may be de-
+ fined before or after the reference. A numbered reference can be ab-
+ solute or relative, as in these examples:
+
+ (...(absolute)...)...(?2)...
+ (...(relative)...)...(?-1)...
+ (...(?+1)...(relative)...
+
+ An earlier example pointed out that the pattern
+
+ (sens|respons)e and \1ibility
+
+ matches "sense and sensibility" and "response and responsibility", but
+ not "sense and responsibility". If instead the pattern
+
+ (sens|respons)e and (?1)ibility
+
+ is used, it does match "sense and responsibility" as well as the other
+ two strings. Another example is given in the discussion of DEFINE
+ above.
+
+ Like recursions, subroutine calls used to be treated as atomic, but
+ this changed at PCRE2 release 10.30, so backtracking into subroutine
+ calls can now occur. However, any capturing parentheses that are set
+ during the subroutine call revert to their previous values afterwards.
+
+ Processing options such as case-independence are fixed when a group is
+ defined, so if it is used as a subroutine, such options cannot be
+ changed for different calls. For example, consider this pattern:
+
+ (abc)(?i:(?-1))
+
+ It matches "abcabc". It does not match "abcABC" because the change of
+ processing option does not affect the called group.
+
+ The behaviour of backtracking control verbs in groups when called as
+ subroutines is described in the section entitled "Backtracking verbs in
+ subroutines" below.
+
+ Recursion and subroutines with returned capture groups
+
+ Since PCRE2 10.47, recursion and subroutine calls may also specify a
+ list of capture groups to return. This is a PCRE2 syntax extension not
+ supported by Perl. The pattern matching recurses into the referenced
+ expression as described above, however, when the recursion returns to
+ the calling expression the subgroups captured during the recursion can
+ be retained when the calling expression's context is restored.
+
+ When used as a subroutine, this allows the subroutine's capture groups
+ to be used as return values.
+
+ Only the specific capture groups listed by the caller will be retained,
+ using the following syntax:
+
+ (?R(grouplist)) recurse whole pattern, returning capture groups
+ (?n(grouplist)) )
+ (?+n(grouplist)) )
+ (?-n(grouplist)) ) call subroutine, returning capture groups
+ (?&name(grouplist)) )
+ (?P>name(grouplist)) )
+
+ The list of capture groups "grouplist" is a comma-separated list of
+ (absolute or relative) group numbers, and group names enclosed in sin-
+ gle quotes or angle brackets.
+
+ Here is an example which first uses the DEFINE condition to create a
+ re-usable routine for matching a weekday, then calls that subroutine
+ and retains the groups it captures for use later:
+
+ (?x: # ignore whitespace for clarity
+ # Define the routine "weekendday" which matches Saturday or
+ # Sunday, and returns the Sat/Sun prefix as \k.
+ (?(DEFINE) (?
+ (?|(?Sat)urday|(?Sun)day) ) )
+ # Call the routine. Matches "Saturday,Sat" or "Sunday,Sun".
+ (?&weekendday()),\k )
+
+ This feature is not available using the Oniguruma syntax \g<...> or
+ \g'...' below.
+
+ Oniguruma subroutine syntax
+
+ For compatibility with Oniguruma, the non-Perl syntax \g followed by a
+ name or a number enclosed either in angle brackets or single quotes, is
+ an alternative syntax for calling a group as a subroutine, possibly re-
+ cursively. Here are two of the examples used above, rewritten using
+ this syntax:
+
+ (? \( ( (?>[^()]+) | \g )* \) )
+ (sens|respons)e and \g'1'ibility
+
+ PCRE2 supports an extension to Oniguruma: if a number is preceded by a
+ plus or a minus sign it is taken as a relative reference. For example:
+
+ (abc)(?i:\g<-1>)
+
+ Note that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are not
+ synonymous. The former is a backreference; the latter is a subroutine
+ call.
+
+
+CALLOUTS
+
+ Perl has a feature whereby using the sequence (?{...}) causes arbitrary
+ Perl code to be obeyed in the middle of matching a regular expression.
+ This makes it possible, amongst other things, to extract different sub-
+ strings that match the same pair of parentheses when there is a repeti-
+ tion.
+
+ PCRE2 provides a similar feature, but of course it cannot obey arbi-
+ trary Perl code. The feature is called "callout". The caller of PCRE2
+ provides an external function by putting its entry point in a match
+ context using the function pcre2_set_callout(), and then passing that
+ context to pcre2_match() or pcre2_dfa_match(). If no match context is
+ passed, or if the callout entry point is set to NULL, callout points
+ will be passed over silently during matching. To disallow callouts in
+ the pattern syntax, you may use the PCRE2_EXTRA_NEVER_CALLOUT option.
+
+ Within a regular expression, (?C) indicates a point at which the
+ external function is to be called. There are two kinds of callout:
+ those with a numerical argument and those with a string argument. (?C)
+ on its own with no argument is treated as (?C0). A numerical argument
+ allows the application to distinguish between different callouts.
+ String arguments were added for release 10.20 to make it possible for
+ script languages that use PCRE2 to embed short scripts within patterns
+ in a similar way to Perl.
+
+ During matching, when PCRE2 reaches a callout point, the external func-
+ tion is called. It is provided with the number or string argument of
+ the callout, the position in the pattern, and one item of data that is
+ also set in the match block. The callout function may cause matching to
+ proceed, to backtrack, or to fail.
+
+ By default, PCRE2 implements a number of optimizations at matching
+ time, and one side-effect is that sometimes callouts are skipped. If
+ you need all possible callouts to happen, you need to set options that
+ disable the relevant optimizations. More details, including a complete
+ description of the programming interface to the callout function, are
+ given in the pcre2callout documentation.
+
+ Callouts with numerical arguments
+
+ If you just want to have a means of identifying different callout
+ points, put a number less than 256 after the letter C. For example,
+ this pattern has two callout points:
+
+ (?C1)abc(?C2)def
+
+ If the PCRE2_AUTO_CALLOUT flag is passed to pcre2_compile(), numerical
+ callouts are automatically installed before each item in the pattern.
+ They are all numbered 255. If there is a conditional group in the pat-
+ tern whose condition is an assertion, an additional callout is inserted
+ just before the condition. An explicit callout may also be set at this
+ position, as in this example:
+
+ (?(?C9)(?=a)abc|def)
+
+ Note that this applies only to assertion conditions, not to other types
+ of condition.
+
+ Callouts with string arguments
+
+ A delimited string may be used instead of a number as a callout argu-
+ ment. The starting delimiter must be one of ` ' " ^ % # $ { and the
+ ending delimiter is the same as the start, except for {, where the end-
+ ing delimiter is }. If the ending delimiter is needed within the
+ string, it must be doubled. For example:
+
+ (?C'ab ''c'' d')xyz(?C{any text})pqr
+
+ The doubling is removed before the string is passed to the callout
+ function.
+
+
+BACKTRACKING CONTROL
+
+ There are a number of special "Backtracking Control Verbs" (to use
+ Perl's terminology) that modify the behaviour of backtracking during
+ matching. They are generally of the form (*VERB) or (*VERB:NAME). Some
+ verbs take either form, and may behave differently depending on whether
+ or not a name argument is present. The names are not required to be
+ unique within the pattern.
+
+ By default, for compatibility with Perl, a name is any sequence of
+ characters that does not include a closing parenthesis. The name is not
+ processed in any way, and it is not possible to include a closing
+ parenthesis in the name. This can be changed by setting the
+ PCRE2_ALT_VERBNAMES option, but the result is no longer Perl-compati-
+ ble.
+
+ When PCRE2_ALT_VERBNAMES is set, backslash processing is applied to
+ verb names and only an unescaped closing parenthesis terminates the
+ name. However, the only backslash items that are permitted are \Q, \E,
+ and sequences such as \x{100} that define character code points. Char-
+ acter type escapes such as \d are faulted.
+
+ A closing parenthesis can be included in a name either as \) or between
+ \Q and \E. In addition to backslash processing, if the PCRE2_EXTENDED
+ or PCRE2_EXTENDED_MORE option is also set, unescaped white space in
+ verb names is skipped, and #-comments are recognized, exactly as in the
+ rest of the pattern. PCRE2_EXTENDED and PCRE2_EXTENDED_MORE do not af-
+ fect verb names unless PCRE2_ALT_VERBNAMES is also set.
+
+ The maximum length of a name is 255 in the 8-bit library and 65535 in
+ the 16-bit and 32-bit libraries. If the name is empty, that is, if the
+ closing parenthesis immediately follows the colon, the effect is as if
+ the colon were not there. Any number of these verbs may occur in a pat-
+ tern. Except for (*ACCEPT), they may not be quantified.
+
+ Since these verbs are specifically related to backtracking, most of
+ them can be used only when the pattern is to be matched using the tra-
+ ditional matching function or JIT, because they use backtracking algo-
+ rithms. With the exception of (*FAIL), which behaves like a failing
+ negative assertion, the backtracking control verbs cause an error if
+ encountered by the DFA matching function.
+
+ The behaviour of these verbs in repeated groups, assertions, and in
+ capture groups called as subroutines (whether or not recursively) is
+ documented below.
+
+ Optimizations that affect backtracking verbs
+
+ PCRE2 contains some optimizations that are used to speed up matching by
+ running some checks at the start of each match attempt. For example, it
+ may know the minimum length of matching subject, or that a particular
+ character must be present. When one of these optimizations bypasses the
+ running of a match, any included backtracking verbs will not, of
+ course, be processed. You can suppress the start-of-match optimizations
+ by setting the PCRE2_NO_START_OPTIMIZE option when calling pcre2_com-
+ pile(), by calling pcre2_set_optimize() with a PCRE2_START_OPTIMIZE_OFF
+ directive, or by starting the pattern with (*NO_START_OPT). There is
+ more discussion of this option in the section entitled "Compiling a
+ pattern" in the pcre2api documentation.
+
+ Experiments with Perl suggest that it too has similar optimizations,
+ and like PCRE2, turning them off can change the result of a match.
+
+ Verbs that act immediately
+
+ The following verbs act as soon as they are encountered.
+
+ (*ACCEPT) or (*ACCEPT:NAME)
+
+ This verb causes the match to end successfully, skipping the remainder
+ of the pattern. However, when it is inside a capture group that is
+ called as a subroutine, only that group is ended successfully. Matching
+ then continues at the outer level. If (*ACCEPT) in triggered in a posi-
+ tive assertion, the assertion succeeds; in a negative assertion, the
+ assertion fails.
+
+ If (*ACCEPT) is inside capturing parentheses, the data so far is cap-
+ tured. For example:
+
+ A((?:A|B(*ACCEPT)|C)D)
+
+ This matches "AB", "AAD", or "ACD"; when it matches "AB", "B" is cap-
+ tured by the outer parentheses.
+
+ (*ACCEPT) is the only backtracking verb that is allowed to be quanti-
+ fied because an ungreedy quantification with a minimum of zero acts
+ only when a backtrack happens. Consider, for example,
+
+ (A(*ACCEPT)??B)C
+
+ where A, B, and C may be complex expressions. After matching "A", the
+ matcher processes "BC"; if that fails, causing a backtrack, (*ACCEPT)
+ is triggered and the match succeeds. In both cases, all but C is cap-
+ tured. Whereas (*COMMIT) (see below) means "fail on backtrack", a re-
+ peated (*ACCEPT) of this type means "succeed on backtrack".
+
+ Warning: (*ACCEPT) should not be used within a script run group, be-
+ cause it causes an immediate exit from the group, bypassing the script
+ run checking.
+
+ (*FAIL) or (*FAIL:NAME)
+
+ This verb causes a matching failure, forcing backtracking to occur. It
+ may be abbreviated to (*F). It is equivalent to (?!) but easier to
+ read. The Perl documentation notes that it is probably useful only when
+ combined with (?{}) or (??{}). Those are, of course, Perl features that
+ are not present in PCRE2. The nearest equivalent is the callout fea-
+ ture, as for example in this pattern:
+
+ a+(?C)(*FAIL)
+
+ A match with the string "aaaa" always fails, but the callout is taken
+ before each backtrack happens (in this example, 10 times).
+
+ (*ACCEPT:NAME) and (*FAIL:NAME) behave the same as (*MARK:NAME)(*AC-
+ CEPT) and (*MARK:NAME)(*FAIL), respectively, that is, a (*MARK) is
+ recorded just before the verb acts.
+
+ Recording which path was taken
+
+ There is one verb whose main purpose is to track how a match was ar-
+ rived at, though it also has a secondary use in conjunction with ad-
+ vancing the match starting point (see (*SKIP) below).
+
+ (*MARK:NAME) or (*:NAME)
+
+ A name is always required with this verb. For all the other backtrack-
+ ing control verbs, a NAME argument is optional.
+
+ When a match succeeds, the name of the last-encountered mark name on
+ the matching path is passed back to the caller as described in the sec-
+ tion entitled "Other information about the match" in the pcre2api docu-
+ mentation. This applies to all instances of (*MARK) and other verbs,
+ including those inside assertions and atomic groups. However, there are
+ differences in those cases when (*MARK) is used in conjunction with
+ (*SKIP) as described below.
+
+ The mark name that was last encountered on the matching path is passed
+ back. A verb without a NAME argument is ignored for this purpose. Here
+ is an example of pcre2test output, where the "mark" modifier requests
+ the retrieval and outputting of (*MARK) data:
+
+ re> /X(*MARK:A)Y|X(*MARK:B)Z/mark
+ data> XY
+ 0: XY
+ MK: A
+ XZ
+ 0: XZ
+ MK: B
+
+ The (*MARK) name is tagged with "MK:" in this output, and in this exam-
+ ple it indicates which of the two alternatives matched. This is a more
+ efficient way of obtaining this information than putting each alterna-
+ tive in its own capturing parentheses.
+
+ If a verb with a name is encountered in a positive assertion that is
+ true, the name is recorded and passed back if it is the last-encoun-
+ tered. This does not happen for negative assertions or failing positive
+ assertions.
+
+ After a partial match or a failed match, the last encountered name in
+ the entire match process is returned. For example:
+
+ re> /X(*MARK:A)Y|X(*MARK:B)Z/mark
+ data> XP
+ No match, mark = B
+
+ Note that in this unanchored example the mark is retained from the
+ match attempt that started at the letter "X" in the subject. Subsequent
+ match attempts starting at "P" and then with an empty string do not get
+ as far as the (*MARK) item, but nevertheless do not reset it.
+
+ If you are interested in (*MARK) values after failed matches, you
+ should probably either set the PCRE2_NO_START_OPTIMIZE option or call
+ pcre2_set_optimize() with a PCRE2_START_OPTIMIZE_OFF directive (see
+ above) to ensure that the match is always attempted.
+
+ Verbs that act after backtracking
+
+ The following verbs do nothing when they are encountered. Matching con-
+ tinues with what follows, but if there is a subsequent match failure,
+ causing a backtrack to the verb, a failure is forced. That is, back-
+ tracking cannot pass to the left of the verb. However, when one of
+ these verbs appears inside an atomic group or in an atomic lookaround
+ assertion that is true, its effect is confined to that group, because
+ once the group has been matched, there is never any backtracking into
+ it. Backtracking from beyond an atomic assertion or group ignores the
+ entire group, and seeks a preceding backtracking point.
+
+ These verbs differ in exactly what kind of failure occurs when back-
+ tracking reaches them. The behaviour described below is what happens
+ when the verb is not in a subroutine or an assertion. Subsequent sec-
+ tions cover these special cases.
+
+ (*COMMIT) or (*COMMIT:NAME)
+
+ This verb causes the whole match to fail outright if there is a later
+ matching failure that causes backtracking to reach it. Even if the pat-
+ tern is unanchored, no further attempts to find a match by advancing
+ the starting point take place. If (*COMMIT) is the only backtracking
+ verb that is encountered, once it has been passed pcre2_match() is com-
+ mitted to finding a match at the current starting point, or not at all.
+ For example:
+
+ a+(*COMMIT)b
+
+ This matches "xxaab" but not "aacaab". It can be thought of as a kind
+ of dynamic anchor, or "I've started, so I must finish."
+
+ The behaviour of (*COMMIT:NAME) is not the same as (*MARK:NAME)(*COM-
+ MIT). It is like (*MARK:NAME) in that the name is remembered for pass-
+ ing back to the caller. However, (*SKIP:NAME) searches only for names
+ that are set with (*MARK), ignoring those set by any of the other back-
+ tracking verbs.
+
+ If there is more than one backtracking verb in a pattern, a different
+ one that follows (*COMMIT) may be triggered first, so merely passing
+ (*COMMIT) during a match does not always guarantee that a match must be
+ at this starting point.
+
+ Note that (*COMMIT) at the start of a pattern is not the same as an an-
+ chor, unless PCRE2's start-of-match optimizations are turned off, as
+ shown in this output from pcre2test:
+
+ re> /(*COMMIT)abc/
+ data> xyzabc
+ 0: abc
+ data>
+ re> /(*COMMIT)abc/no_start_optimize
+ data> xyzabc
+ No match
+
+ For the first pattern, PCRE2 knows that any match must start with "a",
+ so the optimization skips along the subject to "a" before applying the
+ pattern to the first set of data. The match attempt then succeeds. The
+ second pattern disables the optimization that skips along to the first
+ character. The pattern is now applied starting at "x", and so the
+ (*COMMIT) causes the match to fail without trying any other starting
+ points.
+
+ (*PRUNE) or (*PRUNE:NAME)
+
+ This verb causes the match to fail at the current starting position in
+ the subject if there is a later matching failure that causes backtrack-
+ ing to reach it. If the pattern is unanchored, the normal "bumpalong"
+ advance to the next starting character then happens. Backtracking can
+ occur as usual to the left of (*PRUNE), before it is reached, or when
+ matching to the right of (*PRUNE), but if there is no match to the
+ right, backtracking cannot cross (*PRUNE). In simple cases, the use of
+ (*PRUNE) is just an alternative to an atomic group or possessive quan-
+ tifier, but there are some uses of (*PRUNE) that cannot be expressed in
+ any other way. In an anchored pattern (*PRUNE) has the same effect as
+ (*COMMIT).
+
+ The behaviour of (*PRUNE:NAME) is not the same as (*MARK:NAME)(*PRUNE).
+ It is like (*MARK:NAME) in that the name is remembered for passing back
+ to the caller. However, (*SKIP:NAME) searches only for names set with
+ (*MARK), ignoring those set by other backtracking verbs.
+
+ (*SKIP)
+
+ This verb, when given without a name, is like (*PRUNE), except that if
+ the pattern is unanchored, the "bumpalong" advance is not to the next
+ character, but to the position in the subject where (*SKIP) was encoun-
+ tered. (*SKIP) signifies that whatever text was matched leading up to
+ it cannot be part of a successful match if there is a later mismatch.
+ Consider:
+
+ a+(*SKIP)b
+
+ If the subject is "aaaac...", after the first match attempt fails
+ (starting at the first character in the string), the starting point
+ skips on to start the next attempt at "c". Note that a possessive quan-
+ tifier does not have the same effect as this example; although it would
+ suppress backtracking during the first match attempt, the second at-
+ tempt would start at the second character instead of skipping on to
+ "c".
+
+ If (*SKIP) is used to specify a new starting position that is the same
+ as the starting position of the current match, or (by being inside a
+ lookbehind) earlier, the position specified by (*SKIP) is ignored, and
+ instead the normal "bumpalong" occurs.
+
+ (*SKIP:NAME)
+
+ When (*SKIP) has an associated name, its behaviour is modified. When
+ such a (*SKIP) is triggered, the previous path through the pattern is
+ searched for the most recent (*MARK) that has the same name. If one is
+ found, the "bumpalong" advance is to the subject position that corre-
+ sponds to that (*MARK) instead of to where (*SKIP) was encountered. If
+ no (*MARK) with a matching name is found, the (*SKIP) is ignored.
+
+ The search for a (*MARK) name uses the normal backtracking mechanism,
+ which means that it does not see (*MARK) settings that are inside
+ atomic groups or assertions, because they are never re-entered by back-
+ tracking. Compare the following pcre2test examples:
+
+ re> /a(?>(*MARK:X))(*SKIP:X)(*F)|(.)/
+ data: abc
+ 0: a
+ 1: a
+ data:
+ re> /a(?:(*MARK:X))(*SKIP:X)(*F)|(.)/
+ data: abc
+ 0: b
+ 1: b
+
+ In the first example, the (*MARK) setting is in an atomic group, so it
+ is not seen when (*SKIP:X) triggers, causing the (*SKIP) to be ignored.
+ This allows the second branch of the pattern to be tried at the first
+ character position. In the second example, the (*MARK) setting is not
+ in an atomic group. This allows (*SKIP:X) to find the (*MARK) when it
+ backtracks, and this causes a new matching attempt to start at the sec-
+ ond character. This time, the (*MARK) is never seen because "a" does
+ not match "b", so the matcher immediately jumps to the second branch of
+ the pattern.
+
+ Note that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It
+ ignores names that are set by other backtracking verbs.
+
+ (*THEN) or (*THEN:NAME)
+
+ This verb causes a skip to the next innermost alternative when back-
+ tracking reaches it. That is, it cancels any further backtracking
+ within the current alternative. Its name comes from the observation
+ that it can be used for a pattern-based if-then-else block:
+
+ ( COND1 (*THEN) FOO | COND2 (*THEN) BAR | COND3 (*THEN) BAZ ) ...
+
+ If the COND1 pattern matches, FOO is tried (and possibly further items
+ after the end of the group if FOO succeeds); on failure, the matcher
+ skips to the second alternative and tries COND2, without backtracking
+ into COND1. If that succeeds and BAR fails, COND3 is tried. If subse-
+ quently BAZ fails, there are no more alternatives, so there is a back-
+ track to whatever came before the entire group. If (*THEN) is not in-
+ side an alternation, it acts like (*PRUNE).
+
+ The behaviour of (*THEN:NAME) is not the same as (*MARK:NAME)(*THEN).
+ It is like (*MARK:NAME) in that the name is remembered for passing back
+ to the caller. However, (*SKIP:NAME) searches only for names set with
+ (*MARK), ignoring those set by other backtracking verbs.
+
+ A group that does not contain a | character is just a part of the en-
+ closing alternative; it is not a nested alternation with only one al-
+ ternative. The effect of (*THEN) extends beyond such a group to the en-
+ closing alternative. Consider this pattern, where A, B, etc. are com-
+ plex pattern fragments that do not contain any | characters at this
+ level:
+
+ A (B(*THEN)C) | D
+
+ If A and B are matched, but there is a failure in C, matching does not
+ backtrack into A; instead it moves to the next alternative, that is, D.
+ However, if the group containing (*THEN) is given an alternative, it
+ behaves differently:
+
+ A (B(*THEN)C | (*FAIL)) | D
+
+ The effect of (*THEN) is now confined to the inner group. After a fail-
+ ure in C, matching moves to (*FAIL), which causes the whole group to
+ fail because there are no more alternatives to try. In this case,
+ matching does backtrack into A.
+
+ Note that a conditional group is not considered as having two alterna-
+ tives, because only one is ever used. In other words, the | character
+ in a conditional group has a different meaning. Ignoring white space,
+ consider:
+
+ ^.*? (?(?=a) a | b(*THEN)c )
+
+ If the subject is "ba", this pattern does not match. Because .*? is un-
+ greedy, it initially matches zero characters. The condition (?=a) then
+ fails, the character "b" is matched, but "c" is not. At this point,
+ matching does not backtrack to .*? as might perhaps be expected from
+ the presence of the | character. The conditional group is part of the
+ single alternative that comprises the whole pattern, and so the match
+ fails. (If there was a backtrack into .*?, allowing it to match "b",
+ the match would succeed.)
+
+ The verbs just described provide four different "strengths" of control
+ when subsequent matching fails. (*THEN) is the weakest, carrying on the
+ match at the next alternative. (*PRUNE) comes next, failing the match
+ at the current starting position, but allowing an advance to the next
+ character (for an unanchored pattern). (*SKIP) is similar, except that
+ the advance may be more than one character. (*COMMIT) is the strongest,
+ causing the entire match to fail.
+
+ More than one backtracking verb
+
+ If more than one backtracking verb is present in a pattern, the one
+ that is backtracked onto first acts. For example, consider this pat-
+ tern, where A, B, etc. are complex pattern fragments:
+
+ (A(*COMMIT)B(*THEN)C|ABD)
+
+ If A matches but B fails, the backtrack to (*COMMIT) causes the entire
+ match to fail. However, if A and B match, but C fails, the backtrack to
+ (*THEN) causes the next alternative (ABD) to be tried. This behaviour
+ is consistent, but is not always the same as Perl's. It means that if
+ two or more backtracking verbs appear in succession, all but the last
+ of them has no effect. Consider this example:
+
+ ...(*COMMIT)(*PRUNE)...
+
+ If there is a matching failure to the right, backtracking onto (*PRUNE)
+ causes it to be triggered, and its action is taken. There can never be
+ a backtrack onto (*COMMIT).
+
+ Backtracking verbs in repeated groups
+
+ PCRE2 sometimes differs from Perl in its handling of backtracking verbs
+ in repeated groups. For example, consider:
+
+ /(a(*COMMIT)b)+ac/
+
+ If the subject is "abac", Perl matches unless its optimizations are
+ disabled, but PCRE2 always fails because the (*COMMIT) in the second
+ repeat of the group acts.
+
+ Backtracking verbs in assertions
+
+ (*FAIL) in any assertion has its normal effect: it forces an immediate
+ backtrack. The behaviour of the other backtracking verbs depends on
+ whether or not the assertion is standalone or acting as the condition
+ in a conditional group.
+
+ (*ACCEPT) in a standalone positive assertion causes the assertion to
+ succeed without any further processing; captured strings and a mark
+ name (if set) are retained. In a standalone negative assertion, (*AC-
+ CEPT) causes the assertion to fail without any further processing; cap-
+ tured substrings and any mark name are discarded.
+
+ If the assertion is a condition, (*ACCEPT) causes the condition to be
+ true for a positive assertion and false for a negative one; captured
+ substrings are retained in both cases.
+
+ The remaining verbs act only when a later failure causes a backtrack to
+ reach them. This means that, for the Perl-compatible assertions, their
+ effect is confined to the assertion, because Perl lookaround assertions
+ are atomic. A backtrack that occurs after such an assertion is complete
+ does not jump back into the assertion. Note in particular that a
+ (*MARK) name that is set in an assertion is not "seen" by an instance
+ of (*SKIP:NAME) later in the pattern.
+
+ PCRE2 now supports non-atomic positive assertions and also "scan sub-
+ string" assertions, as described in the sections entitled "Non-atomic
+ assertions" and "Scan substring assertions" above. These assertions
+ must be standalone (not used as conditions). They are not Perl-compati-
+ ble. For these assertions, a later backtrack does jump back into the
+ assertion, and therefore verbs such as (*COMMIT) can be triggered by
+ backtracks from later in the pattern.
+
+ The effect of (*THEN) is not allowed to escape beyond an assertion. If
+ there are no more branches to try, (*THEN) causes a positive assertion
+ to be false, and a negative assertion to be true. This behaviour dif-
+ fers from Perl when the assertion has only one branch.
+
+ The other backtracking verbs are not treated specially if they appear
+ in a standalone positive assertion. In a conditional positive asser-
+ tion, backtracking (from within the assertion) into (*COMMIT), (*SKIP),
+ or (*PRUNE) causes the condition to be false. However, for both stand-
+ alone and conditional negative assertions, backtracking into (*COMMIT),
+ (*SKIP), or (*PRUNE) causes the assertion to be true, without consider-
+ ing any further alternative branches.
+
+ Backtracking verbs in subroutines
+
+ These behaviours occur whether or not the group is called recursively.
+
+ (*ACCEPT) in a group called as a subroutine causes the subroutine match
+ to succeed without any further processing. Matching then continues af-
+ ter the subroutine call. Perl documents this behaviour. Perl's treat-
+ ment of the other verbs in subroutines is different in some cases.
+
+ (*FAIL) in a group called as a subroutine has its normal effect: it
+ forces an immediate backtrack.
+
+ (*COMMIT), (*SKIP), and (*PRUNE) cause the subroutine match to fail
+ when triggered by being backtracked to in a group called as a subrou-
+ tine. There is then a backtrack at the outer level.
+
+ (*THEN), when triggered, skips to the next alternative in the innermost
+ enclosing group that has alternatives (its normal behaviour). However,
+ if there is no such group within the subroutine's group, the subroutine
+ match fails and there is a backtrack at the outer level.
+
+
+EBCDIC ENVIRONMENTS
+
+ Differences in the way PCRE behaves when it is running in an EBCDIC en-
+ vironment are covered in this section.
+
+ Escape sequences
+
+ When PCRE2 is compiled in EBCDIC mode, \N{U+hhh..} is not supported.
+ \a, \e, \f, \n, \r, and \t generate the appropriate EBCDIC code values.
+ The \c escape is processed as specified for Perl in the perlebcdic doc-
+ ument. The only characters that are allowed after \c are A-Z, a-z, or
+ one of @, [, \, ], ^, _, or ?. Any other character provokes a compile-
+ time error. The sequence \c@ encodes character code 0; after \c the
+ letters (in either case) encode characters 1-26 (hex 01 to hex 1A); [,
+ \, ], ^, and _ encode characters 27-31 (hex 1B to hex 1F), and \c? be-
+ comes either 255 (hex FF) or 95 (hex 5F).
+
+ Thus, apart from \c?, these escapes generate the same character code
+ values as they do in an ASCII or Unicode environment, though the mean-
+ ings of the values mostly differ. For example, \cG always generates
+ code value 7, which is BEL in ASCII but DEL in EBCDIC.
+
+ The sequence \c? generates DEL (127, hex 7F) in an ASCII environment,
+ but because 127 is not a control character in EBCDIC, Perl makes it
+ generate the APC character. Unfortunately, there are several variants
+ of EBCDIC. In most of them the APC character has the value 255 (hex
+ FF), but in the one Perl calls POSIX-BC its value is 95 (hex 5F). If
+ certain other characters have POSIX-BC values, PCRE2 makes \c? generate
+ 95; otherwise it generates 255.
+
+ Character classes
+
+ In character classes there is a special case in EBCDIC environments for
+ ranges whose end points are both specified as literal letters in the
+ same case. For compatibility with Perl, EBCDIC code points within the
+ range that are not letters are omitted. For example, [h-k] matches only
+ four characters, even though the EBCDIC codes for h and k are 0x88 and
+ 0x92, a range of 11 code points. However, if the range is specified nu-
+ merically, for example, [\x88-\x92] or [h-\x92], all code points are
+ included.
+
+
+SEE ALSO
+
+ pcre2api(3), pcre2callout(3), pcre2matching(3), pcre2syntax(3),
+ pcre2(3).
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 25 October 2025
+ Copyright (c) 1997-2024 University of Cambridge.
+
+
+PCRE2 10.48 25 October 2025 PCRE2PATTERN(3)
+------------------------------------------------------------------------------
+
+
+PCRE2PERFORM(3) Library Functions Manual PCRE2PERFORM(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+
+PCRE2 PERFORMANCE
+
+ Two aspects of performance are discussed below: memory usage and pro-
+ cessing time. The way you express your pattern as a regular expression
+ can affect both of them.
+
+
+COMPILED PATTERN MEMORY USAGE
+
+ Patterns are compiled by PCRE2 into a reasonably efficient interpretive
+ code, so that most simple patterns do not use much memory for storing
+ the compiled version. However, there is one case where the memory usage
+ of a compiled pattern can be unexpectedly large. If a parenthesized
+ group has a quantifier with a minimum greater than 1 and/or a limited
+ maximum, the whole group is repeated in the compiled code. For example,
+ the pattern
+
+ (abc|def){2,4}
+
+ is compiled as if it were
+
+ (abc|def)(abc|def)((abc|def)(abc|def)?)?
+
+ (Technical aside: It is done this way so that backtrack points within
+ each of the repetitions can be independently maintained.)
+
+ For regular expressions whose quantifiers use only small numbers, this
+ is not usually a problem. However, if the numbers are large, and par-
+ ticularly if such repetitions are nested, the memory usage can become
+ an embarrassment. For example, the very simple pattern
+
+ ((ab){1,1000}c){1,3}
+
+ uses over 50KiB when compiled using the 8-bit library. When PCRE2 is
+ compiled with its default internal pointer size of two bytes, the size
+ limit on a compiled pattern is 65535 code units in the 8-bit and 16-bit
+ libraries, and this is reached with the above pattern if the outer rep-
+ etition is increased from 3 to 4. PCRE2 can be compiled to use larger
+ internal pointers and thus handle larger compiled patterns, but it is
+ better to try to rewrite your pattern to use less memory if you can.
+
+ One way of reducing the memory usage for such patterns is to make use
+ of PCRE2's "subroutine" facility. Re-writing the above pattern as
+
+ ((ab)(?2){0,999}c)(?1){0,2}
+
+ reduces the memory requirements to around 16KiB, and indeed it remains
+ under 20KiB even with the outer repetition increased to 100. However,
+ this kind of pattern is not always exactly equivalent, because any cap-
+ tures within subroutine calls are lost when the subroutine completes.
+ If this is not a problem, this kind of rewriting will allow you to
+ process patterns that PCRE2 cannot otherwise handle. The matching per-
+ formance of the two different versions of the pattern are roughly the
+ same. (This applies from release 10.30 - things were different in ear-
+ lier releases.)
+
+
+STACK AND HEAP USAGE AT RUN TIME
+
+ From release 10.30, the interpretive (non-JIT) version of pcre2_match()
+ uses very little system stack at run time. In earlier releases recur-
+ sive function calls could use a great deal of stack, and this could
+ cause problems, but this usage has been eliminated. Backtracking posi-
+ tions are now explicitly remembered in memory frames controlled by the
+ code.
+
+ The size of each frame depends on the size of pointer variables and the
+ number of capturing parenthesized groups in the pattern being matched.
+ On a 64-bit system the frame size for a pattern with no captures is 128
+ bytes. For each capturing group the size increases by 16 bytes.
+
+ Until release 10.41, an initial 20KiB frames vector was allocated on
+ the system stack, but this still caused some issues for multi-thread
+ applications where each thread has a very small stack. From release
+ 10.41 backtracking memory frames are always held in heap memory. An
+ initial heap allocation is obtained the first time any match data block
+ is passed to pcre2_match(). This is remembered with the match data
+ block and re-used if that block is used for another match. It is freed
+ when the match data block itself is freed.
+
+ The size of the initial block is the larger of 20KiB or ten times the
+ pattern's frame size, unless the heap limit is less than this, in which
+ case the heap limit is used. If the initial block proves to be too
+ small during matching, it is replaced by a larger block, subject to the
+ heap limit. The heap limit is checked only when a new block is to be
+ allocated. Reducing the heap limit between calls to pcre2_match() with
+ the same match data block does not affect the saved block.
+
+ In contrast to pcre2_match(), pcre2_dfa_match() does use recursive
+ function calls, but only for processing atomic groups, lookaround as-
+ sertions, and recursion within the pattern. The original version of the
+ code used to allocate quite large internal workspace vectors on the
+ stack, which caused some problems for some patterns in environments
+ with small stacks. From release 10.32 the code for pcre2_dfa_match()
+ has been re-factored to use heap memory when necessary for internal
+ workspace when recursing, though recursive function calls are still
+ used.
+
+ The "match depth" parameter can be used to limit the depth of function
+ recursion, and the "match heap" parameter to limit heap memory in
+ pcre2_dfa_match().
+
+
+PROCESSING TIME
+
+ Certain items in regular expression patterns are processed more effi-
+ ciently than others. It is more efficient to use a character class like
+ [aeiou] than a set of single-character alternatives such as
+ (a|e|i|o|u). In general, the simplest construction that provides the
+ required behaviour is usually the most efficient. Jeffrey Friedl's book
+ contains a lot of useful general discussion about optimizing regular
+ expressions for efficient performance. This document contains a few ob-
+ servations about PCRE2.
+
+ Using Unicode character properties (the \p, \P, and \X escapes) is
+ slow, because PCRE2 has to use a multi-stage table lookup whenever it
+ needs a character's property. If you can find an alternative pattern
+ that does not use character properties, it will probably be faster.
+
+ By default, the escape sequences \b, \d, \s, and \w, and the POSIX
+ character classes such as [:alpha:] do not use Unicode properties,
+ partly for backwards compatibility, and partly for performance reasons.
+ However, you can set the PCRE2_UCP option or start the pattern with
+ (*UCP) if you want Unicode character properties to be used. This can
+ double the matching time for items such as \d, when matched with
+ pcre2_match(); the performance loss is less with a DFA matching func-
+ tion, and in both cases there is not much difference for \b.
+
+ When a pattern begins with .* not in atomic parentheses, nor in paren-
+ theses that are the subject of a backreference, and the PCRE2_DOTALL
+ option is set, the pattern is implicitly anchored by PCRE2, since it
+ can match only at the start of a subject string. If the pattern has
+ multiple top-level branches, they must all be anchorable. The optimiza-
+ tion can be disabled by the PCRE2_NO_DOTSTAR_ANCHOR option, and is au-
+ tomatically disabled if the pattern contains (*PRUNE) or (*SKIP).
+
+ If PCRE2_DOTALL is not set, PCRE2 cannot make this optimization, be-
+ cause the dot metacharacter does not then match a newline, and if the
+ subject string contains newlines, the pattern may match from the char-
+ acter immediately following one of them instead of from the very start.
+ For example, the pattern
+
+ .*second
+
+ matches the subject "first\nand second" (where \n stands for a newline
+ character), with the match starting at the seventh character. In order
+ to do this, PCRE2 has to retry the match starting after every newline
+ in the subject.
+
+ If you are using such a pattern with subject strings that do not con-
+ tain newlines, the best performance is obtained by setting
+ PCRE2_DOTALL, or starting the pattern with ^.* or ^.*? to indicate ex-
+ plicit anchoring. That saves PCRE2 from having to scan along the sub-
+ ject looking for a newline to restart at.
+
+ Beware of patterns that contain nested indefinite repeats. These can
+ take a long time to run when applied to a string that does not match.
+ Consider the pattern fragment
+
+ ^(a+)*
+
+ This can match "aaaa" in 16 different ways, and this number increases
+ very rapidly as the string gets longer. (The * repeat can match 0, 1,
+ 2, 3, or 4 times, and for each of those cases other than 0 or 4, the +
+ repeats can match different numbers of times.) When the remainder of
+ the pattern is such that the entire match is going to fail, PCRE2 has
+ in principle to try every possible variation, and this can take an ex-
+ tremely long time, even for relatively short strings.
+
+ An optimization catches some of the more simple cases such as
+
+ (a+)*b
+
+ where a literal character follows. Before embarking on the standard
+ matching procedure, PCRE2 checks that there is a "b" later in the sub-
+ ject string, and if there is not, it fails the match immediately. How-
+ ever, when there is no following literal this optimization cannot be
+ used. You can see the difference by comparing the behaviour of
+
+ (a+)*\d
+
+ with the pattern above. The former gives a failure almost instantly
+ when applied to a whole line of "a" characters, whereas the latter
+ takes an appreciable time with strings longer than about 20 characters.
+
+ In many cases, the solution to this kind of performance issue is to use
+ an atomic group or a possessive quantifier. This can often reduce mem-
+ ory requirements as well. As another example, consider this pattern:
+
+ ([^<]|<(?!inet))+
+
+ It matches from wherever it starts until it encounters "
+
+ int pcre2_regcomp(regex_t *preg, const char *pattern,
+ int cflags);
+
+ int pcre2_regexec(const regex_t *preg, const char *string,
+ size_t nmatch, regmatch_t pmatch[], int eflags);
+
+ size_t pcre2_regerror(int errcode, const regex_t *preg,
+ char *errbuf, size_t errbuf_size);
+
+ void pcre2_regfree(regex_t *preg);
+
+
+DESCRIPTION
+
+ This set of functions provides a POSIX-style API for the PCRE2 regular
+ expression 8-bit library. There are no POSIX-style wrappers for PCRE2's
+ 16-bit and 32-bit libraries. See the pcre2api documentation for a de-
+ scription of PCRE2's native API, which contains much additional func-
+ tionality.
+
+ IMPORTANT NOTE: The functions described here are NOT thread-safe, and
+ should not be used in multi-threaded applications. They are also lim-
+ ited to processing subjects that are not bigger than 2GB. Use the na-
+ tive API instead.
+
+ These functions are wrapper functions that ultimately call the PCRE2
+ native API. Their prototypes are defined in the pcre2posix.h header
+ file, and they all have unique names starting with pcre2_. However, the
+ pcre2posix.h header also contains macro definitions that convert the
+ standard POSIX names such regcomp() into pcre2_regcomp() etc. This
+ means that a program can use the usual POSIX names without running the
+ risk of accidentally linking with POSIX functions from a different li-
+ brary.
+
+ On Unix-like systems the PCRE2 POSIX library is called libpcre2-posix,
+ so can be accessed by adding -lpcre2-posix to the command for linking
+ an application. Because the POSIX functions call the native ones, it is
+ also necessary to add -lpcre2-8.
+
+ On Windows systems, if you are linking to a DLL version of the library,
+ it is recommended that PCRE2POSIX_SHARED is defined before including
+ the pcre2posix.h header, as it will allow for a more efficient way to
+ invoke the functions by adding the __declspec(dllimport) decorator.
+
+ Although they were not defined as prototypes in pcre2posix.h, releases
+ 10.33 to 10.36 of the library contained functions with the POSIX names
+ regcomp() etc. These simply passed their arguments to the PCRE2 func-
+ tions. These functions were provided for backwards compatibility with
+ earlier versions of PCRE2, which had only POSIX names. However, this
+ has proved troublesome in situations where a program links with several
+ libraries, some of which use PCRE2's POSIX interface while others use
+ the real POSIX functions. For this reason, the POSIX names have been
+ removed since release 10.37.
+
+ Calling the header file pcre2posix.h avoids any conflict with other
+ POSIX libraries. It can, of course, be renamed or aliased as regex.h,
+ which is the "correct" name, if there is no clash. It provides two
+ structure types, regex_t for compiled internal forms, and regmatch_t
+ for returning captured substrings. It also defines some constants whose
+ names start with "REG_"; these are used for setting options and identi-
+ fying error codes.
+
+
+USING THE POSIX FUNCTIONS
+
+ Note that these functions are just POSIX-style wrappers for PCRE2's na-
+ tive API. They do not give POSIX regular expression behaviour, and
+ they are not thread-safe or even POSIX compatible.
+
+ Those POSIX option bits that can reasonably be mapped to PCRE2 native
+ options have been implemented. In addition, the option REG_EXTENDED is
+ defined with the value zero. This has no effect, but since programs
+ that are written to the POSIX interface often use it, this makes it
+ easier to slot in PCRE2 as a replacement library. Other POSIX options
+ are not even defined.
+
+ There are also some options that are not defined by POSIX. These have
+ been added at the request of users who want to make use of certain
+ PCRE2-specific features via the POSIX calling interface or to add BSD
+ or GNU functionality.
+
+ When PCRE2 is called via these functions, it is only the API that is
+ POSIX-like in style. The syntax and semantics of the regular expres-
+ sions themselves are still those of Perl, subject to the setting of
+ various PCRE2 options, as described below. "POSIX-like in style" means
+ that the API approximates to the POSIX definition; it is not fully
+ POSIX-compatible, and in multi-unit encoding domains it is probably
+ even less compatible.
+
+ The descriptions below use the actual names of the functions, but, as
+ described above, the standard POSIX names (without the pcre2_ prefix)
+ may also be used.
+
+
+COMPILING A PATTERN
+
+ The function pcre2_regcomp() is called to compile a pattern into an in-
+ ternal form. By default, the pattern is a C string terminated by a bi-
+ nary zero (but see REG_PEND below). The preg argument is a pointer to a
+ regex_t structure that is used as a base for storing information about
+ the compiled regular expression. It is also used for input when
+ REG_PEND is set. The regex_t structure used by pcre2_regcomp() is de-
+ fined in pcre2posix.h and is not the same as the structure used by
+ other libraries that provide POSIX-style matching.
+
+ The argument cflags is either zero, or contains one or more of the bits
+ defined by the following macros:
+
+ REG_DOTALL
+
+ The PCRE2_DOTALL option is set when the regular expression is passed
+ for compilation to the native function. Note that REG_DOTALL is not
+ part of the POSIX standard.
+
+ REG_ICASE
+
+ The PCRE2_CASELESS option is set when the regular expression is passed
+ for compilation to the native function.
+
+ REG_NEWLINE
+
+ The PCRE2_MULTILINE option is set when the regular expression is passed
+ for compilation to the native function. Note that this does not mimic
+ the defined POSIX behaviour for REG_NEWLINE (see the following sec-
+ tion).
+
+ REG_NOSPEC
+
+ The PCRE2_LITERAL option is set when the regular expression is passed
+ for compilation to the native function. This disables all meta charac-
+ ters in the pattern, causing it to be treated as a literal string. The
+ only other options that are allowed with REG_NOSPEC are REG_ICASE,
+ REG_NOSUB, REG_PEND, and REG_UTF. Note that REG_NOSPEC is not part of
+ the POSIX standard.
+
+ REG_NOSUB
+
+ When a pattern that is compiled with this flag is passed to
+ pcre2_regexec() for matching, the nmatch and pmatch arguments are ig-
+ nored, and no captured strings are returned. Versions of the PCRE2 li-
+ brary prior to 10.22 used to set the PCRE2_NO_AUTO_CAPTURE compile op-
+ tion, but this no longer happens because it disables the use of back-
+ references.
+
+ REG_PEND
+
+ If this option is set, the reg_endp field in the preg structure (which
+ has the type const char *) must be set to point to the character beyond
+ the end of the pattern before calling pcre2_regcomp(). The pattern it-
+ self may now contain binary zeros, which are treated as data charac-
+ ters. Without REG_PEND, a binary zero terminates the pattern and the
+ re_endp field is ignored. This is a GNU extension to the POSIX standard
+ and should be used with caution in software intended to be portable to
+ other systems.
+
+ REG_UCP
+
+ The PCRE2_UCP option is set when the regular expression is passed for
+ compilation to the native function. This causes PCRE2 to use Unicode
+ properties when matching \d, \w, etc., instead of just recognizing
+ ASCII values. Note that REG_UCP is not part of the POSIX standard.
+
+ REG_UNGREEDY
+
+ The PCRE2_UNGREEDY option is set when the regular expression is passed
+ for compilation to the native function. Note that REG_UNGREEDY is not
+ part of the POSIX standard.
+
+ REG_UTF
+
+ The PCRE2_UTF option is set when the regular expression is passed for
+ compilation to the native function. This causes the pattern itself and
+ all data strings used for matching it to be treated as UTF-8 strings.
+ Note that REG_UTF is not part of the POSIX standard.
+
+ In the absence of these flags, no options are passed to the native
+ function. This means that the regex is compiled with PCRE2 default se-
+ mantics. In particular, the way it handles newline characters in the
+ subject string is the Perl way, not the POSIX way. Note that setting
+ PCRE2_MULTILINE has only some of the effects specified for REG_NEWLINE.
+ It does not affect the way newlines are matched by the dot metacharac-
+ ter (they are not) or by a negative class such as [^a] (they are).
+
+ The yield of pcre2_regcomp() is zero on success, and non-zero other-
+ wise. The preg structure is filled in on success, and one other member
+ of the structure (as well as re_endp) is public: re_nsub contains the
+ number of capturing subpatterns in the regular expression. Various er-
+ ror codes are defined in the header file.
+
+ NOTE: If the yield of pcre2_regcomp() is non-zero, you must not attempt
+ to use the contents of the preg structure. If, for example, you pass it
+ to pcre2_regexec(), the result is undefined and your program is likely
+ to crash.
+
+
+MATCHING NEWLINE CHARACTERS
+
+ This area is not simple, because POSIX and Perl take different views of
+ things. It is not possible to get PCRE2 to obey POSIX semantics, but
+ then PCRE2 was never intended to be a POSIX engine. The following table
+ lists the different possibilities for matching newline characters in
+ Perl and PCRE2:
+
+ Default Change with
+
+ . matches newline no PCRE2_DOTALL
+ newline matches [^a] yes not changeable
+ $ matches \n at end yes PCRE2_DOLLAR_ENDONLY
+ $ matches \n in middle no PCRE2_MULTILINE
+ ^ matches \n in middle no PCRE2_MULTILINE
+
+ This is the equivalent table for a POSIX-compatible pattern matcher:
+
+ Default Change with
+
+ . matches newline yes REG_NEWLINE
+ newline matches [^a] yes REG_NEWLINE
+ $ matches \n at end no REG_NEWLINE
+ $ matches \n in middle no REG_NEWLINE
+ ^ matches \n in middle no REG_NEWLINE
+
+ This behaviour is not what happens when PCRE2 is called via its POSIX
+ API. By default, PCRE2's behaviour is the same as Perl's, except that
+ there is no equivalent for PCRE2_DOLLAR_ENDONLY in Perl. In both PCRE2
+ and Perl, there is no way to stop newline from matching [^a].
+
+ Default POSIX newline handling can be obtained by setting PCRE2_DOTALL
+ and PCRE2_DOLLAR_ENDONLY when calling pcre2_compile() directly, but
+ there is no way to make PCRE2 behave exactly as for the REG_NEWLINE ac-
+ tion. When using the POSIX API, passing REG_NEWLINE to PCRE2's
+ pcre2_regcomp() function causes PCRE2_MULTILINE to be passed to
+ pcre2_compile(), and REG_DOTALL passes PCRE2_DOTALL. There is no way to
+ pass PCRE2_DOLLAR_ENDONLY.
+
+
+MATCHING A PATTERN
+
+ The function pcre2_regexec() is called to match a compiled pattern preg
+ against a given string, which is by default terminated by a zero byte
+ (but see REG_STARTEND below), subject to the options in eflags. These
+ can be:
+
+ REG_NOTBOL
+
+ The PCRE2_NOTBOL option is set when calling the underlying PCRE2 match-
+ ing function.
+
+ REG_NOTEMPTY
+
+ The PCRE2_NOTEMPTY option is set when calling the underlying PCRE2
+ matching function. Note that REG_NOTEMPTY is not part of the POSIX
+ standard. However, setting this option can give more POSIX-like behav-
+ iour in some situations.
+
+ REG_NOTEOL
+
+ The PCRE2_NOTEOL option is set when calling the underlying PCRE2 match-
+ ing function.
+
+ REG_STARTEND
+
+ When this option is set, the subject string starts at string +
+ pmatch[0].rm_so and ends at string + pmatch[0].rm_eo, which should
+ point to the first character beyond the string. There may be binary ze-
+ ros within the subject string, and indeed, using REG_STARTEND is the
+ only way to pass a subject string that contains a binary zero.
+
+ Whatever the value of pmatch[0].rm_so, the offsets of the matched
+ string and any captured substrings are still given relative to the
+ start of string itself. (Before PCRE2 release 10.30 these were given
+ relative to string + pmatch[0].rm_so, but this differs from other im-
+ plementations.)
+
+ This is a BSD extension, compatible with but not specified by IEEE
+ Standard 1003.2 (POSIX.2), and should be used with caution in software
+ intended to be portable to other systems. Note that a non-zero rm_so
+ does not imply REG_NOTBOL; REG_STARTEND affects only the location and
+ length of the string, not how it is matched. Setting REG_STARTEND and
+ passing pmatch as NULL are mutually exclusive; the error REG_INVARG is
+ returned.
+
+ If the pattern was compiled with the REG_NOSUB flag, no data about any
+ matched strings is returned. The nmatch and pmatch arguments of
+ pcre2_regexec() are ignored (except possibly as input for REG_STAR-
+ TEND).
+
+ The value of nmatch may be zero, and the value pmatch may be NULL (un-
+ less REG_STARTEND is set); in both these cases no data about any
+ matched strings is returned.
+
+ Otherwise, the portion of the string that was matched, and also any
+ captured substrings, are returned via the pmatch argument, which points
+ to an array of nmatch structures of type regmatch_t, containing the
+ members rm_so and rm_eo. These contain the byte offset to the first
+ character of each substring and the offset to the first character after
+ the end of each substring, respectively. The 0th element of the vector
+ relates to the entire portion of string that was matched; subsequent
+ elements relate to the capturing subpatterns of the regular expression.
+ Unused entries in the array have both structure members set to -1.
+
+ regmatch_t as well as the regoff_t typedef it uses are defined in
+ pcre2posix.h and are not warranted to have the same size or layout as
+ other similarly named types from other libraries that provide POSIX-
+ style matching.
+
+ A successful match yields a zero return; various error codes are de-
+ fined in the header file, of which REG_NOMATCH is the "expected" fail-
+ ure code.
+
+
+ERROR MESSAGES
+
+ The pcre2_regerror() function maps a non-zero errorcode from either
+ pcre2_regcomp() or pcre2_regexec() to a printable message. If preg is
+ not NULL, the error should have arisen from the use of that structure.
+ A message terminated by a binary zero is placed in errbuf. If the
+ buffer is too short, only the first errbuf_size - 1 characters of the
+ error message are used. The yield of the function is the size of buffer
+ needed to hold the whole message, including the terminating zero. This
+ value is greater than errbuf_size if the message was truncated.
+
+
+MEMORY USAGE
+
+ Compiling a regular expression causes memory to be allocated and asso-
+ ciated with the preg structure. The function pcre2_regfree() frees all
+ such memory, after which preg may no longer be used as a compiled ex-
+ pression.
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 27 November 2024
+ Copyright (c) 1997-2024 University of Cambridge.
+
+
+PCRE2 10.48 27 November 2024 PCRE2POSIX(3)
+------------------------------------------------------------------------------
+
+
+PCRE2SAMPLE(3) Library Functions Manual PCRE2SAMPLE(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+
+PCRE2 SAMPLE PROGRAM
+
+ A simple, complete demonstration program to get you started with using
+ PCRE2 is supplied in the file pcre2demo.c in the src directory in the
+ PCRE2 distribution. A listing of this program is given in the pcre2demo
+ documentation. If you do not have a copy of the PCRE2 distribution, you
+ can save this listing to recreate the contents of pcre2demo.c.
+
+ The demonstration program compiles the regular expression that is its
+ first argument, and matches it against the subject string in its second
+ argument. No PCRE2 options are set, and default character tables are
+ used. If matching succeeds, the program outputs the portion of the sub-
+ ject that matched, together with the contents of any captured sub-
+ strings.
+
+ If the -g option is given on the command line, the program then goes on
+ to check for further matches of the same regular expression in the same
+ subject string. The logic is a little bit tricky because of the possi-
+ bility of matching an empty string. Comments in the code explain what
+ is going on.
+
+ The code in pcre2demo.c is an 8-bit program that uses the PCRE2 8-bit
+ library. It handles strings and characters that are stored in 8-bit
+ code units. By default, one character corresponds to one code unit,
+ but if the pattern starts with "(*UTF)", both it and the subject are
+ treated as UTF-8 strings, where characters may occupy multiple code
+ units.
+
+ If PCRE2 is installed in the standard include and library directories
+ for your operating system, you should be able to compile the demonstra-
+ tion program using a command like this:
+
+ cc -o pcre2demo pcre2demo.c -lpcre2-8
+
+ If PCRE2 is installed elsewhere, you may need to add additional options
+ to the command line. For example, on a Unix-like system that has PCRE2
+ installed in /usr/local, you can compile the demonstration program us-
+ ing a command like this:
+
+ cc -o pcre2demo -I/usr/local/include pcre2demo.c \
+ -L/usr/local/lib -lpcre2-8
+
+ Once you have built the demonstration program, you can run simple tests
+ like this:
+
+ ./pcre2demo 'cat|dog' 'the cat sat on the mat'
+ ./pcre2demo -g 'cat|dog' 'the dog sat on the cat'
+ ./pcre2demo -i 'cat' 'the dog sat on the CAT'
+
+ Note that there is a much more comprehensive test program, called
+ pcre2test, which supports many more facilities for testing regular ex-
+ pressions using all three PCRE2 libraries (8-bit, 16-bit, and 32-bit,
+ though not all three need be installed). The pcre2demo program is pro-
+ vided as a relatively simple coding example.
+
+ If you try to run pcre2demo when PCRE2 is not installed in the standard
+ library directory, you may get an error like this on some operating
+ systems (e.g. Solaris):
+
+ ld.so.1: pcre2demo: fatal: libpcre2-8.so.0: open failed: No such file
+ or directory
+
+ This is caused by the way shared library support works on those sys-
+ tems. You need to add
+
+ -R/usr/local/lib
+
+ (for example) to the compile command to get round this problem.
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 28 February 2025
+ Copyright (c) 1997-2016 University of Cambridge.
+
+
+PCRE2 10.48 28 February 2025 PCRE2SAMPLE(3)
+------------------------------------------------------------------------------
+PCRE2SERIALIZE(3) Library Functions Manual PCRE2SERIALIZE(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+
+SAVING AND RE-USING PRECOMPILED PCRE2 PATTERNS
+
+ int32_t pcre2_serialize_decode(pcre2_code **codes,
+ int32_t number_of_codes, const uint8_t *bytes,
+ pcre2_general_context *gcontext);
+
+ int32_t pcre2_serialize_encode(const pcre2_code **codes,
+ int32_t number_of_codes, uint8_t **serialized_bytes,
+ PCRE2_SIZE *serialized_size, pcre2_general_context *gcontext);
+
+ void pcre2_serialize_free(uint8_t *bytes);
+
+ int32_t pcre2_serialize_get_number_of_codes(const uint8_t *bytes);
+
+ If you are running an application that uses a large number of regular
+ expression patterns, it may be useful to store them in a precompiled
+ form instead of having to compile them every time the application is
+ run. However, if you are using the just-in-time optimization feature,
+ it is not possible to save and reload the JIT data, because it is posi-
+ tion-dependent. The host on which the patterns are reloaded must be
+ running the same version of PCRE2, with the same code unit width, and
+ must also have the same endianness, pointer width and PCRE2_SIZE type.
+ For example, patterns compiled on a 32-bit system using PCRE2's 16-bit
+ library cannot be reloaded on a 64-bit system, nor can they be reloaded
+ using the 8-bit library.
+
+ Note that "serialization" in PCRE2 does not convert compiled patterns
+ to an abstract format like Java or .NET serialization. The serialized
+ output is really just a bytecode dump, which is why it can only be re-
+ loaded in the same environment as the one that created it. Hence the
+ restrictions mentioned above. Applications that are not statically
+ linked with a fixed version of PCRE2 must be prepared to recompile pat-
+ terns from their sources, in order to be immune to PCRE2 upgrades.
+
+
+SECURITY CONCERNS
+
+ The facility for saving and restoring compiled patterns is intended for
+ use within individual applications. As such, the data supplied to
+ pcre2_serialize_decode() is expected to be trusted data, not data from
+ arbitrary external sources. There is only some simple consistency
+ checking, not complete validation of what is being re-loaded. Corrupted
+ data may cause undefined results. For example, if the length field of a
+ pattern in the serialized data is corrupted, the deserializing code may
+ read beyond the end of the byte stream that is passed to it.
+
+
+SAVING COMPILED PATTERNS
+
+ Before compiled patterns can be saved they must be serialized, which in
+ PCRE2 means converting the pattern to a stream of bytes. A single byte
+ stream may contain any number of compiled patterns, but they must all
+ use the same character tables. A single copy of the tables is included
+ in the byte stream (its size is 1088 bytes). For more details of char-
+ acter tables, see the section on locale support in the pcre2api docu-
+ mentation.
+
+ The function pcre2_serialize_encode() creates a serialized byte stream
+ from a list of compiled patterns. Its first two arguments specify the
+ list, being a pointer to a vector of pointers to compiled patterns, and
+ the length of the vector. The third and fourth arguments point to vari-
+ ables which are set to point to the created byte stream and its length,
+ respectively. The final argument is a pointer to a general context,
+ which can be used to specify custom memory management functions. If
+ this argument is NULL, malloc() is used to obtain memory for the byte
+ stream. The yield of the function is the number of serialized patterns,
+ or one of the following negative error codes:
+
+ PCRE2_ERROR_BADDATA the number of patterns is zero or less
+ PCRE2_ERROR_BADMAGIC mismatch of id bytes in one of the patterns
+ PCRE2_ERROR_NOMEMORY memory allocation failed
+ PCRE2_ERROR_MIXEDTABLES the patterns do not all use the same tables
+ PCRE2_ERROR_NULL the 1st, 3rd, or 4th argument is NULL
+
+ PCRE2_ERROR_BADMAGIC means either that a pattern's code has been cor-
+ rupted, or that a slot in the vector does not point to a compiled pat-
+ tern.
+
+ Once a set of patterns has been serialized you can save the data in any
+ appropriate manner. Here is sample code that compiles two patterns and
+ writes them to a file. It assumes that the variable fd refers to a file
+ that is open for output. The error checking that should be present in a
+ real application has been omitted for simplicity.
+
+ int errorcode;
+ uint8_t *bytes;
+ PCRE2_SIZE erroroffset;
+ PCRE2_SIZE bytescount;
+ pcre2_code *list_of_codes[2];
+ list_of_codes[0] = pcre2_compile("first pattern",
+ PCRE2_ZERO_TERMINATED, 0, &errorcode, &erroroffset, NULL);
+ list_of_codes[1] = pcre2_compile("second pattern",
+ PCRE2_ZERO_TERMINATED, 0, &errorcode, &erroroffset, NULL);
+ errorcode = pcre2_serialize_encode(list_of_codes, 2, &bytes,
+ &bytescount, NULL);
+ errorcode = fwrite(bytes, 1, bytescount, fd);
+
+ Note that the serialized data is binary data that may contain any of
+ the 256 possible byte values. On systems that make a distinction be-
+ tween binary and non-binary data, be sure that the file is opened for
+ binary output.
+
+ Serializing a set of patterns leaves the original data untouched, so
+ they can still be used for matching. Their memory must eventually be
+ freed in the usual way by calling pcre2_code_free(). When you have fin-
+ ished with the byte stream, it too must be freed by calling pcre2_seri-
+ alize_free(). If this function is called with a NULL argument, it re-
+ turns immediately without doing anything.
+
+
+RE-USING PRECOMPILED PATTERNS
+
+ In order to re-use a set of saved patterns you must first make the se-
+ rialized byte stream available in main memory (for example, by reading
+ from a file). The management of this memory block is up to the applica-
+ tion. You can use the pcre2_serialize_get_number_of_codes() function to
+ find out how many compiled patterns are in the serialized data without
+ actually decoding the patterns:
+
+ uint8_t *bytes = ;
+ int32_t number_of_codes = pcre2_serialize_get_number_of_codes(bytes);
+
+ The pcre2_serialize_decode() function reads a byte stream and recreates
+ the compiled patterns in new memory blocks, setting pointers to them in
+ a vector. The first two arguments are a pointer to a suitable vector
+ and its length, and the third argument points to a byte stream. The fi-
+ nal argument is a pointer to a general context, which can be used to
+ specify custom memory management functions for the decoded patterns. If
+ this argument is NULL, malloc() and free() are used. After deserializa-
+ tion, the byte stream is no longer needed and can be discarded.
+
+ pcre2_code *list_of_codes[2];
+ uint8_t *bytes = ;
+ int32_t number_of_codes =
+ pcre2_serialize_decode(list_of_codes, 2, bytes, NULL);
+
+ If the vector is not large enough for all the patterns in the byte
+ stream, it is filled with those that fit, and the remainder are ig-
+ nored. The yield of the function is the number of decoded patterns, or
+ one of the following negative error codes:
+
+ PCRE2_ERROR_BADDATA second argument is zero or less
+ PCRE2_ERROR_BADMAGIC mismatch of id bytes in the data
+ PCRE2_ERROR_BADMODE mismatch of code unit size or PCRE2 version
+ PCRE2_ERROR_BADSERIALIZEDDATA other sanity check failure
+ PCRE2_ERROR_MEMORY memory allocation failed
+ PCRE2_ERROR_NULL first or third argument is NULL
+
+ PCRE2_ERROR_BADMAGIC may mean that the data is corrupt, or that it was
+ compiled on a system with different endianness.
+
+ Decoded patterns can be used for matching in the usual way, and must be
+ freed by calling pcre2_code_free(). However, be aware that there is a
+ potential race issue if you are using multiple patterns that were de-
+ coded from a single byte stream in a multithreaded application. A sin-
+ gle copy of the character tables is used by all the decoded patterns
+ and a reference count is used to arrange for its memory to be automati-
+ cally freed when the last pattern is freed, but there is no locking on
+ this reference count. Therefore, if you want to call pcre2_code_free()
+ for these patterns in different threads, you must arrange your own
+ locking, and ensure that pcre2_code_free() cannot be called by two
+ threads at the same time.
+
+ If a pattern was processed by pcre2_jit_compile() before being serial-
+ ized, the JIT data is discarded and so is no longer available after a
+ save/restore cycle. You can, however, process a restored pattern with
+ pcre2_jit_compile() if you wish.
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 19 January 2024
+ Copyright (c) 1997-2018 University of Cambridge.
+
+
+PCRE2 10.48 19 January 2024 PCRE2SERIALIZE(3)
+------------------------------------------------------------------------------
+
+
+PCRE2SYNTAX(3) Library Functions Manual PCRE2SYNTAX(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+
+PCRE2 REGULAR EXPRESSION SYNTAX SUMMARY
+
+ The full syntax and semantics of the regular expression patterns that
+ are supported by PCRE2 are described in the pcre2pattern documentation.
+ This document contains a quick-reference summary of the pattern syntax
+ followed by the syntax of replacement strings in substitution function.
+ The full description of the latter is in the pcre2api documentation.
+
+
+QUOTING
+
+ \x where x is non-alphanumeric is a literal x
+ \Q...\E treat enclosed characters as literal
+
+ Note that white space inside \Q...\E is always treated as literal, even
+ if PCRE2_EXTENDED is set, causing most other white space to be ignored.
+ Note also that PCRE2's handling of \Q...\E has some differences from
+ Perl's. See the pcre2pattern documentation for details.
+
+
+BRACED ITEMS
+
+ With one exception, wherever brace characters { and } are required to
+ enclose data for constructions such as \g{2} or \k{name}, space and/or
+ horizontal tab characters that follow { or precede } are allowed and
+ are ignored. In the case of quantifiers, they may also appear before or
+ after the comma. The exception is \u{...} which is not Perl-compatible
+ and is recognized only when PCRE2_EXTRA_ALT_BSUX is set. This is an EC-
+ MAScript compatibility feature, and follows ECMAScript's behaviour.
+
+
+ESCAPED CHARACTERS
+
+ This table applies to ASCII and Unicode environments. An unrecognized
+ escape sequence causes an error.
+
+ \a alarm, that is, the BEL character (hex 07)
+ \cx "control-x", where x is a non-control ASCII character
+ \e escape (hex 1B)
+ \f form feed (hex 0C)
+ \n newline (hex 0A)
+ \r carriage return (hex 0D)
+ \t tab (hex 09)
+ \0dd character with octal code 0dd
+ \ddd character with octal code ddd, or backreference
+ \o{ddd..} character with octal code ddd..
+ \N{U+hh..} character with Unicode code point hh.. (Unicode mode only)
+ \xhh character with hex code hh
+ \x{hh..} character with hex code hh..
+
+ \N{U+hh..} is synonymous with \x{hh..} but is not supported in environ-
+ ments that use EBCDIC code (mainly IBM mainframes). Note that \N not
+ followed by an opening curly bracket has a different meaning (see be-
+ low).
+
+ If PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX is set ("ALT_BSUX mode"), the
+ following are also recognized:
+
+ \U the character "U"
+ \uhhhh character with hex code hhhh
+ \u{hh..} character with hex code hh.. but only for EXTRA_ALT_BSUX
+
+ When \x is not followed by {, one or two hexadecimal digits are read,
+ but in ALT_BSUX mode \x must be followed by two hexadecimal digits to
+ be recognized as a hexadecimal escape; otherwise it matches a literal
+ "x". Likewise, if \u (in ALT_BSUX mode) is not followed by four hexa-
+ decimal digits or (in EXTRA_ALT_BSUX mode) a sequence of hex digits in
+ curly brackets, it matches a literal "u".
+
+ Note that \0dd is always an octal code. The treatment of backslash fol-
+ lowed by a non-zero digit is complicated; for details see the section
+ "Non-printing characters" in the pcre2pattern documentation, where de-
+ tails of escape processing in EBCDIC environments are also given.
+
+
+CHARACTER TYPES
+
+ . any character except newline;
+ in dotall mode, any character whatsoever
+ \C one code unit, even in UTF mode (best avoided)
+ \d a decimal digit
+ \D a character that is not a decimal digit
+ \h a horizontal white space character
+ \H a character that is not a horizontal white space character
+ \N a character that is not a newline
+ \p{xx} a character with the xx property
+ \P{xx} a character without the xx property
+ \R a newline sequence
+ \s a white space character
+ \S a character that is not a white space character
+ \v a vertical white space character
+ \V a character that is not a vertical white space character
+ \w a "word" character
+ \W a "non-word" character
+ \X a Unicode extended grapheme cluster
+
+ \C is dangerous because it may leave the current matching point in the
+ middle of a UTF-8 or UTF-16 character. The application can lock out the
+ use of \C by setting the PCRE2_NEVER_BACKSLASH_C option. It is also
+ possible to build PCRE2 with the use of \C permanently disabled.
+
+ By default, \d, \s, and \w match only ASCII characters, even in UTF-8
+ mode or in the 16-bit and 32-bit libraries. However, if locale-specific
+ matching is happening, \s and \w may also match characters with code
+ points in the range 128-255. If the PCRE2_UCP option is set, the behav-
+ iour of these escape sequences is changed to use Unicode properties and
+ they match many more characters, but there are some option settings
+ that can restrict individual sequences to matching only ASCII charac-
+ ters.
+
+ Property descriptions in \p and \P are matched caselessly; hyphens, un-
+ derscores, and ASCII white space characters are ignored, in accordance
+ with Unicode's "loose matching" rules. For example, \p{Bidi_Class=al}
+ is the same as \p{ bidi class = AL }.
+
+
+GENERAL CATEGORY PROPERTIES FOR \p and \P
+
+ C Other
+ Cc Control
+ Cf Format
+ Cn Unassigned
+ Co Private use
+ Cs Surrogate
+
+ L Letter
+ Lc Cased letter, the union of Ll, Lu, and Lt
+ L& Synonym of Lc
+ Ll Lower case letter
+ Lm Modifier letter
+ Lo Other letter
+ Lt Title case letter
+ Lu Upper case letter
+
+ M Mark
+ Mc Spacing mark
+ Me Enclosing mark
+ Mn Non-spacing mark
+
+ N Number
+ Nd Decimal number
+ Nl Letter number
+ No Other number
+
+ P Punctuation
+ Pc Connector punctuation
+ Pd Dash punctuation
+ Pe Close punctuation
+ Pf Final punctuation
+ Pi Initial punctuation
+ Po Other punctuation
+ Ps Open punctuation
+
+ S Symbol
+ Sc Currency symbol
+ Sk Modifier symbol
+ Sm Mathematical symbol
+ So Other symbol
+
+ Z Separator
+ Zl Line separator
+ Zp Paragraph separator
+ Zs Space separator
+
+ From release 10.45, when caseless matching is set, Ll, Lu, and Lt are
+ all equivalent to Lc.
+
+
+PCRE2 SPECIAL CATEGORY PROPERTIES FOR \p and \P
+
+ Xan Alphanumeric: union of properties L and N
+ Xps POSIX space: property Z or tab, NL, VT, FF, CR
+ Xsp Perl space: property Z or tab, NL, VT, FF, CR
+ Xuc Universally-named character: one that can be
+ represented by a Universal Character Name
+ Xwd Perl word: property Xan or underscore
+
+ Perl and POSIX space are now the same. Perl added VT to its space char-
+ acter set at release 5.18.
+
+
+BINARY PROPERTIES FOR \p AND \P
+
+ Unicode defines a number of binary properties, that is, properties
+ whose only values are true or false. You can obtain a list of those
+ that are recognized by \p and \P, along with their abbreviations, by
+ running this command:
+
+ pcre2test -LP
+
+
+SCRIPT MATCHING WITH \p AND \P
+
+ Many script names and their 4-letter abbreviations are recognized in
+ \p{sc:...} or \p{scx:...} items, or on their own with \p (and also \P
+ of course). You can obtain a list of these scripts by running this com-
+ mand:
+
+ pcre2test -LS
+
+
+THE BIDI_CLASS PROPERTY FOR \p AND \P
+
+ \p{Bidi_Class:} matches a character with the given class
+ \p{BC:} matches a character with the given class
+
+ The recognized classes are:
+
+ AL Arabic letter
+ AN Arabic number
+ B paragraph separator
+ BN boundary neutral
+ CS common separator
+ EN European number
+ ES European separator
+ ET European terminator
+ FSI first strong isolate
+ L left-to-right
+ LRE left-to-right embedding
+ LRI left-to-right isolate
+ LRO left-to-right override
+ NSM non-spacing mark
+ ON other neutral
+ PDF pop directional format
+ PDI pop directional isolate
+ R right-to-left
+ RLE right-to-left embedding
+ RLI right-to-left isolate
+ RLO right-to-left override
+ S segment separator
+ WS white space
+
+
+CHARACTER CLASSES
+
+ [...] positive character class
+ [^...] negative character class
+ [x-y] range (can be used for hex characters)
+ [[:xxx:]] positive POSIX named set
+ [[:^xxx:]] negative POSIX named set
+
+ alnum alphanumeric
+ alpha alphabetic
+ ascii 0-127
+ blank space or tab
+ cntrl control character
+ digit decimal digit
+ graph printing, excluding space
+ lower lower case letter
+ print printing, including space
+ punct printing, excluding alphanumeric
+ space white space
+ upper upper case letter
+ word same as \w
+ xdigit hexadecimal digit
+
+ In PCRE2, POSIX character set names recognize only ASCII characters by
+ default, but some of them use Unicode properties if PCRE2_UCP is set.
+ You can use \Q...\E inside a character class.
+
+ When PCRE2_ALT_EXTENDED_CLASS is set, UTS#18 extended character classes
+ may be used, allowing nested character classes, combined using set op-
+ erators.
+
+ [x&&[^y]] UTS#18 extended character class
+
+ x||y set union (OR)
+ x&&y set intersection (AND)
+ x--y set difference (AND NOT)
+ x~~y set symmetric difference (XOR)
+
+
+PERL EXTENDED CHARACTER CLASSES
+
+ (?[...]) Perl extended character class
+ (?[\p{Thai} & \p{Nd}]) operators; white space ignored
+ (?[(x - y) & z]) parentheses for grouping
+
+ (?[ [^3] & \p{Nd} ]) [...] is a nested ordinary class
+ (?[ [:alpha:] - [z] ]) POSIX set is allowed outside [...]
+ (?[ \d - [3] ]) backslash-escaped set is allowed outside
+ [...]
+ (?[ !\n & [:ascii:] ]) backslash-escaped character is allowed out-
+ side [...]
+ all other characters or ranges must be enclosed
+ in [...]
+
+ x|y, x+y set union (OR)
+ x&y set intersection (AND)
+ x-y set difference (AND NOT)
+ x^y set symmetric difference (XOR)
+ !x set complement (NOT)
+
+ Inside a Perl extended character class, [...] switches mode to be in-
+ terpreted as an ordinary character class. Outside of a nested [...],
+ the only items permitted are backslash-escapes, POSIX sets, operators,
+ and parentheses. Inside a nested ordinary class, ^ has its usual mean-
+ ing (inverts the class when used as the first character); outside of a
+ nested class, ^ is the XOR operator.
+
+
+QUANTIFIERS
+
+ ? 0 or 1, greedy
+ ?+ 0 or 1, possessive
+ ?? 0 or 1, lazy
+ * 0 or more, greedy
+ *+ 0 or more, possessive
+ *? 0 or more, lazy
+ + 1 or more, greedy
+ ++ 1 or more, possessive
+ +? 1 or more, lazy
+ {n} exactly n
+ {n,m} at least n, no more than m, greedy
+ {n,m}+ at least n, no more than m, possessive
+ {n,m}? at least n, no more than m, lazy
+ {n,} n or more, greedy
+ {n,}+ n or more, possessive
+ {n,}? n or more, lazy
+ {,m} zero up to m, greedy
+ {,m}+ zero up to m, possessive
+ {,m}? zero up to m, lazy
+
+
+ANCHORS AND SIMPLE ASSERTIONS
+
+ \b word boundary
+ \B not a word boundary
+ ^ start of subject
+ also after an internal newline in multiline mode
+ (after any newline if PCRE2_ALT_CIRCUMFLEX is set)
+ \A start of subject
+ $ end of subject
+ also before newline at end of subject
+ also before internal newline in multiline mode
+ \Z end of subject
+ also before newline at end of subject
+ \z end of subject
+ \G first matching position in subject
+
+
+REPORTED MATCH POINT SETTING
+
+ \K set reported start of match
+
+ From release 10.38 \K is not permitted by default in lookaround asser-
+ tions, for compatibility with Perl. However, if the PCRE2_EXTRA_AL-
+ LOW_LOOKAROUND_BSK option is set, the previous behaviour is re-enabled.
+ When this option is set, \K is honoured in positive assertions, but ig-
+ nored in negative ones.
+
+
+ALTERNATION
+
+ expr|expr|expr...
+
+
+CAPTURING
+
+ (...) capture group
+ (?...) named capture group (Perl)
+ (?'name'...) named capture group (Perl)
+ (?P...) named capture group (Python)
+ (?:...) non-capture group
+ (?|...) non-capture group; reset group numbers for
+ capture groups in each alternative
+
+ In non-UTF modes, names may contain underscores and ASCII letters and
+ digits; in UTF modes, any Unicode letters and Unicode decimal digits
+ are permitted. In both cases, a name must not start with a digit.
+
+
+ATOMIC GROUPS
+
+ (?>...) atomic non-capture group
+ (*atomic:...) atomic non-capture group
+
+
+COMMENT
+
+ (?#....) comment (not nestable)
+
+
+OPTION SETTING
+ Changes of these options within a group are automatically cancelled at
+ the end of the group.
+
+ (?a) all ASCII options
+ (?aD) restrict \d to ASCII in UCP mode
+ (?aS) restrict \s to ASCII in UCP mode
+ (?aW) restrict \w to ASCII in UCP mode
+ (?aP) restrict all POSIX classes to ASCII in UCP mode
+ (?aT) restrict POSIX digit classes to ASCII in UCP mode
+ (?i) caseless
+ (?J) allow duplicate named groups
+ (?m) multiline
+ (?n) no auto capture
+ (?r) restrict caseless to either ASCII or non-ASCII
+ (?s) single line (dotall)
+ (?U) default ungreedy (lazy)
+ (?x) ignore white space except in classes or \Q...\E
+ (?xx) as (?x) but also ignore space and tab in classes
+ (?-...) unset the given option(s)
+ (?^) unset imnrsx options
+
+ (?aP) implies (?aT) as well, though this has no additional effect. How-
+ ever, it means that (?-aP) also implies (?-aT) and disables all ASCII
+ restrictions for POSIX classes.
+
+ Unsetting x or xx unsets both. Several options may be set at once, and
+ a mixture of setting and unsetting such as (?i-x) is allowed, but there
+ may be only one hyphen. Setting (but no unsetting) is allowed after (?^
+ for example (?^in). An option setting may appear at the start of a non-
+ capture group, for example (?i:...).
+
+ The following are recognized only at the very start of a pattern or af-
+ ter one of the newline or \R sequences or options with similar syntax.
+ More than one of them may appear. For the first three, d is a decimal
+ number.
+
+ (*LIMIT_DEPTH=d) set the backtracking limit to d
+ (*LIMIT_HEAP=d) set the heap size limit to d * 1024 bytes
+ (*LIMIT_MATCH=d) set the match limit to d
+ (*CASELESS_RESTRICT) set PCRE2_EXTRA_CASELESS_RESTRICT when matching
+ (*NOTEMPTY) set PCRE2_NOTEMPTY when matching
+ (*NOTEMPTY_ATSTART) set PCRE2_NOTEMPTY_ATSTART when matching
+ (*NO_AUTO_POSSESS) no auto-possessification (PCRE2_NO_AUTO_POSSESS)
+ (*NO_DOTSTAR_ANCHOR) no .* anchoring (PCRE2_NO_DOTSTAR_ANCHOR)
+ (*NO_JIT) disable JIT optimization
+ (*NO_START_OPT) no start-match optimization (PCRE2_NO_START_OP-
+ TIMIZE)
+ (*TURKISH_CASING) set PCRE2_EXTRA_TURKISH_CASING when matching
+ (*UTF) set appropriate UTF mode for the library in use
+ (*UCP) set PCRE2_UCP (use Unicode properties for \d
+ etc)
+
+ Note that LIMIT_DEPTH, LIMIT_HEAP, and LIMIT_MATCH can only reduce the
+ value of the limits set by the caller of pcre2_match() or
+ pcre2_dfa_match(), not increase them. LIMIT_RECURSION is an obsolete
+ synonym for LIMIT_DEPTH. The application can lock out the use of (*UTF)
+ and (*UCP) by setting the PCRE2_NEVER_UTF or PCRE2_NEVER_UCP options,
+ respectively, at compile time.
+
+
+NEWLINE CONVENTION
+
+ These are recognized only at the very start of the pattern or after op-
+ tion settings with a similar syntax.
+
+ (*CR) carriage return only
+ (*LF) linefeed only
+ (*CRLF) carriage return followed by linefeed
+ (*ANYCRLF) all three of the above
+ (*ANY) any Unicode newline sequence
+ (*NUL) the NUL character (binary zero)
+
+
+WHAT \R MATCHES
+
+ These are recognized only at the very start of the pattern or after op-
+ tion setting with a similar syntax.
+
+ (*BSR_ANYCRLF) CR, LF, or CRLF
+ (*BSR_UNICODE) any Unicode newline sequence
+
+
+LOOKAHEAD AND LOOKBEHIND ASSERTIONS
+
+ (?=...) )
+ (*pla:...) ) positive lookahead
+ (*positive_lookahead:...) )
+
+ (?!...) )
+ (*nla:...) ) negative lookahead
+ (*negative_lookahead:...) )
+
+ (?<=...) )
+ (*plb:...) ) positive lookbehind
+ (*positive_lookbehind:...) )
+
+ (? name
+ 'name' name
+
+
+SCRIPT RUNS
+
+ (*script_run:...) ) script run, can be backtracked into
+ (*sr:...) )
+
+ (*atomic_script_run:...) ) atomic script run
+ (*asr:...) )
+
+
+BACKREFERENCES
+
+ \n reference by number (can be ambiguous)
+ \gn reference by number
+ \g{n} reference by number
+ \g+n relative reference by number (PCRE2 extension)
+ \g-n relative reference by number
+ \g{+n} relative reference by number (PCRE2 extension)
+ \g{-n} relative reference by number
+ \k reference by name (Perl)
+ \k'name' reference by name (Perl)
+ \g{name} reference by name (Perl)
+ \k{name} reference by name (.NET)
+ (?P=name) reference by name (Python)
+
+
+SUBROUTINE REFERENCES (POSSIBLY RECURSIVE)
+
+ (?R) recurse whole pattern
+ (?n) call subroutine by absolute number
+ (?+n) call subroutine by relative number
+ (?-n) call subroutine by relative number
+ (?&name) call subroutine by name (Perl)
+ (?P>name) call subroutine by name (Python)
+ \g call subroutine by name (Oniguruma)
+ \g'name' call subroutine by name (Oniguruma)
+ \g call subroutine by absolute number (Oniguruma)
+ \g'n' call subroutine by absolute number (Oniguruma)
+ \g<+n> call subroutine by relative number (PCRE2 extension)
+ \g'+n' call subroutine by relative number (PCRE2 extension)
+ \g<-n> call subroutine by relative number (PCRE2 extension)
+ \g'-n' call subroutine by relative number (PCRE2 extension)
+
+ The variants using parentheses (?...) may also specify a list of cap-
+ ture groups to return, which shall be retained in the calling subex-
+ pression if set during the recursion (this feature is not supported by
+ Perl).
+
+ (?R(grouplist)) recurse whole pattern, returning capture groups
+ (PCRE2 extension)
+ (?n(grouplist)) )
+ (?+n(grouplist)) ) call subroutine, returning capture groups
+ (?-n(grouplist)) ) (PCRE2 extension)
+ (?&name(grouplist)) )
+ (?P>name(grouplist)) )
+
+ The comma-separated list "grouplist" uses the same syntax as
+ (*scan_substring:(grouplist)...), and may identify groups in any of the
+ following ways:
+
+ n absolute reference
+ +n relative reference
+ -n relative reference
+ name
+ 'name' name
+
+
+CONDITIONAL PATTERNS
+
+ (?(condition)yes-pattern)
+ (?(condition)yes-pattern|no-pattern)
+
+ (?(n) absolute reference condition
+ (?(+n) relative reference condition (PCRE2 extension)
+ (?(-n) relative reference condition (PCRE2 extension)
+ (?() named reference condition (Perl)
+ (?('name') named reference condition (Perl)
+ (?(name) named reference condition (PCRE2, deprecated)
+ (?(R) overall recursion condition
+ (?(Rn) specific numbered group recursion condition
+ (?(R&name) specific named group recursion condition
+ (?(DEFINE) define groups for reference
+ (?(VERSION[>]=n[.m]) test PCRE2 version
+ (?(assert) assertion condition
+
+ Note the ambiguity of (?(R) and (?(Rn) which might be named reference
+ conditions or recursion tests. Such a condition is interpreted as a
+ reference condition if the relevant named group exists.
+
+ The parts within brackets for the VERSION conditional syntax could be
+ ommited. The fractional part of the version number defaults to 0 in
+ that case.
+
+
+BACKTRACKING CONTROL
+
+ All backtracking control verbs may be in the form (*VERB:NAME). For
+ (*MARK) the name is mandatory, for the others it is optional. (*SKIP)
+ changes its behaviour if :NAME is present. The others just set a name
+ for passing back to the caller, but this is not a name that (*SKIP) can
+ see. The following act immediately they are reached:
+
+ (*ACCEPT) force successful match
+ (*FAIL) force backtrack; synonym (*F)
+ (*MARK:NAME) set name to be passed back; synonym (*:NAME)
+
+ The following act only when a subsequent match failure causes a back-
+ track to reach them. They all force a match failure, but they differ in
+ what happens afterwards. Those that advance the start-of-match point do
+ so only if the pattern is not anchored.
+
+ (*COMMIT) overall failure, no advance of starting point
+ (*PRUNE) advance to next starting character
+ (*SKIP) advance to current matching position
+ (*SKIP:NAME) advance to position corresponding to an earlier
+ (*MARK:NAME); if not found, the (*SKIP) is ignored
+ (*THEN) local failure, backtrack to next alternation
+
+ The effect of one of these verbs in a group called as a subroutine is
+ confined to the subroutine call.
+
+
+CALLOUTS
+
+ (?C) callout (assumed number 0)
+ (?Cn) callout with numerical data n
+ (?C"text") callout with string data
+
+ The allowed string delimiters are ` ' " ^ % # $ (which are the same for
+ the start and the end), and the starting delimiter { matched with the
+ ending delimiter }. To encode the ending delimiter within the string,
+ double it.
+
+
+REPLACEMENT STRINGS
+
+ If the PCRE2_SUBSTITUTE_LITERAL option is set, a replacement string for
+ pcre2_substitute() is not interpreted. Otherwise, by default, the only
+ special character is the dollar character in one of the following
+ forms:
+
+ $$ insert a dollar character
+ $n or ${n} insert the contents of group n
+ $ insert the contents of named group
+ $0 or $& insert the entire matched substring
+ $` insert the substring that precedes the match
+ $' insert the substring that follows the match
+ $_ insert the entire input string
+ $+ insert the highest-numbered capture group which
+ matched
+ $*MARK or ${*MARK} insert a control verb name
+
+ For ${n}, n can be a name or a number. If PCRE2_SUBSTITUTE_EXTENDED is
+ set, there is additional interpretation:
+
+ 1. Backslash is an escape character, and the forms described in "ES-
+ CAPED CHARACTERS" above are recognized. Also:
+
+ \Q...\E can be used to suppress interpretation
+ \l force the next character to lower case
+ \u force the next character to upper case
+ \L force subsequent characters to lower case
+ \U force subsequent characters to upper case
+ \u\L force next character to upper case, then all lower
+ \l\U force next character to lower case, then all upper
+ \E end \L or \U case forcing
+ \b backspace character (note: as in character class in pattern)
+ \v vertical tab character (note: not the same as in a pattern)
+
+ 2. The Python form \g, where the angle brackets are part of the syn-
+ tax and n is either a group name or a number, is recognized as an al-
+ ternative way of inserting the contents of a group, for example \g<3>.
+
+ 3. Capture substitution supports the following additional forms:
+
+ ${n:-string} default for unset group
+ ${n:+string1:string2} values for set/unset group
+
+ The substitution strings themselves are expanded. Backslash can be used
+ to escape colons and closing curly brackets.
+
+
+SEE ALSO
+
+ pcre2pattern(3), pcre2api(3), pcre2callout(3), pcre2matching(3),
+ pcre2(3).
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 14 October 2025
+ Copyright (c) 1997-2024 University of Cambridge.
+
+
+PCRE2 10.48 14 October 2025 PCRE2SYNTAX(3)
+------------------------------------------------------------------------------
+
+
+PCRE2UNICODE(3) Library Functions Manual PCRE2UNICODE(3)
+
+
+NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+
+
+UNICODE AND UTF SUPPORT
+
+ PCRE2 is normally built with Unicode support, though if you do not need
+ it, you can build it without, in which case the library will be
+ smaller. With Unicode support, PCRE2 has knowledge of Unicode character
+ properties and can process strings of text in UTF-8, UTF-16, and UTF-32
+ format (depending on the code unit width), but this is not the default.
+ Unless specifically requested, PCRE2 treats each code unit in a string
+ as one character.
+
+ There are two ways of telling PCRE2 to switch to UTF mode, where char-
+ acters may consist of more than one code unit and the range of values
+ is constrained. The program can call pcre2_compile() with the PCRE2_UTF
+ option, or the pattern may start with the sequence (*UTF). However,
+ the latter facility can be locked out by the PCRE2_NEVER_UTF option.
+ That is, the programmer can prevent the supplier of the pattern from
+ switching to UTF mode.
+
+ Note that the PCRE2_MATCH_INVALID_UTF option (see below) forces
+ PCRE2_UTF to be set.
+
+ In UTF mode, both the pattern and any subject strings that are matched
+ against it are treated as UTF strings instead of strings of individual
+ one-code-unit characters. There are also some other changes to the way
+ characters are handled, as documented below.
+
+
+UNICODE PROPERTY SUPPORT
+
+ When PCRE2 is built with Unicode support, the escape sequences \p{..},
+ \P{..}, and \X can be used. This is not dependent on the PCRE2_UTF set-
+ ting. The Unicode properties that can be tested are a subset of those
+ that Perl supports. Currently they are limited to the general category
+ properties such as Lu for an upper case letter or Nd for a decimal num-
+ ber, the derived properties Any and Lc (synonym L&), the Unicode script
+ names such as Arabic or Han, Bidi_Class, Bidi_Control, and a few binary
+ properties.
+
+ The full lists are given in the pcre2pattern and pcre2syntax documenta-
+ tion. In general, only the short names for properties are supported.
+ For example, \p{L} matches a letter. Its longer synonym, \p{Letter}, is
+ not supported. Furthermore, in Perl, many properties may optionally be
+ prefixed by "Is", for compatibility with Perl 5.6. PCRE2 does not sup-
+ port this.
+
+
+WIDE CHARACTERS AND UTF MODES
+
+ Code points less than 256 can be specified in patterns by either braced
+ or unbraced hexadecimal escape sequences (for example, \x{b3} or \xb3).
+ Larger values have to use braced sequences. Unbraced octal code points
+ up to \777 are also recognized; larger ones can be coded using \o{...}.
+
+ The escape sequence \N{U+} is recognized as another way of
+ specifying a Unicode character by code point in a UTF mode. It is not
+ allowed in non-UTF mode.
+
+ In UTF mode, repeat quantifiers apply to complete UTF characters, not
+ to individual code units.
+
+ In UTF mode, the dot metacharacter matches one UTF character instead of
+ a single code unit.
+
+ In UTF mode, capture group names are not restricted to ASCII, and may
+ contain any Unicode letters and decimal digits, as well as underscore.
+
+ The escape sequence \C can be used to match a single code unit in UTF
+ mode, but its use can lead to some strange effects because it breaks up
+ multi-unit characters (see the description of \C in the pcre2pattern
+ documentation). For this reason, there is a build-time option that dis-
+ ables support for \C completely. There is also a less draconian com-
+ pile-time option for locking out the use of \C when a pattern is com-
+ piled.
+
+ The use of \C is not supported by the alternative matching function
+ pcre2_dfa_match() when in UTF-8 or UTF-16 mode, that is, when a charac-
+ ter may consist of more than one code unit. The use of \C in these
+ modes provokes a match-time error. Also, the JIT optimization does not
+ support \C in these modes. If JIT optimization is requested for a UTF-8
+ or UTF-16 pattern that contains \C, it will not succeed, and so when
+ pcre2_match() is called, the matching will be carried out by the inter-
+ pretive function.
+
+ The character escapes \b, \B, \d, \D, \s, \S, \w, and \W correctly test
+ characters of any code value, but, by default, the characters that
+ PCRE2 recognizes as digits, spaces, or word characters remain the same
+ set as in non-UTF mode, all with code points less than 256. This re-
+ mains true even when PCRE2 is built to include Unicode support, because
+ to do otherwise would slow down matching in many common cases. Note
+ that this also applies to \b and \B, because they are defined in terms
+ of \w and \W. If you want to test for a wider sense of, say, "digit",
+ you can use explicit Unicode property tests such as \p{Nd}. Alterna-
+ tively, if you set the PCRE2_UCP option, the way that the character es-
+ capes work is changed so that Unicode properties are used to determine
+ which characters match, though there are some options that suppress
+ this for individual escapes. For details see the section on generic
+ character types in the pcre2pattern documentation.
+
+ Like the escapes, characters that match the POSIX named character
+ classes are all low-valued characters unless the PCRE2_UCP option is
+ set, but there is an option to override this.
+
+ In contrast to the character escapes and character classes, the special
+ horizontal and vertical white space escapes (\h, \H, \v, and \V) do
+ match all the appropriate Unicode characters, whether or not PCRE2_UCP
+ is set.
+
+
+UNICODE CASE-EQUIVALENCE
+
+ If either PCRE2_UTF or PCRE2_UCP is set, upper/lower case processing
+ makes use of Unicode properties except for characters whose code points
+ are less than 128 and that have at most two case-equivalent values. For
+ these, a direct table lookup is used for speed. A few Unicode charac-
+ ters such as Greek sigma have more than two code points that are case-
+ equivalent, and these are treated specially. Setting PCRE2_UCP without
+ PCRE2_UTF allows Unicode-style case processing for non-UTF character
+ encodings such as UCS-2.
+
+ There are two ASCII characters (S and K) that, in addition to their
+ ASCII lower case equivalents, have a non-ASCII one as well (long S and
+ Kelvin sign). Recognition of these non-ASCII characters as case-equiv-
+ alent to their ASCII counterparts can be disabled by setting the
+ PCRE2_EXTRA_CASELESS_RESTRICT option. When this is set, all characters
+ in a case equivalence must either be ASCII or non-ASCII; there can be
+ no mixing.
+
+ Without PCRE2_EXTRA_CASELESS_RESTRICT:
+ 'k' = 'K' = U+212A (Kelvin sign)
+ 's' = 'S' = U+017F (long S)
+ With PCRE2_EXTRA_CASELESS_RESTRICT:
+ 'k' = 'K'
+ U+212A (Kelvin sign) only case-equivalent to itself
+ 's' = 'S'
+ U+017F (long S) only case-equivalent to itself
+
+ One language family, Turkish and Azeri, has its own case-insensitivity
+ rules, which can be selected by setting PCRE2_EXTRA_TURKISH_CASING.
+ This alters the behaviour of the 'i', 'I', U+0130 (capital I with dot
+ above), and U+0131 (small dotless i) characters.
+
+ Without PCRE2_EXTRA_TURKISH_CASING:
+ 'i' = 'I'
+ U+0130 (capital I with dot above) only case-equivalent to itself
+ U+0131 (small dotless i) only case-equivalent to itself
+ With PCRE2_EXTRA_TURKISH_CASING:
+ 'i' = U+0130 (capital I with dot above)
+ U+0131 (small dotless i) = 'I'
+
+ It is not allowed to specify both PCRE2_EXTRA_CASELESS_RESTRICT and
+ PCRE2_EXTRA_TURKISH_CASING together.
+
+ From release 10.45 the Unicode letter properties Lu (upper case), Ll
+ (lower case), and Lt (title case) are all treated as Lc (cased letter)
+ when caseless matching is set by the PCRE2_CASELESS option or (?i)
+ within the pattern.
+
+
+SCRIPT RUNS
+
+ The pattern constructs (*script_run:...) and (*atomic_script_run:...),
+ with synonyms (*sr:...) and (*asr:...), verify that the string matched
+ within the parentheses is a script run. In concept, a script run is a
+ sequence of characters that are all from the same Unicode script. How-
+ ever, because some scripts are commonly used together, and because some
+ diacritical and other marks are used with multiple scripts, it is not
+ that simple.
+
+ Every Unicode character has a Script property, mostly with a value cor-
+ responding to the name of a script, such as Latin, Greek, or Cyrillic.
+ There are also three special values:
+
+ "Unknown" is used for code points that have not been assigned, and also
+ for the surrogate code points. In the PCRE2 32-bit library, characters
+ whose code points are greater than the Unicode maximum (U+10FFFF),
+ which are accessible only in non-UTF mode, are assigned the Unknown
+ script.
+
+ "Common" is used for characters that are used with many scripts. These
+ include punctuation, emoji, mathematical, musical, and currency sym-
+ bols, and the ASCII digits 0 to 9.
+
+ "Inherited" is used for characters such as diacritical marks that mod-
+ ify a previous character. These are considered to take on the script of
+ the character that they modify.
+
+ Some Inherited characters are used with many scripts, but many of them
+ are only normally used with a small number of scripts. For example,
+ U+102E0 (Coptic Epact thousands mark) is used only with Arabic and Cop-
+ tic. In order to make it possible to check this, a Unicode property
+ called Script Extension exists. Its value is a list of scripts that ap-
+ ply to the character. For the majority of characters, the list contains
+ just one script, the same one as the Script property. However, for
+ characters such as U+102E0 more than one Script is listed. There are
+ also some Common characters that have a single, non-Common script in
+ their Script Extension list.
+
+ The next section describes the basic rules for deciding whether a given
+ string of characters is a script run. Note, however, that there are
+ some special cases involving the Chinese Han script, and an additional
+ constraint for decimal digits. These are covered in subsequent sec-
+ tions.
+
+ Basic script run rules
+
+ A string that is less than two characters long is a script run. This is
+ the only case in which an Unknown character can be part of a script
+ run. Longer strings are checked using only the Script Extensions prop-
+ erty, not the basic Script property.
+
+ If a character's Script Extension property is the single value "Inher-
+ ited", it is always accepted as part of a script run. This is also true
+ for the property "Common", subject to the checking of decimal digits
+ described below. All the remaining characters in a script run must have
+ at least one script in common in their Script Extension lists. In set-
+ theoretic terminology, the intersection of all the sets of scripts must
+ not be empty.
+
+ A simple example is an Internet name such as "google.com". The letters
+ are all in the Latin script, and the dot is Common, so this string is a
+ script run. However, the Cyrillic letter "o" looks exactly the same as
+ the Latin "o"; a string that looks the same, but with Cyrillic "o"s is
+ not a script run.
+
+ More interesting examples involve characters with more than one script
+ in their Script Extension. Consider the following characters:
+
+ U+060C Arabic comma
+ U+06D4 Arabic full stop
+
+ The first has the Script Extension list Arabic, Hanifi Rohingya, Syr-
+ iac, and Thaana; the second has just Arabic and Hanifi Rohingya. Both
+ of them could appear in script runs of either Arabic or Hanifi Ro-
+ hingya. The first could also appear in Syriac or Thaana script runs,
+ but the second could not.
+
+ The Chinese Han script
+
+ The Chinese Han script is commonly used in conjunction with other
+ scripts for writing certain languages. Japanese uses the Hiragana and
+ Katakana scripts together with Han; Korean uses Hangul and Han; Tai-
+ wanese Mandarin uses Bopomofo and Han. These three combinations are
+ treated as special cases when checking script runs and are, in effect,
+ "virtual scripts". Thus, a script run may contain a mixture of Hira-
+ gana, Katakana, and Han, or a mixture of Hangul and Han, or a mixture
+ of Bopomofo and Han, but not, for example, a mixture of Hangul and
+ Bopomofo and Han. PCRE2 (like Perl) follows Unicode's Technical Stan-
+ dard 39 ("Unicode Security Mechanisms", http://unicode.org/re-
+ ports/tr39/) in allowing such mixtures.
+
+ Decimal digits
+
+ Unicode contains many sets of 10 decimal digits in different scripts,
+ and some scripts (including the Common script) contain more than one
+ set. Some of these decimal digits them are visually indistinguishable
+ from the common ASCII digits. In addition to the script checking de-
+ scribed above, if a script run contains any decimal digits, they must
+ all come from the same set of 10 adjacent characters.
+
+
+VALIDITY OF UTF STRINGS
+
+ When the PCRE2_UTF option is set, the strings passed as patterns and
+ subjects are (by default) checked for validity on entry to the relevant
+ functions. If an invalid UTF string is passed, a negative error code is
+ returned. The code unit offset to the offending character can be ex-
+ tracted from the match data block by calling pcre2_get_startchar(),
+ which is used for this purpose after a UTF error.
+
+ In some situations, you may already know that your strings are valid,
+ and therefore want to skip these checks in order to improve perfor-
+ mance, for example in the case of a long subject string that is being
+ scanned repeatedly. If you set the PCRE2_NO_UTF_CHECK option at com-
+ pile time or at match time, PCRE2 assumes that the pattern or subject
+ it is given (respectively) contains only valid UTF code unit sequences.
+
+ If you pass an invalid UTF string when PCRE2_NO_UTF_CHECK is set, the
+ result is undefined and your program may crash or loop indefinitely or
+ give incorrect results. There is, however, one mode of matching that
+ can handle invalid UTF subject strings. This is enabled by passing
+ PCRE2_MATCH_INVALID_UTF to pcre2_compile() and is discussed below in
+ the next section. The rest of this section covers the case when
+ PCRE2_MATCH_INVALID_UTF is not set.
+
+ Passing PCRE2_NO_UTF_CHECK to pcre2_compile() just disables the UTF
+ check for the pattern; it does not also apply to subject strings. If
+ you want to disable the check for a subject string you must pass this
+ same option to pcre2_match() or pcre2_dfa_match().
+
+ UTF-16 and UTF-32 strings can indicate their endianness by special code
+ knows as a byte-order mark (BOM). The PCRE2 functions do not handle
+ this, expecting strings to be in host byte order.
+
+ Unless PCRE2_NO_UTF_CHECK is set, a UTF string is checked before any
+ other processing takes place. In the case of pcre2_match() and
+ pcre2_dfa_match() calls with a non-zero starting offset, the check is
+ applied only to that part of the subject that could be inspected during
+ matching, and there is a check that the starting offset points to the
+ first code unit of a character or to the end of the subject. If there
+ are no lookbehind assertions in the pattern, the check starts at the
+ starting offset. Otherwise, it starts at the length of the longest
+ lookbehind before the starting offset, or at the start of the subject
+ if there are not that many characters before the starting offset. Note
+ that the sequences \b and \B are one-character lookbehinds.
+
+ In addition to checking the format of the string, there is a check to
+ ensure that all code points lie in the range U+0 to U+10FFFF, excluding
+ the surrogate area. The so-called "non-character" code points are not
+ excluded because Unicode corrigendum #9 makes it clear that they should
+ not be.
+
+ Characters in the "Surrogate Area" of Unicode are reserved for use by
+ UTF-16, where they are used in pairs to encode code points with values
+ greater than 0xFFFF. The code points that are encoded by UTF-16 pairs
+ are available independently in the UTF-8 and UTF-32 encodings. (In
+ other words, the whole surrogate thing is a fudge for UTF-16 which un-
+ fortunately messes up UTF-8 and UTF-32.)
+
+ Setting PCRE2_NO_UTF_CHECK at compile time does not disable the error
+ that is given if an escape sequence for an invalid Unicode code point
+ is encountered in the pattern. If you want to allow escape sequences
+ such as \x{d800} (a surrogate code point) you can set the PCRE2_EX-
+ TRA_ALLOW_SURROGATE_ESCAPES extra option. However, this is possible
+ only in UTF-8 and UTF-32 modes, because these values are not repre-
+ sentable in UTF-16.
+
+ Errors in UTF-8 strings
+
+ The following negative error codes are given for invalid UTF-8 strings:
+
+ PCRE2_ERROR_UTF8_ERR1
+ PCRE2_ERROR_UTF8_ERR2
+ PCRE2_ERROR_UTF8_ERR3
+ PCRE2_ERROR_UTF8_ERR4
+ PCRE2_ERROR_UTF8_ERR5
+
+ The string ends with a truncated UTF-8 character; the code specifies
+ how many bytes are missing (1 to 5). Although RFC 3629 restricts UTF-8
+ characters to be no longer than 4 bytes, the encoding scheme (origi-
+ nally defined by RFC 2279) allows for up to 6 bytes, and this is
+ checked first; hence the possibility of 4 or 5 missing bytes.
+
+ PCRE2_ERROR_UTF8_ERR6
+ PCRE2_ERROR_UTF8_ERR7
+ PCRE2_ERROR_UTF8_ERR8
+ PCRE2_ERROR_UTF8_ERR9
+ PCRE2_ERROR_UTF8_ERR10
+
+ The two most significant bits of the 2nd, 3rd, 4th, 5th, or 6th byte of
+ the character do not have the binary value 0b10 (that is, either the
+ most significant bit is 0, or the next bit is 1).
+
+ PCRE2_ERROR_UTF8_ERR11
+ PCRE2_ERROR_UTF8_ERR12
+
+ A character that is valid by the RFC 2279 rules is either 5 or 6 bytes
+ long; these code points are excluded by RFC 3629.
+
+ PCRE2_ERROR_UTF8_ERR13
+
+ A 4-byte character has a value greater than 0x10ffff; these code points
+ are excluded by RFC 3629.
+
+ PCRE2_ERROR_UTF8_ERR14
+
+ A 3-byte character has a value in the range 0xd800 to 0xdfff; this
+ range of code points are reserved by RFC 3629 for use with UTF-16, and
+ so are excluded from UTF-8.
+
+ PCRE2_ERROR_UTF8_ERR15
+ PCRE2_ERROR_UTF8_ERR16
+ PCRE2_ERROR_UTF8_ERR17
+ PCRE2_ERROR_UTF8_ERR18
+ PCRE2_ERROR_UTF8_ERR19
+
+ A 2-, 3-, 4-, 5-, or 6-byte character is "overlong", that is, it codes
+ for a value that can be represented by fewer bytes, which is invalid.
+ For example, the two bytes 0xc0, 0xae give the value 0x2e, whose cor-
+ rect coding uses just one byte.
+
+ PCRE2_ERROR_UTF8_ERR20
+
+ The two most significant bits of the first byte of a character have the
+ binary value 0b10 (that is, the most significant bit is 1 and the sec-
+ ond is 0). Such a byte can only validly occur as the second or subse-
+ quent byte of a multi-byte character.
+
+ PCRE2_ERROR_UTF8_ERR21
+
+ The first byte of a character has the value 0xfe or 0xff. These values
+ can never occur in a valid UTF-8 string.
+
+ Errors in UTF-16 strings
+
+ The following negative error codes are given for invalid UTF-16
+ strings:
+
+ PCRE2_ERROR_UTF16_ERR1 Missing low surrogate at end of string
+ PCRE2_ERROR_UTF16_ERR2 Invalid low surrogate follows high surrogate
+ PCRE2_ERROR_UTF16_ERR3 Isolated low surrogate
+
+
+ Errors in UTF-32 strings
+
+ The following negative error codes are given for invalid UTF-32
+ strings:
+
+ PCRE2_ERROR_UTF32_ERR1 Surrogate character (0xd800 to 0xdfff)
+ PCRE2_ERROR_UTF32_ERR2 Code point is greater than 0x10ffff
+
+
+MATCHING IN INVALID UTF STRINGS
+
+ You can run pattern matches on subject strings that may contain invalid
+ UTF sequences if you call pcre2_compile() with the PCRE2_MATCH_IN-
+ VALID_UTF option. This is supported by pcre2_match(), including JIT
+ matching, but not by pcre2_dfa_match(). When PCRE2_MATCH_INVALID_UTF is
+ set, it forces PCRE2_UTF to be set as well. Note, however, that the
+ pattern itself must be a valid UTF string.
+
+ If you do not set PCRE2_MATCH_INVALID_UTF when calling pcre2_compile,
+ and you are not certain that your subject strings are valid UTF se-
+ quences, you should not make use of the JIT "fast path" function
+ pcre2_jit_match() because it bypasses sanity checks, including the one
+ for UTF validity. An invalid string may cause undefined behaviour, in-
+ cluding looping, crashing, or giving the wrong answer.
+
+ Setting PCRE2_MATCH_INVALID_UTF does not affect what pcre2_compile()
+ generates, but if pcre2_jit_compile() is subsequently called, it does
+ generate different code. If JIT is not used, the option affects the be-
+ haviour of the interpretive code in pcre2_match(). When PCRE2_MATCH_IN-
+ VALID_UTF is set at compile time, PCRE2_NO_UTF_CHECK is ignored at
+ match time.
+
+ In this mode, an invalid code unit sequence in the subject never
+ matches any pattern item. It does not match dot, it does not match
+ \p{Any}, it does not even match negative items such as [^X]. A lookbe-
+ hind assertion fails if it encounters an invalid sequence while moving
+ the current point backwards. In other words, an invalid UTF code unit
+ sequence acts as a barrier which no match can cross.
+
+ You can also think of this as the subject being split up into fragments
+ of valid UTF, delimited internally by invalid code unit sequences. The
+ pattern is matched fragment by fragment. The result of a successful
+ match, however, is given as code unit offsets in the entire subject
+ string in the usual way. There are a few points to consider:
+
+ The internal boundaries are not interpreted as the beginnings or ends
+ of lines and so do not match circumflex or dollar characters in the
+ pattern.
+
+ If pcre2_match() is called with an offset that points to an invalid
+ UTF-sequence, that sequence is skipped, and the match starts at the
+ next valid UTF character, or the end of the subject.
+
+ At internal fragment boundaries, \b and \B behave in the same way as at
+ the beginning and end of the subject. For example, a sequence such as
+ \bWORD\b would match an instance of WORD that is surrounded by invalid
+ UTF code units.
+
+ Using PCRE2_MATCH_INVALID_UTF, an application can run matches on arbi-
+ trary data, knowing that any matched strings that are returned are
+ valid UTF. This can be useful when searching for UTF text in executable
+ or other binary files.
+
+ Note, however, that the 16-bit and 32-bit PCRE2 libraries process
+ strings as sequences of uint16_t or uint32_t code points. They cannot
+ find valid UTF sequences within an arbitrary string of bytes unless
+ such sequences are suitably aligned.
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 27 November 2024
+ Copyright (c) 1997-2024 University of Cambridge.
+
+
+PCRE2 10.48 27 November 2024 PCRE2UNICODE(3)
+------------------------------------------------------------------------------
+
+
diff --git a/doc/pcre2_callout_enumerate.3 b/doc/pcre2_callout_enumerate.3
new file mode 100644
index 0000000..53b64ae
--- /dev/null
+++ b/doc/pcre2_callout_enumerate.3
@@ -0,0 +1,51 @@
+.TH PCRE2_COMPILE 3 "23 March 2017" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_callout_enumerate(const pcre2_code *\fIcode\fP,
+.B " int (*\fIcallback\fP)(pcre2_callout_enumerate_block *, void *),"
+.B " void *\fIcallout_data\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function scans a compiled regular expression and calls the \fIcallback()\fP
+function for each callout within the pattern. The yield of the function is zero
+for success and non-zero otherwise. The arguments are:
+.sp
+ \fIcode\fP Points to the compiled pattern
+ \fIcallback\fP The callback function
+ \fIcallout_data\fP User data that is passed to the callback
+.sp
+The \fIcallback()\fP function is passed a pointer to a data block containing
+the following fields (not necessarily in this order):
+.sp
+ uint32_t \fIversion\fP Block version number
+ uint32_t \fIcallout_number\fP Number for numbered callouts
+ PCRE2_SIZE \fIpattern_position\fP Offset to next item in pattern
+ PCRE2_SIZE \fInext_item_length\fP Length of next item in pattern
+ PCRE2_SIZE \fIcallout_string_offset\fP Offset to string within pattern
+ PCRE2_SIZE \fIcallout_string_length\fP Length of callout string
+ PCRE2_SPTR \fIcallout_string\fP Points to callout string or is NULL
+.sp
+The second argument passed to the \fBcallback()\fP function is the callout data
+that was passed to \fBpcre2_callout_enumerate()\fP. The \fBcallback()\fP
+function must return zero for success. Any other value causes the pattern scan
+to stop, with the value being passed back as the result of
+\fBpcre2_callout_enumerate()\fP.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_code_copy.3 b/doc/pcre2_code_copy.3
new file mode 100644
index 0000000..9fa48c0
--- /dev/null
+++ b/doc/pcre2_code_copy.3
@@ -0,0 +1,31 @@
+.TH PCRE2_CODE_COPY 3 "22 November 2016" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B pcre2_code *pcre2_code_copy(const pcre2_code *\fIcode\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function makes a copy of the memory used for a compiled pattern, excluding
+any memory used by the JIT compiler. Without a subsequent call to
+\fBpcre2_jit_compile()\fP, the copy can be used only for non-JIT matching. The
+pointer to the character tables is copied, not the tables themselves (see
+\fBpcre2_code_copy_with_tables()\fP). The yield of the function is NULL if
+\fIcode\fP is NULL or if sufficient memory cannot be obtained.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_code_copy_with_tables.3 b/doc/pcre2_code_copy_with_tables.3
new file mode 100644
index 0000000..77bb7f7
--- /dev/null
+++ b/doc/pcre2_code_copy_with_tables.3
@@ -0,0 +1,32 @@
+.TH PCRE2_CODE_COPY 3 "16 January 2017" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B pcre2_code *pcre2_code_copy_with_tables(const pcre2_code *\fIcode\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function makes a copy of the memory used for a compiled pattern, excluding
+any memory used by the JIT compiler. Without a subsequent call to
+\fBpcre2_jit_compile()\fP, the copy can be used only for non-JIT matching.
+Unlike \fBpcre2_code_copy()\fP, a separate copy of the character tables is also
+made, with the new code pointing to it. This memory will be automatically freed
+when \fBpcre2_code_free()\fP is called. The yield of the function is NULL if
+\fIcode\fP is NULL or if sufficient memory cannot be obtained.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_code_free.3 b/doc/pcre2_code_free.3
new file mode 100644
index 0000000..cfd1f62
--- /dev/null
+++ b/doc/pcre2_code_free.3
@@ -0,0 +1,30 @@
+.TH PCRE2_CODE_FREE 3 "28 June 2018" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_code_free(pcre2_code *\fIcode\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+If \fIcode\fP is NULL, this function does nothing. Otherwise, \fIcode\fP must
+point to a compiled pattern. This function frees its memory, including any
+memory used by the JIT compiler. If the compiled pattern was created by a call
+to \fBpcre2_code_copy_with_tables()\fP, the memory for the character tables is
+also freed.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_compile.3 b/doc/pcre2_compile.3
new file mode 100644
index 0000000..4c0eccd
--- /dev/null
+++ b/doc/pcre2_compile.3
@@ -0,0 +1,107 @@
+.TH PCRE2_COMPILE 3 "30 October 2024" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B pcre2_code *pcre2_compile(PCRE2_SPTR \fIpattern\fP, PCRE2_SIZE \fIlength\fP,
+.B " uint32_t \fIoptions\fP, int *\fIerrorcode\fP, PCRE2_SIZE *\fIerroroffset,\fP"
+.B " pcre2_compile_context *\fIccontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function compiles a regular expression pattern into an internal form. Its
+arguments are:
+.sp
+ \fIpattern\fP A string containing expression to be compiled
+ \fIlength\fP The length of the string or PCRE2_ZERO_TERMINATED
+ \fIoptions\fP Primary option bits
+ \fIerrorcode\fP Where to put an error code
+ \fIerroffset\fP Where to put an error offset
+ \fIccontext\fP Pointer to a compile context or NULL
+.sp
+The length of the pattern and any error offset that is returned are in code
+units, not characters. A NULL pattern with zero length is treated as an empty
+string. A compile context is needed only if you want to provide custom memory
+allocation functions, or to provide an external function for system stack size
+checking (see \fBpcre2_set_compile_recursion_guard()\fP), or to change one or
+more of these parameters:
+.sp
+ What \eR matches (Unicode newlines, or CR, LF, CRLF only);
+ PCRE2's character tables;
+ The newline character sequence;
+ The compile time nested parentheses limit;
+ The maximum pattern length (in code units) that is allowed;
+ The additional options bits.
+.sp
+The primary option bits are:
+.sp
+ PCRE2_ANCHORED Force pattern anchoring
+ PCRE2_ALLOW_EMPTY_CLASS Allow empty classes
+ PCRE2_ALT_BSUX Alternative handling of \eu, \eU, and \ex
+ PCRE2_ALT_CIRCUMFLEX Alternative handling of ^ in multiline mode
+ PCRE2_ALT_EXTENDED_CLASS Alternative extended character class syntax
+ PCRE2_ALT_VERBNAMES Process backslashes in verb names
+ PCRE2_AUTO_CALLOUT Compile automatic callouts
+ PCRE2_CASELESS Do caseless matching
+ PCRE2_DOLLAR_ENDONLY $ not to match newline at end
+ PCRE2_DOTALL . matches anything including NL
+ PCRE2_DUPNAMES Allow duplicate names for subpatterns
+ PCRE2_ENDANCHORED Pattern can match only at end of subject
+ PCRE2_EXTENDED Ignore white space and # comments
+ PCRE2_FIRSTLINE Force matching to be before newline
+ PCRE2_LITERAL Pattern characters are all literal
+ PCRE2_MATCH_INVALID_UTF Enable support for matching invalid UTF
+ PCRE2_MATCH_UNSET_BACKREF Match unset backreferences
+ PCRE2_MULTILINE ^ and $ match newlines within data
+ PCRE2_NEVER_BACKSLASH_C Lock out the use of \eC in patterns
+ PCRE2_NEVER_UCP Lock out PCRE2_UCP, e.g. via (*UCP)
+ PCRE2_NEVER_UTF Lock out PCRE2_UTF, e.g. via (*UTF)
+ PCRE2_NO_AUTO_CAPTURE Disable numbered capturing paren-
+ theses (named ones available)
+ PCRE2_NO_AUTO_POSSESS Disable auto-possessification
+ PCRE2_NO_DOTSTAR_ANCHOR Disable automatic anchoring for .*
+ PCRE2_NO_START_OPTIMIZE Disable match-time start optimizations
+ PCRE2_NO_UTF_CHECK Do not check the pattern for UTF validity
+ (only relevant if PCRE2_UTF is set)
+ PCRE2_UCP Use Unicode properties for \ed, \ew, etc.
+ PCRE2_UNGREEDY Invert greediness of quantifiers
+ PCRE2_USE_OFFSET_LIMIT Enable offset limit for unanchored matching
+ PCRE2_UTF Treat pattern and subjects as UTF strings
+.sp
+PCRE2 must be built with Unicode support (the default) in order to use
+PCRE2_UTF, PCRE2_UCP and related options.
+.P
+Additional options may be set in the compile context via the
+.\" HREF
+\fBpcre2_set_compile_extra_options\fP
+.\"
+function.
+.P
+If either of \fIerrorcode\fP or \fIerroroffset\fP is NULL, the function returns
+NULL immediately. Otherwise, the yield of this function is a pointer to a
+private data structure that contains the compiled pattern, or NULL if an error
+was detected. In the error case, a text error message can be obtained by
+passing the value returned via the \fIerrorcode\fP argument to the
+\fBpcre2_get_error_message()\fP function. The offset (in code units) where the
+error was encountered is returned via the \fIerroroffset\fP argument.
+.P
+If there is no error, the value passed via \fIerrorcode\fP returns the message
+"no error" if passed to \fBpcre2_get_error_message()\fP, and the value passed
+via \fIerroroffset\fP is zero.
+.P
+There is a complete description of the PCRE2 native API, with more detail on
+each option, in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page, and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_compile_context_copy.3 b/doc/pcre2_compile_context_copy.3
new file mode 100644
index 0000000..b8ec3d7
--- /dev/null
+++ b/doc/pcre2_compile_context_copy.3
@@ -0,0 +1,29 @@
+.TH PCRE2_COMPILE_CONTEXT_COPY 3 "25 October 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B pcre2_compile_context *pcre2_compile_context_copy(
+.B " pcre2_compile_context *\fIccontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function makes a new copy of a compile context, using the memory
+allocation function that was used for the original context. The result is NULL
+if the memory cannot be obtained.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_compile_context_create.3 b/doc/pcre2_compile_context_create.3
new file mode 100644
index 0000000..3522a05
--- /dev/null
+++ b/doc/pcre2_compile_context_create.3
@@ -0,0 +1,30 @@
+.TH PCRE2_COMPILE_CONTEXT_CREATE 3 "25 October 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B pcre2_compile_context *pcre2_compile_context_create(
+.B " pcre2_general_context *\fIgcontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function creates and initializes a new compile context. If its argument is
+NULL, \fBmalloc()\fP is used to get the necessary memory; otherwise the memory
+allocation function within the general context is used. The result is NULL if
+the memory could not be obtained.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_compile_context_free.3 b/doc/pcre2_compile_context_free.3
new file mode 100644
index 0000000..75d3585
--- /dev/null
+++ b/doc/pcre2_compile_context_free.3
@@ -0,0 +1,29 @@
+.TH PCRE2_COMPILE_CONTEXT_FREE 3 "28 June 2018" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_compile_context_free(pcre2_compile_context *\fIccontext\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function frees the memory occupied by a compile context, using the memory
+freeing function from the general context with which it was created, or
+\fBfree()\fP if that was not set. If the argument is NULL, the function returns
+immediately without doing anything.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_config.3 b/doc/pcre2_config.3
new file mode 100644
index 0000000..2414297
--- /dev/null
+++ b/doc/pcre2_config.3
@@ -0,0 +1,78 @@
+.TH PCRE2_CONFIG 3 "03 September 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_config(uint32_t \fIwhat\fP, void *\fIwhere\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function makes it possible for a client program to find out which optional
+features are available in the version of the PCRE2 library it is using. The
+arguments are as follows:
+.sp
+ \fIwhat\fP A code specifying what information is required
+ \fIwhere\fP Points to where to put the information
+.sp
+If \fIwhere\fP is NULL, the function returns the amount of memory needed for
+the requested information. When the information is a string, the value is in
+code units; for other types of data it is in bytes.
+.P
+If \fBwhere\fP is not NULL, for PCRE2_CONFIG_JITTARGET,
+PCRE2_CONFIG_UNICODE_VERSION, and PCRE2_CONFIG_VERSION it must point to a
+buffer that is large enough to hold the string. For all other codes it must
+point to a uint32_t integer variable. The available codes are:
+.sp
+ PCRE2_CONFIG_BSR Indicates what \eR matches by default:
+ PCRE2_BSR_UNICODE
+ PCRE2_BSR_ANYCRLF
+ PCRE2_CONFIG_COMPILED_WIDTHS Which of 8/16/32 support was compiled
+ PCRE2_CONFIG_DEPTHLIMIT Default backtracking depth limit
+ PCRE2_CONFIG_EFFECTIVE_LINKSIZE How many bytes are used for link size
+ PCRE2_CONFIG_HEAPLIMIT Default heap memory limit
+.\" JOIN
+ PCRE2_CONFIG_JIT Availability of just-in-time compiler
+ support (1=yes 0=no)
+.\" JOIN
+ PCRE2_CONFIG_JITTARGET Information (a string) about the target
+ architecture for the JIT compiler
+ PCRE2_CONFIG_LINKSIZE Configured internal link size (2, 3, 4)
+ PCRE2_CONFIG_MATCHLIMIT Default internal resource limit
+ PCRE2_CONFIG_NEVER_BACKSLASH_C Whether or not \eC is disabled
+ PCRE2_CONFIG_NEWLINE Code for the default newline sequence:
+ PCRE2_NEWLINE_CR
+ PCRE2_NEWLINE_LF
+ PCRE2_NEWLINE_CRLF
+ PCRE2_NEWLINE_ANY
+ PCRE2_NEWLINE_ANYCRLF
+ PCRE2_NEWLINE_NUL
+ PCRE2_CONFIG_PARENSLIMIT Default parentheses nesting limit
+ PCRE2_CONFIG_RECURSIONLIMIT Obsolete: use PCRE2_CONFIG_DEPTHLIMIT
+ PCRE2_CONFIG_STACKRECURSE Obsolete: always returns 0
+.\" JOIN
+ PCRE2_CONFIG_UNICODE Availability of Unicode support
+ (1=yes 0=no)
+ PCRE2_CONFIG_UNICODE_VERSION The Unicode version (a string)
+ PCRE2_CONFIG_VERSION The PCRE2 version (a string)
+.sp
+The function yields a non-negative value on success or the negative value
+PCRE2_ERROR_BADOPTION otherwise. This is also the result for the
+PCRE2_CONFIG_JITTARGET code if JIT support is not available. When a string is
+requested, the function returns the number of code units used, including the
+terminating zero.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_convert_context_copy.3 b/doc/pcre2_convert_context_copy.3
new file mode 100644
index 0000000..0c5178a
--- /dev/null
+++ b/doc/pcre2_convert_context_copy.3
@@ -0,0 +1,26 @@
+.TH PCRE2_CONVERT_CONTEXT_COPY 3 "12 July 2017" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B pcre2_convert_context *pcre2_convert_context_copy(
+.B " pcre2_convert_context *\fIcvcontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function is part of an experimental set of pattern conversion functions.
+It makes a new copy of a convert context, using the memory allocation function
+that was used for the original context. The result is NULL if the memory cannot
+be obtained.
+.P
+The pattern conversion functions are described in the
+.\" HREF
+\fBpcre2convert\fP
+.\"
+documentation.
diff --git a/doc/pcre2_convert_context_create.3 b/doc/pcre2_convert_context_create.3
new file mode 100644
index 0000000..16d42ee
--- /dev/null
+++ b/doc/pcre2_convert_context_create.3
@@ -0,0 +1,27 @@
+.TH PCRE2_CONVERT_CONTEXT_CREATE 3 "12 July 2017" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B pcre2_convert_context *pcre2_convert_context_create(
+.B " pcre2_general_context *\fIgcontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function is part of an experimental set of pattern conversion functions.
+It creates and initializes a new convert context. If its argument is
+NULL, \fBmalloc()\fP is used to get the necessary memory; otherwise the memory
+allocation function within the general context is used. The result is NULL if
+the memory could not be obtained.
+.P
+The pattern conversion functions are described in the
+.\" HREF
+\fBpcre2convert\fP
+.\"
+documentation.
diff --git a/doc/pcre2_convert_context_free.3 b/doc/pcre2_convert_context_free.3
new file mode 100644
index 0000000..5918645
--- /dev/null
+++ b/doc/pcre2_convert_context_free.3
@@ -0,0 +1,26 @@
+.TH PCRE2_CONVERT_CONTEXT_FREE 3 "13 August 2018" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_convert_context_free(pcre2_convert_context *\fIcvcontext\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function is part of an experimental set of pattern conversion functions.
+It frees the memory occupied by a convert context, using the memory
+freeing function from the general context with which it was created, or
+\fBfree()\fP if that was not set. If the argument is NULL, the function returns
+immediately without doing anything.
+.P
+The pattern conversion functions are described in the
+.\" HREF
+\fBpcre2convert\fP
+.\"
+documentation.
diff --git a/doc/pcre2_converted_pattern_free.3 b/doc/pcre2_converted_pattern_free.3
new file mode 100644
index 0000000..d955f79
--- /dev/null
+++ b/doc/pcre2_converted_pattern_free.3
@@ -0,0 +1,26 @@
+.TH PCRE2_CONVERTED_PATTERN_FREE 3 "13 August 2018" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_converted_pattern_free(PCRE2_UCHAR *\fIconverted_pattern\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function is part of an experimental set of pattern conversion functions.
+It frees the memory occupied by a converted pattern that was obtained by
+calling \fBpcre2_pattern_convert()\fP with arguments that caused it to place
+the converted pattern into newly obtained heap memory. If the argument is NULL,
+the function returns immediately without doing anything.
+.P
+The pattern conversion functions are described in the
+.\" HREF
+\fBpcre2convert\fP
+.\"
+documentation.
diff --git a/doc/pcre2_dfa_match.3 b/doc/pcre2_dfa_match.3
new file mode 100644
index 0000000..e5de75f
--- /dev/null
+++ b/doc/pcre2_dfa_match.3
@@ -0,0 +1,86 @@
+.TH PCRE2_DFA_MATCH 3 "31 August 2021" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_dfa_match(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
+.B " PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
+.B " uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
+.B " pcre2_match_context *\fImcontext\fP,"
+.B " int *\fIworkspace\fP, PCRE2_SIZE \fIwscount\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function matches a compiled regular expression against a given subject
+string, using an alternative matching algorithm that scans the subject string
+just once (except when processing lookaround assertions). This function is
+\fInot\fP Perl-compatible (the Perl-compatible matching function is
+\fBpcre2_match()\fP). The arguments for this function are:
+.sp
+ \fIcode\fP Points to the compiled pattern
+ \fIsubject\fP Points to the subject string
+ \fIlength\fP Length of the subject string
+ \fIstartoffset\fP Offset in the subject at which to start matching
+ \fIoptions\fP Option bits
+ \fImatch_data\fP Points to a match data block, for results
+ \fImcontext\fP Points to a match context, or is NULL
+ \fIworkspace\fP Points to a vector of ints used as working space
+ \fIwscount\fP Number of elements in the vector
+.sp
+The size of output vector needed to contain all the results depends on the
+number of simultaneous matches, not on the number of parentheses in the
+pattern. Using \fBpcre2_match_data_create_from_pattern()\fP to create the match
+data block is therefore not advisable when using this function.
+.P
+A match context is needed only if you want to set up a callout function or
+specify the heap limit or the match or the recursion depth limits. The
+\fIlength\fP and \fIstartoffset\fP values are code units, not characters. The
+options are:
+.sp
+ PCRE2_ANCHORED Match only at the first position
+ PCRE2_COPY_MATCHED_SUBJECT
+ On success, make a private subject copy
+ PCRE2_ENDANCHORED Pattern can match only at end of subject
+ PCRE2_NOTBOL Subject is not the beginning of a line
+ PCRE2_NOTEOL Subject is not the end of a line
+ PCRE2_NOTEMPTY An empty string is not a valid match
+.\" JOIN
+ PCRE2_NOTEMPTY_ATSTART An empty string at the start of the subject
+ is not a valid match
+.\" JOIN
+ PCRE2_NO_UTF_CHECK Do not check the subject for UTF
+ validity (only relevant if PCRE2_UTF
+ was set at compile time)
+.\" JOIN
+ PCRE2_PARTIAL_HARD Return PCRE2_ERROR_PARTIAL for a partial
+ match even if there is a full match
+.\" JOIN
+ PCRE2_PARTIAL_SOFT Return PCRE2_ERROR_PARTIAL for a partial
+ match if no full matches are found
+ PCRE2_DFA_RESTART Restart after a partial match
+ PCRE2_DFA_SHORTEST Return only the shortest match
+.sp
+There are restrictions on what may appear in a pattern when using this matching
+function. Details are given in the
+.\" HREF
+\fBpcre2matching\fP
+.\"
+documentation. For details of partial matching, see the
+.\" HREF
+\fBpcre2partial\fP
+.\"
+page. There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_general_context_copy.3 b/doc/pcre2_general_context_copy.3
new file mode 100644
index 0000000..3993cd2
--- /dev/null
+++ b/doc/pcre2_general_context_copy.3
@@ -0,0 +1,30 @@
+.TH PCRE2_GENERAL_CONTEXT_COPY 3 "25 October 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B pcre2_general_context *pcre2_general_context_copy(
+.B " pcre2_general_context *\fIgcontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function makes a new copy of a general context, using the memory
+allocation functions in the context, if set, to get the necessary memory.
+Otherwise \fBmalloc()\fP is used. The result is NULL if the memory cannot be
+obtained.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_general_context_create.3 b/doc/pcre2_general_context_create.3
new file mode 100644
index 0000000..cc85e45
--- /dev/null
+++ b/doc/pcre2_general_context_create.3
@@ -0,0 +1,32 @@
+.TH PCRE2_GENERAL_CONTEXT_CREATE 3 "23 January 2023" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B pcre2_general_context *pcre2_general_context_create(
+.B " void *(*\fIprivate_malloc\fP)(size_t, void *),"
+.B " void (*\fIprivate_free\fP)(void *, void *), void *\fImemory_data\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function creates and initializes a general context. The arguments define
+custom memory management functions and a data value that is passed to them when
+they are called. The \fBprivate_malloc()\fP function is used to get memory for
+the context. If either of the first two arguments is NULL, the system memory
+management function is used. The result is NULL if no memory could be obtained.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_general_context_free.3 b/doc/pcre2_general_context_free.3
new file mode 100644
index 0000000..8069c65
--- /dev/null
+++ b/doc/pcre2_general_context_free.3
@@ -0,0 +1,28 @@
+.TH PCRE2_GENERAL_CONTEXT_FREE 3 "28 June 2018" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_general_context_free(pcre2_general_context *\fIgcontext\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function frees the memory occupied by a general context, using the memory
+freeing function within the context, if set. If the argument is NULL, the
+function returns immediately without doing anything.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_get_error_message.3 b/doc/pcre2_get_error_message.3
new file mode 100644
index 0000000..7d87341
--- /dev/null
+++ b/doc/pcre2_get_error_message.3
@@ -0,0 +1,39 @@
+.TH PCRE2_GET_ERROR_MESSAGE 3 "24 March 2017" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_get_error_message(int \fIerrorcode\fP, PCRE2_UCHAR *\fIbuffer\fP,
+.B " PCRE2_SIZE \fIbufflen\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function provides a textual error message for each PCRE2 error code.
+Compilation errors are positive numbers; UTF formatting errors and matching
+errors are negative numbers. The arguments are:
+.sp
+ \fIerrorcode\fP an error code (positive or negative)
+ \fIbuffer\fP where to put the message
+ \fIbufflen\fP the length of the buffer (code units)
+.sp
+The function returns the length of the message in code units, excluding the
+trailing zero, or the negative error code PCRE2_ERROR_NOMEMORY if the buffer is
+too small. In this case, the returned message is truncated (but still with a
+trailing zero). If \fIerrorcode\fP does not contain a recognized error code
+number, the negative value PCRE2_ERROR_BADDATA is returned.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_get_mark.3 b/doc/pcre2_get_mark.3
new file mode 100644
index 0000000..4e870ae
--- /dev/null
+++ b/doc/pcre2_get_mark.3
@@ -0,0 +1,34 @@
+.TH PCRE2_GET_MARK 3 "13 January 2018" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B PCRE2_SPTR pcre2_get_mark(pcre2_match_data *\fImatch_data\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+After a call of \fBpcre2_match()\fP that was passed the match block that is
+this function's argument, this function returns a pointer to the last (*MARK),
+(*PRUNE), or (*THEN) name that was encountered during the matching process. The
+name is zero-terminated, and is within the compiled pattern. The length of the
+name is in the preceding code unit. If no name is available, NULL is returned.
+.P
+After a successful match, the name that is returned is the last one on the
+matching path. After a failed match or a partial match, the last encountered
+name is returned.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_get_match_data_heapframes_size.3 b/doc/pcre2_get_match_data_heapframes_size.3
new file mode 100644
index 0000000..33f016e
--- /dev/null
+++ b/doc/pcre2_get_match_data_heapframes_size.3
@@ -0,0 +1,28 @@
+.TH PCRE2_GET_MATCH_DATA_HEAPFRAMES_SIZE 3 "18 January 2023" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B PCRE2_SIZE pcre2_get_match_data_heapframes_size(
+.B " pcre2_match_data *\fImatch_data\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function returns the size, in bytes, of the heapframes data block that is
+owned by its argument.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_get_match_data_size.3 b/doc/pcre2_get_match_data_size.3
new file mode 100644
index 0000000..5216e99
--- /dev/null
+++ b/doc/pcre2_get_match_data_size.3
@@ -0,0 +1,27 @@
+.TH PCRE2_GET_MATCH_DATA_SIZE 3 "17 October 2019" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B PCRE2_SIZE pcre2_get_match_data_size(pcre2_match_data *\fImatch_data\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function returns the size, in bytes, of the match data block that is its
+argument.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_get_ovector_count.3 b/doc/pcre2_get_ovector_count.3
new file mode 100644
index 0000000..803d39e
--- /dev/null
+++ b/doc/pcre2_get_ovector_count.3
@@ -0,0 +1,27 @@
+.TH PCRE2_GET_OVECTOR_COUNT 3 "25 October 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B uint32_t pcre2_get_ovector_count(pcre2_match_data *\fImatch_data\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function returns the number of pairs of offsets in the ovector that forms
+part of the given match data block.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_get_ovector_pointer.3 b/doc/pcre2_get_ovector_pointer.3
new file mode 100644
index 0000000..bc42d3d
--- /dev/null
+++ b/doc/pcre2_get_ovector_pointer.3
@@ -0,0 +1,28 @@
+.TH PCRE2_GET_OVECTOR_POINTER 3 "25 October 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B PCRE2_SIZE *pcre2_get_ovector_pointer(pcre2_match_data *\fImatch_data\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function returns a pointer to the vector of offsets that forms part of the
+given match data block. The number of pairs can be found by calling
+\fBpcre2_get_ovector_count()\fP.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_get_startchar.3 b/doc/pcre2_get_startchar.3
new file mode 100644
index 0000000..40a8ba6
--- /dev/null
+++ b/doc/pcre2_get_startchar.3
@@ -0,0 +1,32 @@
+.TH PCRE2_GET_STARTCHAR 3 "25 October 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B PCRE2_SIZE pcre2_get_startchar(pcre2_match_data *\fImatch_data\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+After a successful call of \fBpcre2_match()\fP that was passed the match block
+that is this function's argument, this function returns the code unit offset of
+the character at which the successful match started. For a non-partial match,
+this can be different to the value of \fIovector[0]\fP if the pattern contains
+the \eK escape sequence. After a partial match, however, this value is always
+the same as \fIovector[0]\fP because \eK does not affect the result of a
+partial match.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_jit_compile.3 b/doc/pcre2_jit_compile.3
new file mode 100644
index 0000000..bc95717
--- /dev/null
+++ b/doc/pcre2_jit_compile.3
@@ -0,0 +1,61 @@
+.TH PCRE2_JIT_COMPILE 3 "22 August 2024" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_jit_compile(pcre2_code *\fIcode\fP, uint32_t \fIoptions\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function requests JIT compilation, which, if the just-in-time compiler is
+available, further processes a compiled pattern into machine code that executes
+much faster than the \fBpcre2_match()\fP interpretive matching function. Full
+details are given in the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+documentation.
+.P
+The availability of JIT support can be tested by calling
+\fBpcre2_compile_jit()\fP with a single option PCRE2_JIT_TEST_ALLOC (the
+code argument is ignored, so a NULL value is accepted). Such a call
+returns zero if JIT is available and has a working allocator. Otherwise
+it returns PCRE2_ERROR_NOMEMORY if JIT is available but cannot allocate
+executable memory, or PCRE2_ERROR_JIT_UNSUPPORTED if JIT support is not
+compiled.
+.P
+Otherwise, the first argument must be a pointer that was returned by a
+successful call to \fBpcre2_compile()\fP, and the second must contain one or
+more of the following bits:
+.sp
+ PCRE2_JIT_COMPLETE compile code for full matching
+ PCRE2_JIT_PARTIAL_SOFT compile code for soft partial matching
+ PCRE2_JIT_PARTIAL_HARD compile code for hard partial matching
+.sp
+There is also an obsolete option called PCRE2_JIT_INVALID_UTF, which has been
+superseded by the \fBpcre2_compile()\fP option PCRE2_MATCH_INVALID_UTF. The old
+option is deprecated and may be removed in the future.
+.P
+The yield of the function when called with any of the three options above is 0
+for success, or a negative error code otherwise. In particular,
+PCRE2_ERROR_JIT_BADOPTION is returned if JIT is not supported or if an unknown
+bit is set in \fIoptions\fP. The function can also return PCRE2_ERROR_NOMEMORY
+if JIT is unable to allocate executable memory for the compiler, even if it was
+because of a system security restriction. In a few cases, the function may
+return with PCRE2_ERROR_JIT_UNSUPPORTED for unsupported features.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_jit_free_unused_memory.3 b/doc/pcre2_jit_free_unused_memory.3
new file mode 100644
index 0000000..c0318da
--- /dev/null
+++ b/doc/pcre2_jit_free_unused_memory.3
@@ -0,0 +1,31 @@
+.TH PCRE2_JIT_FREE_UNUSED_MEMORY 3 "24 April 2020" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_jit_free_unused_memory(pcre2_general_context *\fIgcontext\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function frees unused JIT executable memory. The argument is a general
+context, for custom memory management, or NULL for standard memory management.
+JIT memory allocation retains some memory in order to improve future JIT
+compilation speed. In low memory conditions,
+\fBpcre2_jit_free_unused_memory()\fP can be used to cause this memory to be
+freed.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_jit_match.3 b/doc/pcre2_jit_match.3
new file mode 100644
index 0000000..5cc914b
--- /dev/null
+++ b/doc/pcre2_jit_match.3
@@ -0,0 +1,58 @@
+.TH PCRE2_JIT_MATCH 3 "20 January 2023" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_jit_match(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
+.B " PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
+.B " uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
+.B " pcre2_match_context *\fImcontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function matches a compiled regular expression that has been successfully
+processed by the JIT compiler against a given subject string, using a matching
+algorithm that is similar to Perl's. It is a "fast path" interface to JIT, and
+it bypasses some of the sanity checks that \fBpcre2_match()\fP applies.
+.P
+In UTF mode, the subject string is not checked for UTF validity. Unless
+PCRE2_MATCH_INVALID_UTF was set when the pattern was compiled, passing an
+invalid UTF string results in undefined behaviour. Your program may crash or
+loop or give wrong results. In the absence of PCRE2_MATCH_INVALID_UTF you
+should only call \fBpcre2_jit_match()\fP in UTF mode if you are sure the
+subject is valid.
+.P
+The arguments for \fBpcre2_jit_match()\fP are exactly the same as for
+.\" HREF
+\fBpcre2_match()\fP,
+.\"
+except that the subject string must be specified with a length;
+PCRE2_ZERO_TERMINATED is not supported.
+.P
+The supported options are PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY,
+PCRE2_NOTEMPTY_ATSTART, PCRE2_PARTIAL_HARD, and PCRE2_PARTIAL_SOFT. Unsupported
+options are ignored.
+.P
+The return values are the same as for \fBpcre2_match()\fP plus
+PCRE2_ERROR_JIT_BADOPTION if a matching mode (partial or complete) is requested
+that was not compiled. For details of partial matching, see the
+.\" HREF
+\fBpcre2partial\fP
+.\"
+page.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the JIT API in the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+page.
diff --git a/doc/pcre2_jit_stack_assign.3 b/doc/pcre2_jit_stack_assign.3
new file mode 100644
index 0000000..7605632
--- /dev/null
+++ b/doc/pcre2_jit_stack_assign.3
@@ -0,0 +1,59 @@
+.TH PCRE2_JIT_STACK_ASSIGN 3 "13 August 2018" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_jit_stack_assign(pcre2_match_context *\fImcontext\fP,
+.B " pcre2_jit_callback \fIcallback_function\fP, void *\fIcallback_data\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function provides control over the memory used by JIT as a run-time stack
+when \fBpcre2_match()\fP or \fBpcre2_jit_match()\fP is called with a pattern
+that has been successfully processed by the JIT compiler. The information that
+determines which stack is used is put into a match context that is subsequently
+passed to a matching function. The arguments of this function are:
+.sp
+ mcontext a pointer to a match context
+ callback a callback function
+ callback_data a JIT stack or a value to be passed to the callback
+.P
+If \fImcontext\fP is NULL, the function returns immediately, without doing
+anything.
+.P
+If \fIcallback\fP is NULL and \fIcallback_data\fP is NULL, an internal 32KiB
+block on the machine stack is used.
+.P
+If \fIcallback\fP is NULL and \fIcallback_data\fP is not NULL,
+\fIcallback_data\fP must be a valid JIT stack, the result of calling
+\fBpcre2_jit_stack_create()\fP.
+.P
+If \fIcallback\fP not NULL, it is called with \fIcallback_data\fP as an
+argument at the start of matching, in order to set up a JIT stack. If the
+result is NULL, the internal 32KiB stack is used; otherwise the return value
+must be a valid JIT stack, the result of calling
+\fBpcre2_jit_stack_create()\fP.
+.P
+You may safely use the same JIT stack for multiple patterns, as long as they
+are all matched in the same thread. In a multithread application, each thread
+must use its own JIT stack. For more details, see the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+page.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_jit_stack_create.3 b/doc/pcre2_jit_stack_create.3
new file mode 100644
index 0000000..318d850
--- /dev/null
+++ b/doc/pcre2_jit_stack_create.3
@@ -0,0 +1,40 @@
+.TH PCRE2_JIT_STACK_CREATE 3 "23 January 2023" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B pcre2_jit_stack *pcre2_jit_stack_create(size_t \fIstartsize\fP,
+.B " size_t \fImaxsize\fP, pcre2_general_context *\fIgcontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function is used to create a stack for use by the code compiled by the JIT
+compiler. The first two arguments are a starting size for the stack, and a
+maximum size to which it is allowed to grow. The final argument is a general
+context, for memory allocation functions, or NULL for standard memory
+allocation. The result can be passed to the JIT run-time code by calling
+\fBpcre2_jit_stack_assign()\fP to associate the stack with a compiled pattern,
+which can then be processed by \fBpcre2_match()\fP or \fBpcre2_jit_match()\fP.
+A maximum stack size of 512KiB to 1MiB should be more than enough for any
+pattern. If the stack couldn't be allocated or the values passed were not
+reasonable, NULL will be returned. For more details, see the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+page.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_jit_stack_free.3 b/doc/pcre2_jit_stack_free.3
new file mode 100644
index 0000000..bd0c6ea
--- /dev/null
+++ b/doc/pcre2_jit_stack_free.3
@@ -0,0 +1,33 @@
+.TH PCRE2_JIT_STACK_FREE 3 "26 February 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_jit_stack_free(pcre2_jit_stack *\fIjit_stack\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function is used to free a JIT stack that was created by
+\fBpcre2_jit_stack_create()\fP when it is no longer needed. If the argument is
+NULL, the function returns immediately without doing anything. For more
+details, see the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+page.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_maketables.3 b/doc/pcre2_maketables.3
new file mode 100644
index 0000000..7efba74
--- /dev/null
+++ b/doc/pcre2_maketables.3
@@ -0,0 +1,37 @@
+.TH PCRE2_MAKETABLES 3 "26 February 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B const uint8_t *pcre2_maketables(pcre2_general_context *\fIgcontext\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function builds a set of character tables for character code points that
+are less than 256. These can be passed to \fBpcre2_compile()\fP in a compile
+context in order to override the internal, built-in tables (which were either
+defaulted or made by \fBpcre2_maketables()\fP when PCRE2 was compiled). See the
+.\" HREF
+\fBpcre2_set_character_tables()\fP
+.\"
+page. You might want to do this if you are using a non-standard locale.
+.P
+If the argument is NULL, \fBmalloc()\fP is used to get memory for the tables.
+Otherwise it must point to a general context, which can supply pointers to a
+custom memory manager. The function yields a pointer to the tables.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_maketables_free.3 b/doc/pcre2_maketables_free.3
new file mode 100644
index 0000000..9031c99
--- /dev/null
+++ b/doc/pcre2_maketables_free.3
@@ -0,0 +1,31 @@
+.TH PCRE2_MAKETABLES_FREE 3 "03 September 2019" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_maketables_free(pcre2_general_context *\fIgcontext\fP,
+.B " const uint8_t *\fItables\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function discards a set of character tables that were created by a call
+to
+.\" HREF
+\fBpcre2_maketables()\fP.
+.\"
+.P
+The \fIgcontext\fP parameter should match what was used in that call to
+account for any custom allocators that might be in use; if it is NULL
+the system \fBfree()\fP is used.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page.
diff --git a/doc/pcre2_match.3 b/doc/pcre2_match.3
new file mode 100644
index 0000000..4fe04ff
--- /dev/null
+++ b/doc/pcre2_match.3
@@ -0,0 +1,86 @@
+.TH PCRE2_MATCH 3 "27 January 2024" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_match(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
+.B " PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
+.B " uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
+.B " pcre2_match_context *\fImcontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function matches a compiled regular expression against a given subject
+string, using a matching algorithm that is similar to Perl's. It returns
+offsets to what it has matched and to captured substrings via the
+\fBmatch_data\fP block, which can be processed by functions with names that
+start with \fBpcre2_get_ovector_...()\fP or \fBpcre2_substring_...()\fP. The
+return from \fBpcre2_match()\fP is one more than the highest numbered capturing
+pair that has been set (for example, 1 if there are no captures), zero if the
+vector of offsets is too small, or a negative error code for no match and other
+errors. The function arguments are:
+.sp
+ \fIcode\fP Points to the compiled pattern
+ \fIsubject\fP Points to the subject string
+ \fIlength\fP Length of the subject string
+ \fIstartoffset\fP Offset in the subject at which to start matching
+ \fIoptions\fP Option bits
+ \fImatch_data\fP Points to a match data block, for results
+ \fImcontext\fP Points to a match context, or is NULL
+.sp
+A match context is needed only if you want to:
+.sp
+ Set up a callout function
+ Set a matching offset limit
+ Change the heap memory limit
+ Change the backtracking match limit
+ Change the backtracking depth limit
+ Set custom memory management specifically for the match
+.sp
+The \fIlength\fP and \fIstartoffset\fP values are code units, not characters.
+The length may be given as PCRE2_ZERO_TERMINATED for a subject that is
+terminated by a binary zero code unit. The options are:
+.sp
+ PCRE2_ANCHORED Match only at the first position
+ PCRE2_COPY_MATCHED_SUBJECT
+ On success, make a private subject copy
+ PCRE2_DISABLE_RECURSELOOP_CHECK
+ Only useful in rare cases; use with care
+ PCRE2_ENDANCHORED Pattern can match only at end of subject
+ PCRE2_NOTBOL Subject string is not the beginning of a line
+ PCRE2_NOTEOL Subject string is not the end of a line
+ PCRE2_NOTEMPTY An empty string is not a valid match
+.\" JOIN
+ PCRE2_NOTEMPTY_ATSTART An empty string at the start of the subject
+ is not a valid match
+ PCRE2_NO_JIT Do not use JIT matching
+.\" JOIN
+ PCRE2_NO_UTF_CHECK Do not check the subject for UTF
+ validity (only relevant if PCRE2_UTF
+ was set at compile time)
+.\" JOIN
+ PCRE2_PARTIAL_HARD Return PCRE2_ERROR_PARTIAL for a partial
+ match even if there is a full match
+.\" JOIN
+ PCRE2_PARTIAL_SOFT Return PCRE2_ERROR_PARTIAL for a partial
+ match if no full matches are found
+.sp
+For details of partial matching, see the
+.\" HREF
+\fBpcre2partial\fP
+.\"
+page. There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_match_context_copy.3 b/doc/pcre2_match_context_copy.3
new file mode 100644
index 0000000..381391f
--- /dev/null
+++ b/doc/pcre2_match_context_copy.3
@@ -0,0 +1,29 @@
+.TH PCRE2_MATCH_CONTEXT_COPY 3 "25 October 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B pcre2_match_context *pcre2_match_context_copy(
+.B " pcre2_match_context *\fImcontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function makes a new copy of a match context, using the memory
+allocation function that was used for the original context. The result is NULL
+if the memory cannot be obtained.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_match_context_create.3 b/doc/pcre2_match_context_create.3
new file mode 100644
index 0000000..94887bb
--- /dev/null
+++ b/doc/pcre2_match_context_create.3
@@ -0,0 +1,30 @@
+.TH PCRE2_MATCH_CONTEXT_CREATE 3 "25 October 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B pcre2_match_context *pcre2_match_context_create(
+.B " pcre2_general_context *\fIgcontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function creates and initializes a new match context. If its argument is
+NULL, \fBmalloc()\fP is used to get the necessary memory; otherwise the memory
+allocation function within the general context is used. The result is NULL if
+the memory could not be obtained.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_match_context_free.3 b/doc/pcre2_match_context_free.3
new file mode 100644
index 0000000..199f7e1
--- /dev/null
+++ b/doc/pcre2_match_context_free.3
@@ -0,0 +1,29 @@
+.TH PCRE2_MATCH_CONTEXT_FREE 3 "28 June 2018" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_match_context_free(pcre2_match_context *\fImcontext\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function frees the memory occupied by a match context, using the memory
+freeing function from the general context with which it was created, or
+\fBfree()\fP if that was not set. If the argument is NULL, the function returns
+immediately without doing anything.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_match_data_create.3 b/doc/pcre2_match_data_create.3
new file mode 100644
index 0000000..068cefe
--- /dev/null
+++ b/doc/pcre2_match_data_create.3
@@ -0,0 +1,37 @@
+.TH PCRE2_MATCH_DATA_CREATE 3 "28 August 2021" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B pcre2_match_data *pcre2_match_data_create(uint32_t \fIovecsize\fP,
+.B " pcre2_general_context *\fIgcontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function creates a new match data block, which is used for holding the
+result of a match. The first argument specifies the number of pairs of offsets
+that are required. These form the "output vector" (ovector) within the match
+data block, and are used to identify the matched string and any captured
+substrings when matching with \fBpcre2_match()\fP, or a number of different
+matches at the same point when used with \fBpcre2_dfa_match()\fP. There is
+always one pair of offsets; if \fBovecsize\fP is zero, it is treated as one.
+.P
+The second argument points to a general context, for custom memory management,
+or is NULL for system memory management. The result of the function is NULL if
+the memory for the block could not be obtained.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_match_data_create_from_pattern.3 b/doc/pcre2_match_data_create_from_pattern.3
new file mode 100644
index 0000000..10eb594
--- /dev/null
+++ b/doc/pcre2_match_data_create_from_pattern.3
@@ -0,0 +1,40 @@
+.TH PCRE2_MATCH_DATA_CREATE_FROM_PATTERN 3 "11 August 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B pcre2_match_data *pcre2_match_data_create_from_pattern(
+.B " const pcre2_code *\fIcode\fP, pcre2_general_context *\fIgcontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function creates a new match data block for holding the result of a match.
+If the first argument is NULL, this function returns NULL, otherwise the first
+argument points to a compiled pattern. The number of capturing parentheses
+within the pattern is used to compute the number of pairs of offsets that are
+required in the match data block. These form the "output vector" (ovector)
+within the match data block, and are used to identify the matched string and
+any captured substrings when matching with \fBpcre2_match()\fP. If you are
+using \fBpcre2_dfa_match()\fP, which uses the output vector in a different way,
+you should use \fBpcre2_match_data_create()\fP instead of this function.
+.P
+The second argument points to a general context, for custom memory management,
+or is NULL to use the same memory allocator that was used for the compiled
+pattern. The result of the function is NULL if the memory for the block could
+not be obtained or if NULL was provided as the first argument.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_match_data_free.3 b/doc/pcre2_match_data_free.3
new file mode 100644
index 0000000..6e2d8dc
--- /dev/null
+++ b/doc/pcre2_match_data_free.3
@@ -0,0 +1,35 @@
+.TH PCRE2_MATCH_DATA_FREE 3 "16 August 2023" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_match_data_free(pcre2_match_data *\fImatch_data\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+If \fImatch_data\fP is NULL, this function does nothing. Otherwise,
+\fImatch_data\fP must point to a match data block, which this function frees,
+using the memory freeing function from the general context or compiled pattern
+with which it was created, or \fBfree()\fP if that was not set. If the match
+data block was previously passed to \fBpcre2_match()\fP, it will have an
+attached heapframe vector; this is also freed.
+.P
+If the PCRE2_COPY_MATCHED_SUBJECT was used for a successful match using this
+match data block, the copy of the subject that was referenced within the block
+is also freed.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_next_match.3 b/doc/pcre2_next_match.3
new file mode 100644
index 0000000..44da3d2
--- /dev/null
+++ b/doc/pcre2_next_match.3
@@ -0,0 +1,41 @@
+.TH PCRE2_NEXT_MATCH 3 "24 March 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_next_match(pcre2_match_data *\fImatch_data\fP,
+.B " PCRE2_SIZE *\fIpstart_offset\fP, uint32_t *\fIpoptions\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function can be called after one of the match functions
+(\fBpcre2_match()\fP, \fBpcre2_dfa_match()\fP, or \fBpcre2_jit_match()\fP), and
+must be provided with the same \fImatch_data\fP parameter. It outputs the
+appropriate parameters for searching for the next match in the same subject
+string, and is suitable for applications providing "global" matching behaviour
+(for example, replacing all matches in the subject, or splitting the subject on
+all matches, or simply counting the number of matches).
+.P
+It returns 0 ("false") if there is no need to make any further match attempts,
+or 1 ("true") if another match should be attempted.
+.P
+The *\fIpstart_offset\fP and *\fIpoptions\fP are set if the function returns 1.
+The *\fIpstart_offset\fP should be passed to the next match attempt directly,
+and the *\fIpoptions\fP should be passed to the next match attempt by combining
+with the application's match options using OR.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_pattern_convert.3 b/doc/pcre2_pattern_convert.3
new file mode 100644
index 0000000..d6f3c68
--- /dev/null
+++ b/doc/pcre2_pattern_convert.3
@@ -0,0 +1,55 @@
+.TH PCRE2_PATTERN_CONVERT 3 "12 July 2017" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_pattern_convert(PCRE2_SPTR \fIpattern\fP, PCRE2_SIZE \fIlength\fP,
+.B " uint32_t \fIoptions\fP, PCRE2_UCHAR **\fIbuffer\fP,"
+.B " PCRE2_SIZE *\fIblength\fP, pcre2_convert_context *\fIcvcontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function is part of an experimental set of pattern conversion functions.
+It converts a foreign pattern (for example, a glob) into a PCRE2 regular
+expression pattern. Its arguments are:
+.sp
+ \fIpattern\fP The foreign pattern
+ \fIlength\fP The length of the input pattern or PCRE2_ZERO_TERMINATED
+ \fIoptions\fP Option bits
+ \fIbuffer\fP Pointer to pointer to output buffer, or NULL
+ \fIblength\fP Pointer to output length field
+ \fIcvcontext\fP Pointer to a convert context or NULL
+.sp
+The length of the converted pattern (excluding the terminating zero) is
+returned via \fIblength\fP. If \fIbuffer\fP is NULL, the function just returns
+the output length. If \fIbuffer\fP points to a NULL pointer, heap memory is
+obtained for the converted pattern, using the allocator in the context if
+present (or else \fBmalloc()\fP), and the field pointed to by \fIbuffer\fP is
+updated. If \fIbuffer\fP points to a non-NULL field, that must point to a
+buffer whose size is in the variable pointed to by \fIblength\fP. This value is
+updated.
+.P
+The option bits are:
+.sp
+ PCRE2_CONVERT_UTF Input is UTF
+ PCRE2_CONVERT_NO_UTF_CHECK Do not check UTF validity
+ PCRE2_CONVERT_POSIX_BASIC Convert POSIX basic pattern
+ PCRE2_CONVERT_POSIX_EXTENDED Convert POSIX extended pattern
+ PCRE2_CONVERT_GLOB ) Convert
+ PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR ) various types
+ PCRE2_CONVERT_GLOB_NO_STARSTAR ) of glob
+.sp
+The return value from \fBpcre2_pattern_convert()\fP is zero on success or a
+non-zero PCRE2 error code.
+.P
+The pattern conversion functions are described in the
+.\" HREF
+\fBpcre2convert\fP
+.\"
+documentation.
diff --git a/doc/pcre2_pattern_info.3 b/doc/pcre2_pattern_info.3
new file mode 100644
index 0000000..51d40f3
--- /dev/null
+++ b/doc/pcre2_pattern_info.3
@@ -0,0 +1,108 @@
+.TH PCRE2_PATTERN_INFO 3 "14 February 2019" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_pattern_info(const pcre2_code *\fIcode\fP, uint32_t \fIwhat\fP,
+.B " void *\fIwhere\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function returns information about a compiled pattern. Its arguments are:
+.sp
+ \fIcode\fP Pointer to a compiled regular expression pattern
+ \fIwhat\fP What information is required
+ \fIwhere\fP Where to put the information
+.sp
+The recognized values for the \fIwhat\fP argument, and the information they
+request are as follows:
+.sp
+ PCRE2_INFO_ALLOPTIONS Final options after compiling
+ PCRE2_INFO_ARGOPTIONS Options passed to \fBpcre2_compile()\fP
+ PCRE2_INFO_BACKREFMAX Number of highest backreference
+ PCRE2_INFO_BSR What \eR matches:
+ PCRE2_BSR_UNICODE: Unicode line endings
+ PCRE2_BSR_ANYCRLF: CR, LF, or CRLF only
+ PCRE2_INFO_CAPTURECOUNT Number of capturing subpatterns
+.\" JOIN
+ PCRE2_INFO_DEPTHLIMIT Backtracking depth limit if set,
+ otherwise PCRE2_ERROR_UNSET
+ PCRE2_INFO_EXTRAOPTIONS Extra options that were passed in the
+ compile context
+ PCRE2_INFO_FIRSTBITMAP Bitmap of first code units, or NULL
+ PCRE2_INFO_FIRSTCODETYPE Type of start-of-match information
+ 0 nothing set
+ 1 first code unit is set
+ 2 start of string or after newline
+ PCRE2_INFO_FIRSTCODEUNIT First code unit when type is 1
+ PCRE2_INFO_FRAMESIZE Size of backtracking frame
+ PCRE2_INFO_HASBACKSLASHC Return 1 if pattern contains \eC
+.\" JOIN
+ PCRE2_INFO_HASCRORLF Return 1 if explicit CR or LF matches
+ exist in the pattern
+.\" JOIN
+ PCRE2_INFO_HEAPLIMIT Heap memory limit if set,
+ otherwise PCRE2_ERROR_UNSET
+ PCRE2_INFO_JCHANGED Return 1 if (?J) or (?-J) was used
+ PCRE2_INFO_JITSIZE Size of JIT compiled code, or 0
+ PCRE2_INFO_LASTCODETYPE Type of must-be-present information
+ 0 nothing set
+ 1 code unit is set
+ PCRE2_INFO_LASTCODEUNIT Last code unit when type is 1
+.\" JOIN
+ PCRE2_INFO_MATCHEMPTY 1 if the pattern can match an
+ empty string, 0 otherwise
+.\" JOIN
+ PCRE2_INFO_MATCHLIMIT Match limit if set,
+ otherwise PCRE2_ERROR_UNSET
+.\" JOIN
+ PCRE2_INFO_MAXLOOKBEHIND Length (in characters) of the longest
+ lookbehind assertion
+ PCRE2_INFO_MINLENGTH Lower bound length of matching strings
+ PCRE2_INFO_NAMECOUNT Number of named subpatterns
+ PCRE2_INFO_NAMEENTRYSIZE Size of name table entries
+ PCRE2_INFO_NAMETABLE Pointer to name table
+ PCRE2_CONFIG_NEWLINE Code for the newline sequence:
+ PCRE2_NEWLINE_CR
+ PCRE2_NEWLINE_LF
+ PCRE2_NEWLINE_CRLF
+ PCRE2_NEWLINE_ANY
+ PCRE2_NEWLINE_ANYCRLF
+ PCRE2_NEWLINE_NUL
+ PCRE2_INFO_RECURSIONLIMIT Obsolete synonym for PCRE2_INFO_DEPTHLIMIT
+ PCRE2_INFO_SIZE Size of compiled pattern
+.sp
+If \fIwhere\fP is NULL, the function returns the amount of memory needed for
+the requested information, in bytes. Otherwise, the \fIwhere\fP argument must
+point to an unsigned 32-bit integer (uint32_t variable), except for the
+following \fIwhat\fP values, when it must point to a variable of the type
+shown:
+.sp
+ PCRE2_INFO_FIRSTBITMAP const uint8_t *
+ PCRE2_INFO_JITSIZE size_t
+ PCRE2_INFO_NAMETABLE PCRE2_SPTR
+ PCRE2_INFO_SIZE size_t
+.sp
+The yield of the function is zero on success or:
+.sp
+ PCRE2_ERROR_NULL the argument \fIcode\fP is NULL
+ PCRE2_ERROR_BADMAGIC the "magic number" was not found
+ PCRE2_ERROR_BADOPTION the value of \fIwhat\fP is invalid
+ PCRE2_ERROR_BADMODE the pattern was compiled in the wrong mode
+ PCRE2_ERROR_UNSET the requested information is not set
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_serialize_decode.3 b/doc/pcre2_serialize_decode.3
new file mode 100644
index 0000000..9e4af0c
--- /dev/null
+++ b/doc/pcre2_serialize_decode.3
@@ -0,0 +1,53 @@
+.TH PCRE2_SERIALIZE_DECODE 3 "22 April 2022" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int32_t pcre2_serialize_decode(pcre2_code **\fIcodes\fP,
+.B " int32_t \fInumber_of_codes\fP, const uint8_t *\fIbytes\fP,"
+.B " pcre2_general_context *\fIgcontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function decodes a serialized set of compiled patterns back into a list of
+individual patterns. This is possible only on a host that is running the same
+version of PCRE2, with the same code unit width, and the host must also have
+the same endianness, pointer width and PCRE2_SIZE type. The arguments for
+\fBpcre2_serialize_decode()\fP are:
+.sp
+ \fIcodes\fP pointer to a vector in which to build the list
+ \fInumber_of_codes\fP number of slots in the vector
+ \fIbytes\fP the serialized byte stream
+ \fIgcontext\fP pointer to a general context or NULL
+.sp
+The \fIbytes\fP argument must point to a block of data that was originally
+created by \fBpcre2_serialize_encode()\fP, though it may have been saved on
+disc or elsewhere in the meantime. If there are more codes in the serialized
+data than slots in the list, only those compiled patterns that will fit are
+decoded. The yield of the function is the number of decoded patterns, or one of
+the following negative error codes:
+.sp
+ PCRE2_ERROR_BADDATA \fInumber_of_codes\fP is zero or less
+ PCRE2_ERROR_BADMAGIC mismatch of id bytes in \fIbytes\fP
+ PCRE2_ERROR_BADMODE mismatch of variable unit size or PCRE version
+ PCRE2_ERROR_NOMEMORY memory allocation failed
+ PCRE2_ERROR_NULL \fIcodes\fP or \fIbytes\fP is NULL
+.sp
+PCRE2_ERROR_BADMAGIC may mean that the data is corrupt, or that it was compiled
+on a system with different endianness.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the serialization functions in the
+.\" HREF
+\fBpcre2serialize\fP
+.\"
+page.
diff --git a/doc/pcre2_serialize_encode.3 b/doc/pcre2_serialize_encode.3
new file mode 100644
index 0000000..e5d8ae6
--- /dev/null
+++ b/doc/pcre2_serialize_encode.3
@@ -0,0 +1,54 @@
+.TH PCRE2_SERIALIZE_ENCODE 3 "13 August 2018" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int32_t pcre2_serialize_encode(const pcre2_code **\fIcodes\fP,
+.B " int32_t \fInumber_of_codes\fP, uint8_t **\fIserialized_bytes\fP,"
+.B " PCRE2_SIZE *\fIserialized_size\fP, pcre2_general_context *\fIgcontext\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function encodes a list of compiled patterns into a byte stream that can
+be saved on disc or elsewhere. Note that this is not an abstract format like
+Java or .NET. Conversion of the byte stream back into usable compiled patterns
+can only happen on a host that is running the same version of PCRE2, with the
+same code unit width, and the host must also have the same endianness, pointer
+width and PCRE2_SIZE type. The arguments for \fBpcre2_serialize_encode()\fP
+are:
+.sp
+ \fIcodes\fP pointer to a vector containing the list
+ \fInumber_of_codes\fP number of slots in the vector
+ \fIserialized_bytes\fP set to point to the serialized byte stream
+ \fIserialized_size\fP set to the number of bytes in the byte stream
+ \fIgcontext\fP pointer to a general context or NULL
+.sp
+The context argument is used to obtain memory for the byte stream. When the
+serialized data is no longer needed, it must be freed by calling
+\fBpcre2_serialize_free()\fP. The yield of the function is the number of
+serialized patterns, or one of the following negative error codes:
+.sp
+ PCRE2_ERROR_BADDATA \fInumber_of_codes\fP is zero or less
+ PCRE2_ERROR_BADMAGIC mismatch of id bytes in one of the patterns
+ PCRE2_ERROR_MEMORY memory allocation failed
+ PCRE2_ERROR_MIXEDTABLES the patterns do not all use the same tables
+ PCRE2_ERROR_NULL an argument other than \fIgcontext\fP is NULL
+.sp
+PCRE2_ERROR_BADMAGIC means either that a pattern's code has been corrupted, or
+that a slot in the vector does not point to a compiled pattern.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the serialization functions in the
+.\" HREF
+\fBpcre2serialize\fP
+.\"
+page.
diff --git a/doc/pcre2_serialize_free.3 b/doc/pcre2_serialize_free.3
new file mode 100644
index 0000000..545d865
--- /dev/null
+++ b/doc/pcre2_serialize_free.3
@@ -0,0 +1,29 @@
+.TH PCRE2_SERIALIZE_FREE 3 "13 August 2018" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_serialize_free(uint8_t *\fIbytes\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function frees the memory that was obtained by
+\fBpcre2_serialize_encode()\fP to hold a serialized byte stream. The argument
+must point to such a byte stream or be NULL, in which case the function returns
+without doing anything.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the serialization functions in the
+.\" HREF
+\fBpcre2serialize\fP
+.\"
+page.
diff --git a/doc/pcre2_serialize_get_number_of_codes.3 b/doc/pcre2_serialize_get_number_of_codes.3
new file mode 100644
index 0000000..ea76daa
--- /dev/null
+++ b/doc/pcre2_serialize_get_number_of_codes.3
@@ -0,0 +1,37 @@
+.TH PCRE2_SERIALIZE_GET_NUMBER_OF_CODES 3 "13 August 2018" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int32_t pcre2_serialize_get_number_of_codes(const uint8_t *\fIbytes\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+The \fIbytes\fP argument must point to a serialized byte stream that was
+originally created by \fBpcre2_serialize_encode()\fP (though it may have been
+saved on disc or elsewhere in the meantime). The function returns the number of
+serialized patterns in the byte stream, or one of the following negative error
+codes:
+.sp
+ PCRE2_ERROR_BADMAGIC mismatch of id bytes in \fIbytes\fP
+ PCRE2_ERROR_BADMODE mismatch of variable unit size or PCRE version
+ PCRE2_ERROR_NULL the argument is NULL
+.sp
+PCRE2_ERROR_BADMAGIC may mean that the data is corrupt, or that it was compiled
+on a system with different endianness.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the serialization functions in the
+.\" HREF
+\fBpcre2serialize\fP
+.\"
+page.
diff --git a/doc/pcre2_set_bsr.3 b/doc/pcre2_set_bsr.3
new file mode 100644
index 0000000..1d2b0de
--- /dev/null
+++ b/doc/pcre2_set_bsr.3
@@ -0,0 +1,30 @@
+.TH PCRE2_SET_BSR 3 "25 October 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_bsr(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets the convention for processing \eR within a compile context.
+The second argument must be one of PCRE2_BSR_ANYCRLF or PCRE2_BSR_UNICODE. The
+result is zero for success or PCRE2_ERROR_BADDATA if the second argument is
+invalid.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_callout.3 b/doc/pcre2_set_callout.3
new file mode 100644
index 0000000..7b20d9f
--- /dev/null
+++ b/doc/pcre2_set_callout.3
@@ -0,0 +1,31 @@
+.TH PCRE2_SET_CALLOUT 3 "25 March 2017" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_callout(pcre2_match_context *\fImcontext\fP,
+.B " int (*\fIcallout_function\fP)(pcre2_callout_block *),"
+.B " void *\fIcallout_data\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets the callout fields in a match context (the first argument).
+The second argument specifies a callout function, and the third argument is an
+opaque data item that is passed to it. The result of this function is always
+zero.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_character_tables.3 b/doc/pcre2_set_character_tables.3
new file mode 100644
index 0000000..a57041c
--- /dev/null
+++ b/doc/pcre2_set_character_tables.3
@@ -0,0 +1,35 @@
+.TH PCRE2_SET_CHARACTER_TABLES 3 "15 April 2020" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_character_tables(pcre2_compile_context *\fIccontext\fP,
+.B " const uint8_t *\fItables\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets a pointer to custom character tables within a compile
+context. The second argument must point to a set of PCRE2 character tables or
+be NULL to request the default tables. The result is always zero. Character
+tables can be created by calling \fBpcre2_maketables()\fP or by running the
+\fBpcre2_dftables\fP maintenance command in binary mode (see the
+.\" HREF
+\fBpcre2build\fP
+.\"
+documentation).
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_compile_extra_options.3 b/doc/pcre2_set_compile_extra_options.3
new file mode 100644
index 0000000..d1eb8d3
--- /dev/null
+++ b/doc/pcre2_set_compile_extra_options.3
@@ -0,0 +1,59 @@
+.TH PCRE2_SET_COMPILE_EXTRA_OPTIONS 3 "14 October 2024" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_compile_extra_options(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIextra_options\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets additional option bits for \fBpcre2_compile()\fP that are
+housed in a compile context. It completely replaces all the bits. The extra
+options are:
+.sp
+ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK Allow \eK in lookarounds
+.\" JOIN
+ PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES Allow \ex{d800} to \ex{dfff}
+ in UTF-8 and UTF-32 modes
+.\" JOIN
+ PCRE2_EXTRA_ALT_BSUX Extended alternate \eu, \eU, and
+ \ex handling
+ PCRE2_EXTRA_ASCII_BSD \ed remains ASCII in UCP mode
+ PCRE2_EXTRA_ASCII_BSS \es remains ASCII in UCP mode
+ PCRE2_EXTRA_ASCII_BSW \ew remains ASCII in UCP mode
+.\" JOIN
+ PCRE2_EXTRA_ASCII_DIGIT [:digit:] and [:xdigit:] POSIX classes
+ remain ASCII in UCP mode
+.\" JOIN
+ PCRE2_EXTRA_ASCII_POSIX POSIX classes remain ASCII in
+ UCP mode
+.\" JOIN
+ PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL Treat all invalid escapes as
+ a literal following character
+.\" JOIN
+ PCRE2_EXTRA_CASELESS_RESTRICT Disable mixed ASCII/non-ASCII
+ case folding
+ PCRE2_EXTRA_ESCAPED_CR_IS_LF Interpret \er as \en
+ PCRE2_EXTRA_MATCH_LINE Pattern matches whole lines
+ PCRE2_EXTRA_MATCH_WORD Pattern matches "words"
+ PCRE2_EXTRA_NEVER_CALLOUT Disallow callouts in pattern
+ PCRE2_EXTRA_NO_BS0 Disallow \e0 (but not \e00 or \e000)
+ PCRE2_EXTRA_PYTHON_OCTAL Use Python rules for octal
+ PCRE2_EXTRA_TURKISH_CASING Use Turkish I case folding
+.sp
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_compile_recursion_guard.3 b/doc/pcre2_set_compile_recursion_guard.3
new file mode 100644
index 0000000..a6c80be
--- /dev/null
+++ b/doc/pcre2_set_compile_recursion_guard.3
@@ -0,0 +1,34 @@
+.TH PCRE2_SET_COMPILE_RECURSION_GUARD 3 "26 November 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_compile_recursion_guard(pcre2_compile_context *\fIccontext\fP,
+.B " int (*\fIguard_function\fP)(uint32_t, void *), void *\fIuser_data\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function defines, within a compile context, a function that is called
+whenever \fBpcre2_compile()\fP starts to compile a parenthesized part of a
+pattern. The first argument to the function gives the current depth of
+parenthesis nesting, and the second is user data that is supplied when the
+function is set up. The callout function should return zero if all is well, or
+non-zero to force an error. This feature is provided so that applications can
+check the available system stack space, in order to avoid running out. The
+result of \fBpcre2_set_compile_recursion_guard()\fP is always zero.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_depth_limit.3 b/doc/pcre2_set_depth_limit.3
new file mode 100644
index 0000000..59857b8
--- /dev/null
+++ b/doc/pcre2_set_depth_limit.3
@@ -0,0 +1,28 @@
+.TH PCRE2_SET_DEPTH_LIMIT 3 "25 March 2017" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_depth_limit(pcre2_match_context *\fImcontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets the backtracking depth limit field in a match context. The
+result is always zero.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_glob_escape.3 b/doc/pcre2_set_glob_escape.3
new file mode 100644
index 0000000..73ef5c9
--- /dev/null
+++ b/doc/pcre2_set_glob_escape.3
@@ -0,0 +1,29 @@
+.TH PCRE2_SET_GLOB_ESCAPE 3 "12 July 2017" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_glob_escape(pcre2_convert_context *\fIcvcontext\fP,
+.B " uint32_t \fIescape_char\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function is part of an experimental set of pattern conversion functions.
+It sets the escape character that is used when converting globs. The second
+argument must either be zero (meaning there is no escape character) or a
+punctuation character whose code point is less than 256. The default is grave
+accent if running under Windows, otherwise backslash. The result of the
+function is zero for success or PCRE2_ERROR_BADDATA if the second argument is
+invalid.
+.P
+The pattern conversion functions are described in the
+.\" HREF
+\fBpcre2convert\fP
+.\"
+documentation.
diff --git a/doc/pcre2_set_glob_separator.3 b/doc/pcre2_set_glob_separator.3
new file mode 100644
index 0000000..cba2042
--- /dev/null
+++ b/doc/pcre2_set_glob_separator.3
@@ -0,0 +1,28 @@
+.TH PCRE2_SET_GLOB_SEPARATOR 3 "17 June 2018" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_glob_separator(pcre2_convert_context *\fIcvcontext\fP,
+.B " uint32_t \fIseparator_char\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function is part of an experimental set of pattern conversion functions.
+It sets the component separator character that is used when converting globs.
+The second argument must be one of the characters forward slash, backslash, or
+dot. The default is backslash when running under Windows, otherwise forward
+slash. The result of the function is zero for success or PCRE2_ERROR_BADDATA if
+the second argument is invalid.
+.P
+The pattern conversion functions are described in the
+.\" HREF
+\fBpcre2convert\fP
+.\"
+documentation.
diff --git a/doc/pcre2_set_heap_limit.3 b/doc/pcre2_set_heap_limit.3
new file mode 100644
index 0000000..c5fa2dd
--- /dev/null
+++ b/doc/pcre2_set_heap_limit.3
@@ -0,0 +1,28 @@
+.TH PCRE2_SET_HEAP_LIMIT 3 "17 June 2018" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_heap_limit(pcre2_match_context *\fImcontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets the backtracking heap limit field in a match context. The
+result is always zero.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_match_limit.3 b/doc/pcre2_set_match_limit.3
new file mode 100644
index 0000000..4c1da55
--- /dev/null
+++ b/doc/pcre2_set_match_limit.3
@@ -0,0 +1,28 @@
+.TH PCRE2_SET_MATCH_LIMIT 3 "25 October 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_match_limit(pcre2_match_context *\fImcontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets the match limit field in a match context. The result is
+always zero.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_max_pattern_compiled_length.3 b/doc/pcre2_set_max_pattern_compiled_length.3
new file mode 100644
index 0000000..93c389b
--- /dev/null
+++ b/doc/pcre2_set_max_pattern_compiled_length.3
@@ -0,0 +1,32 @@
+.TH PCRE2_SET_MAX_PATTERN_COMPILED_LENGTH 3 "09 June 2024" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_max_pattern_compiled_length(
+.B " pcre2_compile_context *\fIccontext\fP, PCRE2_SIZE \fIvalue\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets, in a compile context, the maximum size (in bytes) for the
+memory needed to hold the compiled version of a pattern that is using this
+context. The result is always zero. If a pattern that is passed to
+\fBpcre2_compile()\fP referencing this context needs more memory, an error is
+generated. The default is the largest number that a PCRE2_SIZE variable can
+hold, which is effectively unlimited.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_max_pattern_length.3 b/doc/pcre2_set_max_pattern_length.3
new file mode 100644
index 0000000..3946e91
--- /dev/null
+++ b/doc/pcre2_set_max_pattern_length.3
@@ -0,0 +1,31 @@
+.TH PCRE2_SET_MAX_PATTERN_LENGTH 3 "05 October 2016" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_max_pattern_length(pcre2_compile_context *\fIccontext\fP,
+.B " PCRE2_SIZE \fIvalue\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets, in a compile context, the maximum text length (in code
+units) of the pattern that can be compiled. The result is always zero. If a
+longer pattern is passed to \fBpcre2_compile()\fP there is an immediate error
+return. The default is effectively unlimited, being the largest value a
+PCRE2_SIZE variable can hold.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_max_varlookbehind.3 b/doc/pcre2_set_max_varlookbehind.3
new file mode 100644
index 0000000..a3aa86d
--- /dev/null
+++ b/doc/pcre2_set_max_varlookbehind.3
@@ -0,0 +1,30 @@
+.TH PCRE2_SET_NEWLINE 3 "11 August 2023" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_max_varlookbehind(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This sets a maximum length for the number of characters matched by a
+variable-length lookbehind assertion. The default is set when PCRE2 is built,
+with the ultimate default being 255, the same as Perl. Lookbehind assertions
+without a bounding length are not supported. The result is always zero.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_newline.3 b/doc/pcre2_set_newline.3
new file mode 100644
index 0000000..5668767
--- /dev/null
+++ b/doc/pcre2_set_newline.3
@@ -0,0 +1,39 @@
+.TH PCRE2_SET_NEWLINE 3 "19 July 2017" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_newline(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets the newline convention within a compile context. This
+specifies which character(s) are recognized as newlines when compiling and
+matching patterns. The second argument must be one of:
+.sp
+ PCRE2_NEWLINE_CR Carriage return only
+ PCRE2_NEWLINE_LF Linefeed only
+ PCRE2_NEWLINE_CRLF CR followed by LF only
+ PCRE2_NEWLINE_ANYCRLF Any of the above
+ PCRE2_NEWLINE_ANY Any Unicode newline sequence
+ PCRE2_NEWLINE_NUL The NUL character (binary zero)
+.sp
+The result is zero for success or PCRE2_ERROR_BADDATA if the second argument is
+invalid.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_offset_limit.3 b/doc/pcre2_set_offset_limit.3
new file mode 100644
index 0000000..02ebb33
--- /dev/null
+++ b/doc/pcre2_set_offset_limit.3
@@ -0,0 +1,28 @@
+.TH PCRE2_SET_OFFSET_LIMIT 3 "22 September 2015" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_offset_limit(pcre2_match_context *\fImcontext\fP,
+.B " PCRE2_SIZE \fIvalue\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets the offset limit field in a match context. The result is
+always zero.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_optimize.3 b/doc/pcre2_set_optimize.3
new file mode 100644
index 0000000..181f268
--- /dev/null
+++ b/doc/pcre2_set_optimize.3
@@ -0,0 +1,42 @@
+.TH PCRE2_SET_OPTIMIZE 3 "22 September 2024" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_optimize(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIdirective\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function controls which performance optimizations will be applied
+by \fBpcre2_compile()\fP. It can be called multiple times with the same compile
+context; the effects are cumulative, with the effects of later calls taking
+precedence over earlier ones.
+.P
+The result is zero for success, PCRE2_ERROR_NULL if \fIccontext\fP is NULL,
+or PCRE2_ERROR_BADOPTION if \fIdirective\fP is unknown. The latter could be
+useful to detect if a certain optimization is available.
+.P
+The list of possible values for the \fIdirective\fP parameter are:
+.sp
+ PCRE2_OPTIMIZATION_FULL Enable all optimizations (default)
+ PCRE2_OPTIMIZATION_NONE Disable all optimizations
+ PCRE2_AUTO_POSSESS Enable auto-possessification
+ PCRE2_AUTO_POSSESS_OFF Disable auto-possessification
+ PCRE2_DOTSTAR_ANCHOR Enable implicit dotstar anchoring
+ PCRE2_DOTSTAR_ANCHOR_OFF Disable implicit dotstar anchoring
+ PCRE2_START_OPTIMIZE Enable start-up optimizations at match time
+ PCRE2_START_OPTIMIZE_OFF Disable start-up optimizations at match time
+.sp
+There is a complete description of the PCRE2 native API, including detailed
+descriptions \fIdirective\fP parameter values in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page.
diff --git a/doc/pcre2_set_parens_nest_limit.3 b/doc/pcre2_set_parens_nest_limit.3
new file mode 100644
index 0000000..910bd5c
--- /dev/null
+++ b/doc/pcre2_set_parens_nest_limit.3
@@ -0,0 +1,28 @@
+.TH PCRE2_SET_PARENS_NEST_LIMIT 3 "25 October 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_parens_nest_limit(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets, in a compile context, the maximum depth of nested
+parentheses in a pattern. The result is always zero.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_recursion_limit.3 b/doc/pcre2_set_recursion_limit.3
new file mode 100644
index 0000000..8138dd5
--- /dev/null
+++ b/doc/pcre2_set_recursion_limit.3
@@ -0,0 +1,28 @@
+.TH PCRE2_SET_RECURSION_LIMIT 3 "19 July 2017" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_recursion_limit(pcre2_match_context *\fImcontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function is obsolete and should not be used in new code. Use
+\fBpcre2_set_depth_limit()\fP instead.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_recursion_memory_management.3 b/doc/pcre2_set_recursion_memory_management.3
new file mode 100644
index 0000000..a0bb4af
--- /dev/null
+++ b/doc/pcre2_set_recursion_memory_management.3
@@ -0,0 +1,30 @@
+.TH PCRE2_SET_RECURSION_MEMORY_MANAGEMENT 3 "23 January 2023" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_recursion_memory_management(
+.B " pcre2_match_context *\fImcontext\fP,"
+.B " void *(*\fIprivate_malloc\fP)(size_t, void *),"
+.B " void (*\fIprivate_free\fP)(void *, void *), void *\fImemory_data\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+From release 10.30 onwards, this function is obsolete and does nothing. The
+result is always zero.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_substitute_callout.3 b/doc/pcre2_set_substitute_callout.3
new file mode 100644
index 0000000..80917f0
--- /dev/null
+++ b/doc/pcre2_set_substitute_callout.3
@@ -0,0 +1,31 @@
+.TH PCRE2_SET_SUBSTITUTE_CALLOUT 3 "04 October 2024" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_substitute_callout(pcre2_match_context *\fImcontext\fP,
+.B " int (*\fIcallout_function\fP)(pcre2_substitute_callout_block *, void *),"
+.B " void *\fIcallout_data\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets the substitute callout fields in a match context (the first
+argument). The second argument specifies a callout function, and the third
+argument is an opaque data item that is passed to it. The result of this
+function is always zero.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_set_substitute_case_callout.3 b/doc/pcre2_set_substitute_case_callout.3
new file mode 100644
index 0000000..b52fbe8
--- /dev/null
+++ b/doc/pcre2_set_substitute_case_callout.3
@@ -0,0 +1,33 @@
+.TH PCRE2_SET_SUBSTITUTE_CASE_CALLOUT 3 "26 December 2024" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_set_substitute_case_callout(pcre2_match_context *\fImcontext\fP,
+.B " PCRE2_SIZE (*\fIcallout_function\fP)(PCRE2_SPTR, PCRE2_SIZE,"
+.B " PCRE2_UCHAR *, PCRE2_SIZE,"
+.B " int, void *),"
+.B " void *\fIcallout_data\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function sets the substitute case callout fields in a match context (the
+first argument). The second argument specifies a callout function, and the third
+argument is an opaque data item that is passed to it. The result of this
+function is always zero.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_substitute.3 b/doc/pcre2_substitute.3
new file mode 100644
index 0000000..1bc8aa9
--- /dev/null
+++ b/doc/pcre2_substitute.3
@@ -0,0 +1,111 @@
+.TH PCRE2_SUBSTITUTE 3 "03 October 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_substitute(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
+.B " PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
+.B " uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
+.B " pcre2_match_context *\fImcontext\fP, PCRE2_SPTR \fIreplacement\fP,"
+.B " PCRE2_SIZE \fIrlength\fP, PCRE2_UCHAR *\fIoutputbuffer\fP,"
+.B " PCRE2_SIZE *\fIoutlengthptr\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function matches a compiled regular expression against a given subject
+string, using a matching algorithm that is similar to Perl's. It then makes a
+copy of the subject, substituting a replacement string for what was matched.
+Its arguments are:
+.sp
+ \fIcode\fP Points to the compiled pattern
+ \fIsubject\fP Points to the subject string
+ \fIlength\fP Length of the subject string
+ \fIstartoffset\fP Offset in the subject at which to start matching
+ \fIoptions\fP Option bits
+ \fImatch_data\fP Points to a match data block, or is NULL
+ \fImcontext\fP Points to a match context, or is NULL
+ \fIreplacement\fP Points to the replacement string
+ \fIrlength\fP Length of the replacement string
+ \fIoutputbuffer\fP Points to the output buffer
+ \fIoutlengthptr\fP Points to the length of the output buffer
+.sp
+A match data block is needed only if you want to inspect the data from the
+final match that is returned in that block or if PCRE2_SUBSTITUTE_MATCHED is
+set. A match context is needed only if you want to:
+.sp
+ Set up a callout function
+ Set a matching offset limit
+ Change the backtracking match limit
+ Change the backtracking depth limit
+ Set custom memory management in the match context
+.sp
+The \fIlength\fP, \fIstartoffset\fP and \fIrlength\fP values are code units,
+not characters, as is the contents of the variable pointed at by
+\fIoutlengthptr\fP. This variable must contain the length of the output buffer
+when the function is called. If the function is successful, the value is
+changed to the length of the new string, excluding the trailing zero that is
+automatically added.
+.P
+The subject and replacement lengths can be given as PCRE2_ZERO_TERMINATED for
+zero-terminated strings. The options are:
+.sp
+ PCRE2_ANCHORED Match only at the first position
+ PCRE2_ENDANCHORED Match only at end of subject
+.\" JOIN
+ PCRE2_NOTBOL Subject is not the beginning of a
+ line
+ PCRE2_NOTEOL Subject is not the end of a line
+.\" JOIN
+ PCRE2_NOTEMPTY An empty string is not a
+ valid match
+.\" JOIN
+ PCRE2_NOTEMPTY_ATSTART An empty string at the start of
+ the subject is not a valid match
+ PCRE2_NO_JIT Do not use JIT matching
+.\" JOIN
+ PCRE2_NO_UTF_CHECK Do not check for UTF validity in
+ the subject or replacement
+.\" JOIN
+ (only relevant if PCRE2_UTF was
+ set at compile time)
+ PCRE2_SUBSTITUTE_EXTENDED Do extended replacement processing
+.\" JOIN
+ PCRE2_SUBSTITUTE_GLOBAL Replace all occurrences in the
+ subject
+ PCRE2_SUBSTITUTE_LITERAL The replacement string is literal
+.\" JOIN
+ PCRE2_SUBSTITUTE_MATCHED Use pre-existing match data for
+ first match
+ PCRE2_SUBSTITUTE_OVERFLOW_LENGTH If overflow, compute needed length
+ PCRE2_SUBSTITUTE_REPLACEMENT_ONLY Return only replacement string(s)
+ PCRE2_SUBSTITUTE_UNKNOWN_UNSET Treat unknown group as unset
+ PCRE2_SUBSTITUTE_UNSET_EMPTY Simple unset insert = empty string
+.sp
+If PCRE2_SUBSTITUTE_LITERAL is set, PCRE2_SUBSTITUTE_EXTENDED,
+PCRE2_SUBSTITUTE_UNKNOWN_UNSET, and PCRE2_SUBSTITUTE_UNSET_EMPTY are ignored.
+.P
+If PCRE2_SUBSTITUTE_MATCHED is set, \fImatch_data\fP must be non-NULL; its
+contents must be the result of a call to \fBpcre2_match()\fP (or
+\fBpcre2_jit_match()\fP) using the same pattern, subject pointer, effective
+subject length, start offset, and match options.
+.P
+The function returns the number of substitutions, which may be zero if there
+are no matches. The result may be greater than one only when
+PCRE2_SUBSTITUTE_GLOBAL is set. In the event of an error, a negative error code
+is returned.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_substring_copy_byname.3 b/doc/pcre2_substring_copy_byname.3
new file mode 100644
index 0000000..1fade54
--- /dev/null
+++ b/doc/pcre2_substring_copy_byname.3
@@ -0,0 +1,46 @@
+.TH PCRE2_SUBSTRING_COPY_BYNAME 3 "19 December 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_substring_copy_byname(pcre2_match_data *\fImatch_data\fP,
+.B " PCRE2_SPTR \fIname\fP, PCRE2_UCHAR *\fIbuffer\fP, PCRE2_SIZE *\fIbufflen\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This is a convenience function for extracting a captured substring, identified
+by name, into a given buffer. The arguments are:
+.sp
+ \fImatch_data\fP The match data block for the match
+ \fIname\fP Name of the required substring
+ \fIbuffer\fP Buffer to receive the string
+ \fIbufflen\fP Length of buffer (code units)
+.sp
+The \fIbufflen\fP variable is updated to contain the length of the extracted
+string, excluding the trailing zero. The yield of the function is zero for
+success or one of the following error numbers:
+.sp
+ PCRE2_ERROR_NOSUBSTRING there are no groups of that name
+ PCRE2_ERROR_UNAVAILBLE the ovector was too small for that group
+ PCRE2_ERROR_UNSET the group did not participate in the match
+ PCRE2_ERROR_NOMEMORY the buffer is not big enough
+.sp
+If there is more than one group with the given name, the first one that is set
+is returned. In this situation PCRE2_ERROR_UNSET means that no group with the
+given name was set.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_substring_copy_bynumber.3 b/doc/pcre2_substring_copy_bynumber.3
new file mode 100644
index 0000000..11f3777
--- /dev/null
+++ b/doc/pcre2_substring_copy_bynumber.3
@@ -0,0 +1,44 @@
+.TH PCRE2_SUBSTRING_COPY_BYNUMBER 3 "13 December 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_substring_copy_bynumber(pcre2_match_data *\fImatch_data\fP,
+.B " uint32_t \fInumber\fP, PCRE2_UCHAR *\fIbuffer\fP,"
+.B " PCRE2_SIZE *\fIbufflen\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This is a convenience function for extracting a captured substring into a given
+buffer. The arguments are:
+.sp
+ \fImatch_data\fP The match data block for the match
+ \fInumber\fP Number of the required substring
+ \fIbuffer\fP Buffer to receive the string
+ \fIbufflen\fP Length of buffer
+.sp
+The \fIbufflen\fP variable is updated with the length of the extracted string,
+excluding the terminating zero. The yield of the function is zero for success
+or one of the following error numbers:
+.sp
+ PCRE2_ERROR_NOSUBSTRING there are no groups of that number
+ PCRE2_ERROR_UNAVAILBLE the ovector was too small for that group
+ PCRE2_ERROR_UNSET the group did not participate in the match
+ PCRE2_ERROR_NOMEMORY the buffer is too small
+.sp
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_substring_free.3 b/doc/pcre2_substring_free.3
new file mode 100644
index 0000000..58ae037
--- /dev/null
+++ b/doc/pcre2_substring_free.3
@@ -0,0 +1,29 @@
+.TH PCRE2_SUBSTRING_FREE 3 "26 February 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_substring_free(PCRE2_UCHAR *\fIbuffer\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This is a convenience function for freeing the memory obtained by a previous
+call to \fBpcre2_substring_get_byname()\fP or
+\fBpcre2_substring_get_bynumber()\fP. Its only argument is a pointer to the
+string. If the argument is NULL, the function does nothing.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_substring_get_byname.3 b/doc/pcre2_substring_get_byname.3
new file mode 100644
index 0000000..a841403
--- /dev/null
+++ b/doc/pcre2_substring_get_byname.3
@@ -0,0 +1,48 @@
+.TH PCRE2_SUBSTRING_GET_BYNAME 3 "19 December 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_substring_get_byname(pcre2_match_data *\fImatch_data\fP,
+.B " PCRE2_SPTR \fIname\fP, PCRE2_UCHAR **\fIbufferptr\fP, PCRE2_SIZE *\fIbufflen\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This is a convenience function for extracting a captured substring by name into
+newly acquired memory. The arguments are:
+.sp
+ \fImatch_data\fP The match data for the match
+ \fIname\fP Name of the required substring
+ \fIbufferptr\fP Where to put the string pointer
+ \fIbufflen\fP Where to put the string length
+.sp
+The memory in which the substring is placed is obtained by calling the same
+memory allocation function that was used for the match data block. The
+convenience function \fBpcre2_substring_free()\fP can be used to free it when
+it is no longer needed. The yield of the function is zero for success or one of
+the following error numbers:
+.sp
+ PCRE2_ERROR_NOSUBSTRING there are no groups of that name
+ PCRE2_ERROR_UNAVAILBLE the ovector was too small for that group
+ PCRE2_ERROR_UNSET the group did not participate in the match
+ PCRE2_ERROR_NOMEMORY memory could not be obtained
+.sp
+If there is more than one group with the given name, the first one that is set
+is returned. In this situation PCRE2_ERROR_UNSET means that no group with the
+given name was set.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_substring_get_bynumber.3 b/doc/pcre2_substring_get_bynumber.3
new file mode 100644
index 0000000..1efe1e2
--- /dev/null
+++ b/doc/pcre2_substring_get_bynumber.3
@@ -0,0 +1,45 @@
+.TH PCRE2_SUBSTRING_GET_BYNUMBER 3 "13 December 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_substring_get_bynumber(pcre2_match_data *\fImatch_data\fP,
+.B " uint32_t \fInumber\fP, PCRE2_UCHAR **\fIbufferptr\fP, PCRE2_SIZE *\fIbufflen\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This is a convenience function for extracting a captured substring by number
+into newly acquired memory. The arguments are:
+.sp
+ \fImatch_data\fP The match data for the match
+ \fInumber\fP Number of the required substring
+ \fIbufferptr\fP Where to put the string pointer
+ \fIbufflen\fP Where to put the string length
+.sp
+The memory in which the substring is placed is obtained by calling the same
+memory allocation function that was used for the match data block. The
+convenience function \fBpcre2_substring_free()\fP can be used to free it when
+it is no longer needed. The yield of the function is zero for success or one of
+the following error numbers:
+.sp
+ PCRE2_ERROR_NOSUBSTRING there are no groups of that number
+ PCRE2_ERROR_UNAVAILBLE the ovector was too small for that group
+ PCRE2_ERROR_UNSET the group did not participate in the match
+ PCRE2_ERROR_NOMEMORY memory could not be obtained
+.sp
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_substring_length_byname.3 b/doc/pcre2_substring_length_byname.3
new file mode 100644
index 0000000..1c3815f
--- /dev/null
+++ b/doc/pcre2_substring_length_byname.3
@@ -0,0 +1,36 @@
+.TH PCRE2_SUBSTRING_LENGTH_BYNAME 3 "26 September 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_substring_length_byname(pcre2_match_data *\fImatch_data\fP,
+.B " PCRE2_SPTR \fIname\fP, PCRE2_SIZE *\fIlength\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function returns the length of a matched substring, identified by name.
+The arguments are:
+.sp
+ \fImatch_data\fP The match data block for the match
+ \fIname\fP The substring name
+ \fIlength\fP Where to return the length, or NULL
+.sp
+The third argument may be NULL if all you want to know is whether or not a
+substring is set. The yield is zero on success, or a negative error code
+otherwise.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_substring_length_bynumber.3 b/doc/pcre2_substring_length_bynumber.3
new file mode 100644
index 0000000..0c81f55
--- /dev/null
+++ b/doc/pcre2_substring_length_bynumber.3
@@ -0,0 +1,36 @@
+.TH PCRE2_SUBSTRING_LENGTH_BYNUMBER 3 "22 December 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_substring_length_bynumber(pcre2_match_data *\fImatch_data\fP,
+.B " uint32_t \fInumber\fP, PCRE2_SIZE *\fIlength\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This function returns the length of a matched substring, identified by number.
+The arguments are:
+.sp
+ \fImatch_data\fP The match data block for the match
+ \fInumber\fP The substring number
+ \fIlength\fP Where to return the length, or NULL
+.sp
+The third argument may be NULL if all you want to know is whether or not a
+substring is set. The yield is zero on success, or a negative error code
+otherwise. After a partial match, only substring 0 is available.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_substring_list_free.3 b/doc/pcre2_substring_list_free.3
new file mode 100644
index 0000000..a17712e
--- /dev/null
+++ b/doc/pcre2_substring_list_free.3
@@ -0,0 +1,29 @@
+.TH PCRE2_SUBSTRING_LIST_FREE 3 "26 February 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B void pcre2_substring_list_free(PCRE2_UCHAR **\fIlist\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This is a convenience function for freeing the store obtained by a previous
+call to \fBpcre2substring_list_get()\fP. Its only argument is a pointer to
+the list of string pointers. If the argument is NULL, the function returns
+immediately, without doing anything.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_substring_list_get.3 b/doc/pcre2_substring_list_get.3
new file mode 100644
index 0000000..b7868d0
--- /dev/null
+++ b/doc/pcre2_substring_list_get.3
@@ -0,0 +1,44 @@
+.TH PCRE2_SUBSTRING_LIST_GET 3 "21 October 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_substring_list_get(pcre2_match_data *\fImatch_data\fP,
+.B " PCRE2_UCHAR ***\fIlistptr\fP, PCRE2_SIZE **\fIlengthsptr\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This is a convenience function for extracting all the captured substrings after
+a pattern match. It builds a list of pointers to the strings, and (optionally)
+a second list that contains their lengths (in code units), excluding a
+terminating zero that is added to each of them. All this is done in a single
+block of memory that is obtained using the same memory allocation function that
+was used to get the match data block. The convenience function
+\fBpcre2_substring_list_free()\fP can be used to free it when it is no longer
+needed. The arguments are:
+.sp
+ \fImatch_data\fP The match data block
+ \fIlistptr\fP Where to put a pointer to the list
+ \fIlengthsptr\fP Where to put a pointer to the lengths, or NULL
+.sp
+A pointer to a list of pointers is put in the variable whose address is in
+\fIlistptr\fP. The list is terminated by a NULL pointer. If \fIlengthsptr\fP is
+not NULL, a matching list of lengths is created, and its address is placed in
+\fIlengthsptr\fP. The yield of the function is zero on success or
+PCRE2_ERROR_NOMEMORY if sufficient memory could not be obtained.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_substring_nametable_scan.3 b/doc/pcre2_substring_nametable_scan.3
new file mode 100644
index 0000000..849d827
--- /dev/null
+++ b/doc/pcre2_substring_nametable_scan.3
@@ -0,0 +1,41 @@
+.TH PCRE2_SUBSTRING_NAMETABLE_SCAN 3 "06 February 2019" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_substring_nametable_scan(const pcre2_code *\fIcode\fP,
+.B " PCRE2_SPTR \fIname\fP, PCRE2_SPTR *\fIfirst\fP, PCRE2_SPTR *\fIlast\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This convenience function finds, for a compiled pattern, the first and last
+entries for a given name in the table that translates capture group names into
+numbers.
+.sp
+ \fIcode\fP Compiled regular expression
+ \fIname\fP Name whose entries required
+ \fIfirst\fP Where to return a pointer to the first entry
+ \fIlast\fP Where to return a pointer to the last entry
+.sp
+When the name is found in the table, if \fIfirst\fP is NULL, the function
+returns a group number, but if there is more than one matching entry, it is not
+defined which one. Otherwise, when both pointers have been set, the yield of
+the function is the length of each entry in code units. If the name is not
+found, PCRE2_ERROR_NOSUBSTRING is returned.
+.P
+There is a complete description of the PCRE2 native API, including the format of
+the table entries, in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page, and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2_substring_number_from_name.3 b/doc/pcre2_substring_number_from_name.3
new file mode 100644
index 0000000..bbd1400
--- /dev/null
+++ b/doc/pcre2_substring_number_from_name.3
@@ -0,0 +1,38 @@
+.TH PCRE2_SUBSTRING_NUMBER_FROM_NAME 3 "03 November 2014" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_substring_number_from_name(const pcre2_code *\fIcode\fP,
+.B " PCRE2_SPTR \fIname\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This convenience function finds the number of a named substring capturing
+parenthesis in a compiled pattern, provided that it is a unique name. The
+function arguments are:
+.sp
+ \fIcode\fP Compiled regular expression
+ \fIname\fP Name whose number is required
+.sp
+The yield of the function is the number of the parenthesis if the name is
+found, or PCRE2_ERROR_NOSUBSTRING if it is not found. When duplicate names are
+allowed (PCRE2_DUPNAMES is set), if the name is not unique,
+PCRE2_ERROR_NOUNIQUESUBSTRING is returned. You can obtain the list of numbers
+with the same name by calling \fBpcre2_substring_nametable_scan()\fP.
+.P
+There is a complete description of the PCRE2 native API in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page and a description of the POSIX API in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+page.
diff --git a/doc/pcre2api.3 b/doc/pcre2api.3
new file mode 100644
index 0000000..8d49818
--- /dev/null
+++ b/doc/pcre2api.3
@@ -0,0 +1,4627 @@
+.TH PCRE2API 3 "08 December 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.sp
+.B #include
+.sp
+PCRE2 is a new API for PCRE, starting at release 10.0. This document contains a
+description of all its native functions. See the
+.\" HREF
+\fBpcre2\fP
+.\"
+document for an overview of all the PCRE2 documentation.
+.
+.
+.SH "PCRE2 NATIVE API BASIC FUNCTIONS"
+.rs
+.sp
+.nf
+.B pcre2_code *pcre2_compile(PCRE2_SPTR \fIpattern\fP, PCRE2_SIZE \fIlength\fP,
+.B " uint32_t \fIoptions\fP, int *\fIerrorcode\fP, PCRE2_SIZE *\fIerroroffset,\fP"
+.B " pcre2_compile_context *\fIccontext\fP);"
+.sp
+.B void pcre2_code_free(pcre2_code *\fIcode\fP);
+.sp
+.B pcre2_match_data *pcre2_match_data_create(uint32_t \fIovecsize\fP,
+.B " pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B pcre2_match_data *pcre2_match_data_create_from_pattern(
+.B " const pcre2_code *\fIcode\fP, pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B int pcre2_match(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
+.B " PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
+.B " uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
+.B " pcre2_match_context *\fImcontext\fP);"
+.sp
+.B int pcre2_dfa_match(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
+.B " PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
+.B " uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
+.B " pcre2_match_context *\fImcontext\fP,"
+.B " int *\fIworkspace\fP, PCRE2_SIZE \fIwscount\fP);"
+.sp
+.B void pcre2_match_data_free(pcre2_match_data *\fImatch_data\fP);
+.fi
+.
+.
+.SH "PCRE2 NATIVE API AUXILIARY MATCH FUNCTIONS"
+.rs
+.sp
+.nf
+.B PCRE2_SPTR pcre2_get_mark(pcre2_match_data *\fImatch_data\fP);
+.sp
+.B PCRE2_SIZE pcre2_get_match_data_size(pcre2_match_data *\fImatch_data\fP);
+.sp
+.B PCRE2_SIZE pcre2_get_match_data_heapframes_size(
+.B " pcre2_match_data *\fImatch_data\fP);"
+.sp
+.B uint32_t pcre2_get_ovector_count(pcre2_match_data *\fImatch_data\fP);
+.sp
+.B PCRE2_SIZE *pcre2_get_ovector_pointer(pcre2_match_data *\fImatch_data\fP);
+.sp
+.B PCRE2_SIZE pcre2_get_startchar(pcre2_match_data *\fImatch_data\fP);
+.fi
+.
+.
+.SH "PCRE2 NATIVE API GENERAL CONTEXT FUNCTIONS"
+.rs
+.sp
+.nf
+.B pcre2_general_context *pcre2_general_context_create(
+.B " void *(*\fIprivate_malloc\fP)(PCRE2_SIZE, void *),"
+.B " void (*\fIprivate_free\fP)(void *, void *), void *\fImemory_data\fP);"
+.sp
+.B pcre2_general_context *pcre2_general_context_copy(
+.B " pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B void pcre2_general_context_free(pcre2_general_context *\fIgcontext\fP);
+.fi
+.
+.
+.SH "PCRE2 NATIVE API COMPILE CONTEXT FUNCTIONS"
+.rs
+.sp
+.nf
+.B pcre2_compile_context *pcre2_compile_context_create(
+.B " pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B pcre2_compile_context *pcre2_compile_context_copy(
+.B " pcre2_compile_context *\fIccontext\fP);"
+.sp
+.B void pcre2_compile_context_free(pcre2_compile_context *\fIccontext\fP);
+.sp
+.B int pcre2_set_bsr(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.sp
+.B int pcre2_set_character_tables(pcre2_compile_context *\fIccontext\fP,
+.B " const uint8_t *\fItables\fP);"
+.sp
+.B int pcre2_set_compile_extra_options(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIextra_options\fP);"
+.sp
+.B int pcre2_set_max_pattern_length(pcre2_compile_context *\fIccontext\fP,
+.B " PCRE2_SIZE \fIvalue\fP);"
+.sp
+.B int pcre2_set_max_pattern_compiled_length(
+.B " pcre2_compile_context *\fIccontext\fP, PCRE2_SIZE \fIvalue\fP);"
+.sp
+.B int pcre2_set_max_varlookbehind(pcre2_compile_contest *\fIccontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.sp
+.B int pcre2_set_newline(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.sp
+.B int pcre2_set_parens_nest_limit(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.sp
+.B int pcre2_set_compile_recursion_guard(pcre2_compile_context *\fIccontext\fP,
+.B " int (*\fIguard_function\fP)(uint32_t, void *), void *\fIuser_data\fP);"
+.sp
+.B int pcre2_set_optimize(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIdirective\fP);"
+.fi
+.
+.
+.SH "PCRE2 NATIVE API MATCH CONTEXT FUNCTIONS"
+.rs
+.sp
+.nf
+.B pcre2_match_context *pcre2_match_context_create(
+.B " pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B pcre2_match_context *pcre2_match_context_copy(
+.B " pcre2_match_context *\fImcontext\fP);"
+.sp
+.B void pcre2_match_context_free(pcre2_match_context *\fImcontext\fP);
+.sp
+.B int pcre2_set_callout(pcre2_match_context *\fImcontext\fP,
+.B " int (*\fIcallout_function\fP)(pcre2_callout_block *, void *),"
+.B " void *\fIcallout_data\fP);"
+.sp
+.B int pcre2_set_substitute_callout(pcre2_match_context *\fImcontext\fP,
+.B " int (*\fIcallout_function\fP)(pcre2_substitute_callout_block *, void *),"
+.B " void *\fIcallout_data\fP);"
+.sp
+.B int pcre2_set_substitute_case_callout(pcre2_match_context *\fImcontext\fP,
+.B " PCRE2_SIZE (*\fIcallout_function\fP)(PCRE2_SPTR, PCRE2_SIZE,"
+.B " PCRE2_UCHAR *, PCRE2_SIZE,"
+.B " int, void *),"
+.B " void *\fIcallout_data\fP);"
+.sp
+.B int pcre2_set_offset_limit(pcre2_match_context *\fImcontext\fP,
+.B " PCRE2_SIZE \fIvalue\fP);"
+.sp
+.B int pcre2_set_heap_limit(pcre2_match_context *\fImcontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.sp
+.B int pcre2_set_match_limit(pcre2_match_context *\fImcontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.sp
+.B int pcre2_set_depth_limit(pcre2_match_context *\fImcontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.
+.
+.SH "PCRE2 NATIVE API STRING EXTRACTION FUNCTIONS"
+.rs
+.sp
+.nf
+.B int pcre2_substring_copy_byname(pcre2_match_data *\fImatch_data\fP,
+.B " PCRE2_SPTR \fIname\fP, PCRE2_UCHAR *\fIbuffer\fP, PCRE2_SIZE *\fIbufflen\fP);"
+.sp
+.B int pcre2_substring_copy_bynumber(pcre2_match_data *\fImatch_data\fP,
+.B " uint32_t \fInumber\fP, PCRE2_UCHAR *\fIbuffer\fP,"
+.B " PCRE2_SIZE *\fIbufflen\fP);"
+.sp
+.B void pcre2_substring_free(PCRE2_UCHAR *\fIbuffer\fP);
+.sp
+.B int pcre2_substring_get_byname(pcre2_match_data *\fImatch_data\fP,
+.B " PCRE2_SPTR \fIname\fP, PCRE2_UCHAR **\fIbufferptr\fP, PCRE2_SIZE *\fIbufflen\fP);"
+.sp
+.B int pcre2_substring_get_bynumber(pcre2_match_data *\fImatch_data\fP,
+.B " uint32_t \fInumber\fP, PCRE2_UCHAR **\fIbufferptr\fP,"
+.B " PCRE2_SIZE *\fIbufflen\fP);"
+.sp
+.B int pcre2_substring_length_byname(pcre2_match_data *\fImatch_data\fP,
+.B " PCRE2_SPTR \fIname\fP, PCRE2_SIZE *\fIlength\fP);"
+.sp
+.B int pcre2_substring_length_bynumber(pcre2_match_data *\fImatch_data\fP,
+.B " uint32_t \fInumber\fP, PCRE2_SIZE *\fIlength\fP);"
+.sp
+.B int pcre2_substring_nametable_scan(const pcre2_code *\fIcode\fP,
+.B " PCRE2_SPTR \fIname\fP, PCRE2_SPTR *\fIfirst\fP, PCRE2_SPTR *\fIlast\fP);"
+.sp
+.B int pcre2_substring_number_from_name(const pcre2_code *\fIcode\fP,
+.B " PCRE2_SPTR \fIname\fP);"
+.sp
+.B void pcre2_substring_list_free(PCRE2_UCHAR **\fIlist\fP);
+.sp
+.B int pcre2_substring_list_get(pcre2_match_data *\fImatch_data\fP,
+.B " PCRE2_UCHAR ***\fIlistptr\fP, PCRE2_SIZE **\fIlengthsptr\fP);"
+.fi
+.
+.
+.SH "PCRE2 NATIVE API STRING SUBSTITUTION FUNCTION"
+.rs
+.sp
+.nf
+.B int pcre2_substitute(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
+.B " PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
+.B " uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
+.B " pcre2_match_context *\fImcontext\fP, PCRE2_SPTR \fIreplacement\fP,"
+.B " PCRE2_SIZE \fIrlength\fP, PCRE2_UCHAR *\fIoutputbuffer\fP,"
+.B " PCRE2_SIZE *\fIoutlengthptr\fP);"
+.fi
+.
+.
+.SH "PCRE2 NATIVE API JIT FUNCTIONS"
+.rs
+.sp
+.nf
+.B int pcre2_jit_compile(pcre2_code *\fIcode\fP, uint32_t \fIoptions\fP);
+.sp
+.B int pcre2_jit_match(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
+.B " PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
+.B " uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
+.B " pcre2_match_context *\fImcontext\fP);"
+.sp
+.B void pcre2_jit_free_unused_memory(pcre2_general_context *\fIgcontext\fP);
+.sp
+.B pcre2_jit_stack *pcre2_jit_stack_create(size_t \fIstartsize\fP,
+.B " size_t \fImaxsize\fP, pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B void pcre2_jit_stack_assign(pcre2_match_context *\fImcontext\fP,
+.B " pcre2_jit_callback \fIcallback_function\fP, void *\fIcallback_data\fP);"
+.sp
+.B void pcre2_jit_stack_free(pcre2_jit_stack *\fIjit_stack\fP);
+.fi
+.
+.
+.SH "PCRE2 NATIVE API SERIALIZATION FUNCTIONS"
+.rs
+.sp
+.nf
+.B int32_t pcre2_serialize_decode(pcre2_code **\fIcodes\fP,
+.B " int32_t \fInumber_of_codes\fP, const uint8_t *\fIbytes\fP,"
+.B " pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B int32_t pcre2_serialize_encode(const pcre2_code **\fIcodes\fP,
+.B " int32_t \fInumber_of_codes\fP, uint8_t **\fIserialized_bytes\fP,"
+.B " PCRE2_SIZE *\fIserialized_size\fP, pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B void pcre2_serialize_free(uint8_t *\fIbytes\fP);
+.sp
+.B int32_t pcre2_serialize_get_number_of_codes(const uint8_t *\fIbytes\fP);
+.fi
+.
+.
+.SH "PCRE2 NATIVE API AUXILIARY FUNCTIONS"
+.rs
+.sp
+.nf
+.B pcre2_code *pcre2_code_copy(const pcre2_code *\fIcode\fP);
+.sp
+.B pcre2_code *pcre2_code_copy_with_tables(const pcre2_code *\fIcode\fP);
+.sp
+.B int pcre2_get_error_message(int \fIerrorcode\fP, PCRE2_UCHAR *\fIbuffer\fP,
+.B " PCRE2_SIZE \fIbufflen\fP);"
+.sp
+.B const uint8_t *pcre2_maketables(pcre2_general_context *\fIgcontext\fP);
+.sp
+.B void pcre2_maketables_free(pcre2_general_context *\fIgcontext\fP,
+.B " const uint8_t *\fItables\fP);"
+.sp
+.B int pcre2_pattern_info(const pcre2_code *\fIcode\fP, uint32_t \fIwhat\fP,
+.B " void *\fIwhere\fP);"
+.sp
+.B int pcre2_callout_enumerate(const pcre2_code *\fIcode\fP,
+.B " int (*\fIcallback\fP)(pcre2_callout_enumerate_block *, void *),"
+.B " void *\fIuser_data\fP);"
+.sp
+.B int pcre2_config(uint32_t \fIwhat\fP, void *\fIwhere\fP);
+.fi
+.
+.
+.SH "PCRE2 NATIVE API OBSOLETE FUNCTIONS"
+.rs
+.sp
+.nf
+.B int pcre2_set_recursion_limit(pcre2_match_context *\fImcontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.sp
+.B int pcre2_set_recursion_memory_management(
+.B " pcre2_match_context *\fImcontext\fP,"
+.B " void *(*\fIprivate_malloc\fP)(size_t, void *),"
+.B " void (*\fIprivate_free\fP)(void *, void *), void *\fImemory_data\fP);"
+.fi
+.sp
+These functions became obsolete at release 10.30 and are retained only for
+backward compatibility. They should not be used in new code. The first is
+replaced by \fBpcre2_set_depth_limit()\fP; the second is no longer needed and
+has no effect (it always returns zero).
+.
+.
+.SH "PCRE2 EXPERIMENTAL PATTERN CONVERSION FUNCTIONS"
+.rs
+.sp
+.nf
+.B pcre2_convert_context *pcre2_convert_context_create(
+.B " pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B pcre2_convert_context *pcre2_convert_context_copy(
+.B " pcre2_convert_context *\fIcvcontext\fP);"
+.sp
+.B void pcre2_convert_context_free(pcre2_convert_context *\fIcvcontext\fP);
+.sp
+.B int pcre2_set_glob_escape(pcre2_convert_context *\fIcvcontext\fP,
+.B " uint32_t \fIescape_char\fP);"
+.sp
+.B int pcre2_set_glob_separator(pcre2_convert_context *\fIcvcontext\fP,
+.B " uint32_t \fIseparator_char\fP);"
+.sp
+.B int pcre2_pattern_convert(PCRE2_SPTR \fIpattern\fP, PCRE2_SIZE \fIlength\fP,
+.B " uint32_t \fIoptions\fP, PCRE2_UCHAR **\fIbuffer\fP,"
+.B " PCRE2_SIZE *\fIblength\fP, pcre2_convert_context *\fIcvcontext\fP);"
+.sp
+.B void pcre2_converted_pattern_free(PCRE2_UCHAR *\fIconverted_pattern\fP);
+.fi
+.sp
+These functions provide a way of converting non-PCRE2 patterns into
+patterns that can be processed by \fBpcre2_compile()\fP. This facility is
+experimental and may be changed in future releases. At present, "globs" and
+POSIX basic and extended patterns can be converted. Details are given in the
+.\" HREF
+\fBpcre2convert\fP
+.\"
+documentation.
+.
+.
+.SH "PCRE2 8-BIT, 16-BIT, AND 32-BIT LIBRARIES"
+.rs
+.sp
+There are three PCRE2 libraries, supporting 8-bit, 16-bit, and 32-bit code
+units, respectively. However, there is just one header file, \fBpcre2.h\fP.
+This contains the function prototypes and other definitions for all three
+libraries. One, two, or all three can be installed simultaneously. On Unix-like
+systems the libraries are called \fBlibpcre2-8\fP, \fBlibpcre2-16\fP, and
+\fBlibpcre2-32\fP, and they can also co-exist with the original PCRE libraries.
+Every PCRE2 function comes in three different forms, one for each library, for
+example:
+.sp
+ \fBpcre2_compile_8()\fP
+ \fBpcre2_compile_16()\fP
+ \fBpcre2_compile_32()\fP
+.sp
+There are also three different sets of data types:
+.sp
+ \fBPCRE2_UCHAR8, PCRE2_UCHAR16, PCRE2_UCHAR32\fP
+ \fBPCRE2_SPTR8, PCRE2_SPTR16, PCRE2_SPTR32\fP
+.sp
+The UCHAR types define unsigned code units of the appropriate widths.
+For example, PCRE2_UCHAR16 is usually defined as `uint16_t'.
+The SPTR types are pointers to constants of the equivalent UCHAR types,
+that is, they are pointers to vectors of unsigned code units.
+.P
+Character strings are passed to a PCRE2 library as sequences of unsigned
+integers in code units of the appropriate width. The length of a string may
+be given as a number of code units, or the string may be specified as
+zero-terminated.
+.P
+Many applications use only one code unit width. For their convenience, macros
+are defined whose names are the generic forms such as \fBpcre2_compile()\fP and
+PCRE2_SPTR. These macros use the value of the macro PCRE2_CODE_UNIT_WIDTH to
+generate the appropriate width-specific function and macro names.
+PCRE2_CODE_UNIT_WIDTH is not defined by default. An application must define it
+to be 8, 16, or 32 before including \fBpcre2.h\fP in order to make use of the
+generic names.
+.P
+Applications that use more than one code unit width can be linked with more
+than one PCRE2 library, but must define PCRE2_CODE_UNIT_WIDTH to be 0 before
+including \fBpcre2.h\fP, and then use the real function names. Any code that is
+to be included in an environment where the value of PCRE2_CODE_UNIT_WIDTH is
+unknown should also use the real function names. (Unfortunately, it is not
+possible in C code to save and restore the value of a macro.)
+.P
+If PCRE2_CODE_UNIT_WIDTH is not defined before including \fBpcre2.h\fP, a
+compiler error occurs.
+.P
+When using multiple libraries in an application, you must take care when
+processing any particular pattern to use only functions from a single library.
+For example, if you want to run a match using a pattern that was compiled with
+\fBpcre2_compile_16()\fP, you must do so with \fBpcre2_match_16()\fP, not
+\fBpcre2_match_8()\fP or \fBpcre2_match_32()\fP.
+.P
+In the function summaries above, and in the rest of this document and other
+PCRE2 documents, functions and data types are described using their generic
+names, without the _8, _16, or _32 suffix.
+.
+.
+.SH "PCRE2 API OVERVIEW"
+.rs
+.sp
+PCRE2 has its own native API, which is described in this document. There are
+also some wrapper functions for the 8-bit library that correspond to the
+POSIX regular expression API, but they do not give access to all the
+functionality of PCRE2 and they are not thread-safe. They are described in the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+documentation. Both these APIs define a set of C function calls.
+.P
+The native API C data types, function prototypes, option values, and error
+codes are defined in the header file \fBpcre2.h\fP, which also contains
+definitions of PCRE2_MAJOR and PCRE2_MINOR, the major and minor release numbers
+for the library. Applications can use these to include support for different
+releases of PCRE2.
+.P
+In a Windows environment, if you want to statically link an application program
+against a non-dll PCRE2 library, you must define PCRE2_STATIC before including
+\fBpcre2.h\fP.
+.P
+The functions \fBpcre2_compile()\fP and \fBpcre2_match()\fP are used for
+compiling and matching regular expressions in a Perl-compatible manner. A
+sample program that demonstrates the simplest way of using them is provided in
+the file called \fIpcre2demo.c\fP in the PCRE2 source distribution. A listing
+of this program is given in the
+.\" HREF
+\fBpcre2demo\fP
+.\"
+documentation, and the
+.\" HREF
+\fBpcre2sample\fP
+.\"
+documentation describes how to compile and run it.
+.P
+The compiling and matching functions recognize various options that are passed
+as bits in an options argument. There are also some more complicated parameters
+such as custom memory management functions and resource limits that are passed
+in "contexts" (which are just memory blocks, described below). Simple
+applications do not need to make use of contexts.
+.P
+Just-in-time (JIT) compiler support is an optional feature of PCRE2 that can be
+built in appropriate hardware environments. It greatly speeds up the matching
+performance of many patterns. Programs can request that it be used if
+available by calling \fBpcre2_jit_compile()\fP after a pattern has been
+successfully compiled by \fBpcre2_compile()\fP. This does nothing if JIT
+support is not available.
+.P
+More complicated programs might need to make use of the specialist functions
+\fBpcre2_jit_stack_create()\fP, \fBpcre2_jit_stack_free()\fP, and
+\fBpcre2_jit_stack_assign()\fP in order to control the JIT code's memory usage.
+.P
+JIT matching is automatically used by \fBpcre2_match()\fP if it is available,
+unless the PCRE2_NO_JIT option is set. There is also a direct interface for JIT
+matching, which gives improved performance at the expense of less sanity
+checking. The JIT-specific functions are discussed in the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+documentation.
+.P
+A second matching function, \fBpcre2_dfa_match()\fP, which is not
+Perl-compatible, is also provided. This uses a different algorithm for the
+matching. The alternative algorithm finds all possible matches (at a given
+point in the subject), and scans the subject just once (unless there are
+lookaround assertions). However, this algorithm does not return captured
+substrings. A description of the two matching algorithms and their advantages
+and disadvantages is given in the
+.\" HREF
+\fBpcre2matching\fP
+.\"
+documentation. There is no JIT support for \fBpcre2_dfa_match()\fP.
+.P
+In addition to the main compiling and matching functions, there are convenience
+functions for extracting captured substrings from a subject string that has
+been matched by \fBpcre2_match()\fP. They are:
+.sp
+ \fBpcre2_substring_copy_byname()\fP
+ \fBpcre2_substring_copy_bynumber()\fP
+ \fBpcre2_substring_get_byname()\fP
+ \fBpcre2_substring_get_bynumber()\fP
+ \fBpcre2_substring_list_get()\fP
+ \fBpcre2_substring_length_byname()\fP
+ \fBpcre2_substring_length_bynumber()\fP
+ \fBpcre2_substring_nametable_scan()\fP
+ \fBpcre2_substring_number_from_name()\fP
+.sp
+\fBpcre2_substring_free()\fP and \fBpcre2_substring_list_free()\fP are also
+provided, to free memory used for extracted strings. If either of these
+functions is called with a NULL argument, the function returns immediately
+without doing anything.
+.P
+The function \fBpcre2_substitute()\fP can be called to match a pattern and
+return a copy of the subject string with substitutions for parts that were
+matched.
+.P
+Functions whose names begin with \fBpcre2_serialize_\fP are used for saving
+compiled patterns on disc or elsewhere, and reloading them later.
+.P
+Finally, there are functions for finding out information about a compiled
+pattern (\fBpcre2_pattern_info()\fP) and about the configuration with which
+PCRE2 was built (\fBpcre2_config()\fP) and that it is using.
+.P
+Functions with names ending with \fB_free()\fP are used for freeing memory
+blocks of various sorts. In all cases, if one of these functions is called with
+a NULL argument, it does nothing.
+.
+.
+.SH "STRING LENGTHS AND OFFSETS"
+.rs
+.sp
+The PCRE2 API uses string lengths and offsets into strings of code units in
+several places. These values are always of type PCRE2_SIZE, which is an
+unsigned integer type, currently always defined as \fIsize_t\fP. The largest
+value that can be stored in such a type (that is ~(PCRE2_SIZE)0) is reserved
+as a special indicator for zero-terminated strings and unset offsets.
+Therefore, the longest string that can be handled is one less than this
+maximum. Note that string lengths are always given in code units. Only in the
+8-bit library is such a length the same as the number of bytes in the string.
+.
+.
+.\" HTML
+.SH NEWLINES
+.rs
+.sp
+PCRE2 supports five different conventions for indicating line breaks in
+strings: a single CR (carriage return) character, a single LF (linefeed)
+character, the two-character sequence CRLF, any of the three preceding, or any
+Unicode newline sequence. The Unicode newline sequences are the three just
+mentioned, plus the single characters VT (vertical tab, U+000B), FF (form feed,
+U+000C), NEL (next line, U+0085), LS (line separator, U+2028), and PS
+(paragraph separator, U+2029).
+.P
+Each of the first three conventions is used by at least one operating system as
+its standard newline sequence. When PCRE2 is built, a default can be specified.
+If it is not, the default is set to LF, which is the Unix standard. However,
+the newline convention can be changed by an application when calling
+\fBpcre2_compile()\fP, or it can be specified by special text at the start of
+the pattern itself; this overrides any other settings. See the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+page for details of the special character sequences.
+.P
+In the PCRE2 documentation the word "newline" is used to mean "the character or
+pair of characters that indicate a line break". The choice of newline
+convention affects the handling of the dot, circumflex, and dollar
+metacharacters, the handling of #-comments in /x mode, and, when CRLF is a
+recognized line ending sequence, the match position advancement for a
+non-anchored pattern. There is more detail about this in the
+.\" HTML
+.\"
+section on \fBpcre2_match()\fP options
+.\"
+below.
+.P
+The choice of newline convention does not affect the interpretation of
+the \en or \er escape sequences, nor does it affect what \eR matches; this has
+its own separate convention.
+.
+.
+.SH MULTITHREADING
+.rs
+.sp
+In a multithreaded application it is important to keep thread-specific data
+separate from data that can be shared between threads. The PCRE2 library code
+itself is thread-safe: it contains no static or global variables. The API is
+designed to be fairly simple for non-threaded applications while at the same
+time ensuring that multithreaded applications can use it.
+.P
+There are several different blocks of data that are used to pass information
+between the application and the PCRE2 libraries.
+.
+.
+.SS "The compiled pattern"
+.rs
+.sp
+A pointer to the compiled form of a pattern is returned to the user when
+\fBpcre2_compile()\fP is successful. The data in the compiled pattern is fixed,
+and does not change when the pattern is matched. Therefore, it is thread-safe,
+that is, the same compiled pattern can be used by more than one thread
+simultaneously. For example, an application can compile all its patterns at the
+start, before forking off multiple threads that use them. However, if the
+just-in-time (JIT) optimization feature is being used, it needs separate memory
+stack areas for each thread. See the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+documentation for more details.
+.P
+In a more complicated situation, where patterns are compiled only when they are
+first needed, but are still shared between threads, pointers to compiled
+patterns must be protected from simultaneous writing by multiple threads. This
+is somewhat tricky to do correctly. If you know that writing to a pointer is
+atomic in your environment, you can use logic like this:
+.sp
+ Get a read-only (shared) lock (mutex) for pointer
+ if (pointer == NULL)
+ {
+ Get a write (unique) lock for pointer
+ if (pointer == NULL) pointer = pcre2_compile(...
+ }
+ Release the lock
+ Use pointer in pcre2_match()
+.sp
+Of course, testing for compilation errors should also be included in the code.
+.P
+The reason for checking the pointer a second time is as follows: Several
+threads may have acquired the shared lock and tested the pointer for being
+NULL, but only one of them will be given the write lock, with the rest kept
+waiting. The winning thread will compile the pattern and store the result.
+After this thread releases the write lock, another thread will get it, and if
+it does not retest pointer for being NULL, will recompile the pattern and
+overwrite the pointer, creating a memory leak and possibly causing other
+issues.
+.P
+In an environment where writing to a pointer may not be atomic, the above logic
+is not sufficient. The thread that is doing the compiling may be descheduled
+after writing only part of the pointer, which could cause other threads to use
+an invalid value. Instead of checking the pointer itself, a separate "pointer
+is valid" flag (that can be updated atomically) must be used:
+.sp
+ Get a read-only (shared) lock (mutex) for pointer
+ if (!pointer_is_valid)
+ {
+ Get a write (unique) lock for pointer
+ if (!pointer_is_valid)
+ {
+ pointer = pcre2_compile(...
+ pointer_is_valid = TRUE
+ }
+ }
+ Release the lock
+ Use pointer in pcre2_match()
+.sp
+If JIT is being used, but the JIT compilation is not being done immediately
+(perhaps waiting to see if the pattern is used often enough), similar logic is
+required. JIT compilation updates a value within the compiled code block, so a
+thread must gain unique write access to the pointer before calling
+\fBpcre2_jit_compile()\fP. Alternatively, \fBpcre2_code_copy()\fP or
+\fBpcre2_code_copy_with_tables()\fP can be used to obtain a private copy of the
+compiled code before calling the JIT compiler.
+.
+.
+.SS "Context blocks"
+.rs
+.sp
+The next main section below introduces the idea of "contexts" in which PCRE2
+functions are called. A context is nothing more than a collection of parameters
+that control the way PCRE2 operates. Grouping a number of parameters together
+in a context is a convenient way of passing them to a PCRE2 function without
+using lots of arguments. The parameters that are stored in contexts are in some
+sense "advanced features" of the API. Many straightforward applications will
+not need to use contexts.
+.P
+In a multithreaded application, if the parameters in a context are values that
+are never changed, the same context can be used by all the threads. However, if
+any thread needs to change any value in a context, it must make its own
+thread-specific copy.
+.
+.
+.SS "Match blocks"
+.rs
+.sp
+The matching functions need a block of memory for storing the results of a
+match. This includes details of what was matched, as well as additional
+information such as the name of a (*MARK) setting. Each thread must provide its
+own copy of this memory.
+.
+.
+.SH "PCRE2 CONTEXTS"
+.rs
+.sp
+Some PCRE2 functions have a lot of parameters, many of which are used only by
+specialist applications, for example, those that use custom memory management
+or non-standard character tables. To keep function argument lists at a
+reasonable size, and at the same time to keep the API extensible, "uncommon"
+parameters are passed to certain functions in a \fBcontext\fP instead of
+directly. A context is just a block of memory that holds the parameter values.
+Applications that do not need to adjust any of the context parameters can pass
+NULL when a context pointer is required.
+.P
+There are three different types of context: a general context that is relevant
+for several PCRE2 operations, a compile-time context, and a match-time context.
+.
+.
+.SS "The general context"
+.rs
+.sp
+At present, this context just contains pointers to (and data for) external
+memory management functions that are called from several places in the PCRE2
+library. The context is named `general' rather than specifically `memory'
+because in future other fields may be added. If you do not want to supply your
+own custom memory management functions, you do not need to bother with a
+general context. A general context is created by:
+.sp
+.nf
+.B pcre2_general_context *pcre2_general_context_create(
+.B " void *(*\fIprivate_malloc\fP)(PCRE2_SIZE, void *),"
+.B " void (*\fIprivate_free\fP)(void *, void *), void *\fImemory_data\fP);"
+.fi
+.sp
+The two function pointers specify custom memory management functions, whose
+prototypes are:
+.sp
+ \fBvoid *private_malloc(PCRE2_SIZE, void *);\fP
+ \fBvoid private_free(void *, void *);\fP
+.sp
+Whenever code in PCRE2 calls these functions, the final argument is the value
+of \fImemory_data\fP. Either of the first two arguments of the creation
+function may be NULL, in which case the system memory management functions
+\fImalloc()\fP and \fIfree()\fP are used. (This is not currently useful, as
+there are no other fields in a general context, but in future there might be.)
+The \fIprivate_malloc()\fP function is used (if supplied) to obtain memory for
+storing the context, and all three values are saved as part of the context.
+.P
+Whenever PCRE2 creates a data block of any kind, the block contains a pointer
+to the \fIfree()\fP function that matches the \fImalloc()\fP function that was
+used. When the time comes to free the block, this function is called.
+.P
+A general context can be copied by calling:
+.sp
+.nf
+.B pcre2_general_context *pcre2_general_context_copy(
+.B " pcre2_general_context *\fIgcontext\fP);"
+.fi
+.sp
+The memory used for a general context should be freed by calling:
+.sp
+.nf
+.B void pcre2_general_context_free(pcre2_general_context *\fIgcontext\fP);
+.fi
+.sp
+If this function is passed a NULL argument, it returns immediately without
+doing anything.
+.
+.
+.\" HTML
+.SS "The compile context"
+.rs
+.sp
+A compile context is required if you want to provide an external function for
+stack checking during compilation or to change the default values of any of the
+following compile-time parameters:
+.sp
+ What \eR matches (Unicode newlines or CR, LF, CRLF only)
+ PCRE2's character tables
+ The newline character sequence
+ The compile time nested parentheses limit
+ The maximum length of the pattern string
+ The extra options bits (none set by default)
+ Which performance optimizations the compiler should apply
+.sp
+A compile context is also required if you are using custom memory management.
+If none of these apply, just pass NULL as the context argument of
+\fIpcre2_compile()\fP.
+.P
+A compile context is created, copied, and freed by the following functions:
+.sp
+.nf
+.B pcre2_compile_context *pcre2_compile_context_create(
+.B " pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B pcre2_compile_context *pcre2_compile_context_copy(
+.B " pcre2_compile_context *\fIccontext\fP);"
+.sp
+.B void pcre2_compile_context_free(pcre2_compile_context *\fIccontext\fP);
+.fi
+.sp
+A compile context is created with default values for its parameters. These can
+be changed by calling the following functions, which return 0 on success, or
+PCRE2_ERROR_BADDATA if invalid data is detected.
+.sp
+.nf
+.B int pcre2_set_bsr(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.sp
+The value must be PCRE2_BSR_ANYCRLF, to specify that \eR matches only CR, LF,
+or CRLF, or PCRE2_BSR_UNICODE, to specify that \eR matches any Unicode line
+ending sequence. The value is used by the JIT compiler and by the two
+interpreted matching functions, \fIpcre2_match()\fP and
+\fIpcre2_dfa_match()\fP.
+.sp
+.nf
+.B int pcre2_set_character_tables(pcre2_compile_context *\fIccontext\fP,
+.B " const uint8_t *\fItables\fP);"
+.fi
+.sp
+The value must be the result of a call to \fBpcre2_maketables()\fP, whose only
+argument is a general context. This function builds a set of character tables
+in the current locale.
+.sp
+.nf
+.B int pcre2_set_compile_extra_options(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIextra_options\fP);"
+.fi
+.sp
+As PCRE2 has developed, almost all the 32 option bits that are available in
+the \fIoptions\fP argument of \fBpcre2_compile()\fP have been used up. To avoid
+running out, the compile context contains a set of extra option bits which are
+used for some newer, assumed rarer, options. This function sets those bits. It
+always sets all the bits (either on or off). It does not modify any existing
+setting. The available options are defined in the section entitled "Extra
+compile options"
+.\" HTML
+.\"
+below.
+.\"
+.sp
+.nf
+.B int pcre2_set_max_pattern_length(pcre2_compile_context *\fIccontext\fP,
+.B " PCRE2_SIZE \fIvalue\fP);"
+.fi
+.sp
+This sets a maximum length, in code units, for any pattern string that is
+compiled with this context. If the pattern is longer, an error is generated.
+This facility is provided so that applications that accept patterns from
+external sources can limit their size. The default is the largest number that a
+PCRE2_SIZE variable can hold, which is effectively unlimited.
+.sp
+.nf
+.B int pcre2_set_max_pattern_compiled_length(
+.B " pcre2_compile_context *\fIccontext\fP, PCRE2_SIZE \fIvalue\fP);"
+.fi
+.sp
+This sets a maximum size, in bytes, for the memory needed to hold the compiled
+version of a pattern that is compiled with this context. If the pattern needs
+more memory, an error is generated. This facility is provided so that
+applications that accept patterns from external sources can limit the amount of
+memory they use. The default is the largest number that a PCRE2_SIZE variable
+can hold, which is effectively unlimited.
+.sp
+.nf
+.B int pcre2_set_max_varlookbehind(pcre2_compile_contest *\fIccontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.sp
+This sets a maximum length for the number of characters matched by a
+variable-length lookbehind assertion. The default is set when PCRE2 is built,
+with the ultimate default being 255, the same as Perl. Lookbehind assertions
+without a bounding length are not supported.
+.sp
+.nf
+.B int pcre2_set_newline(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.sp
+This specifies which characters or character sequences are to be recognized as
+newlines. The value must be one of PCRE2_NEWLINE_CR (carriage return only),
+PCRE2_NEWLINE_LF (linefeed only), PCRE2_NEWLINE_CRLF (the two-character
+sequence CR followed by LF), PCRE2_NEWLINE_ANYCRLF (any of the above),
+PCRE2_NEWLINE_ANY (any Unicode newline sequence), or PCRE2_NEWLINE_NUL (the
+NUL character, that is a binary zero).
+.P
+A pattern can override the value set in the compile context by starting with a
+sequence such as (*CRLF). See the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+page for details.
+.P
+When a pattern is compiled with the PCRE2_EXTENDED or PCRE2_EXTENDED_MORE
+option, the newline convention affects the recognition of the end of internal
+comments starting with #. The value is saved with the compiled pattern for
+subsequent use by the JIT compiler and by the two interpreted matching
+functions, \fIpcre2_match()\fP and \fIpcre2_dfa_match()\fP.
+.sp
+.nf
+.B int pcre2_set_parens_nest_limit(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.sp
+This parameter adjusts the limit, set when PCRE2 is built (default 250), on the
+depth of parenthesis nesting in a pattern. This limit stops rogue patterns
+using up too much system stack when being compiled. The limit applies to
+parentheses of all kinds, not just capturing parentheses.
+.sp
+.nf
+.B int pcre2_set_compile_recursion_guard(pcre2_compile_context *\fIccontext\fP,
+.B " int (*\fIguard_function\fP)(uint32_t, void *), void *\fIuser_data\fP);"
+.fi
+.sp
+There is at least one application that runs PCRE2 in threads with very limited
+system stack, where running out of stack is to be avoided at all costs. The
+parenthesis limit above cannot take account of how much stack is actually
+available during compilation. For a finer control, you can supply a function
+that is called whenever \fBpcre2_compile()\fP starts to compile a parenthesized
+part of a pattern. This function can check the actual stack size (or anything
+else that it wants to, of course).
+.P
+The first argument to the callout function gives the current depth of
+nesting, and the second is user data that is set up by the last argument of
+\fBpcre2_set_compile_recursion_guard()\fP. The callout function should return
+zero if all is well, or non-zero to force an error.
+.sp
+.nf
+.B int pcre2_set_optimize(pcre2_compile_context *\fIccontext\fP,
+.B " uint32_t \fIdirective\fP);"
+.fi
+.sp
+PCRE2 can apply various performance optimizations during compilation, in order
+to make matching faster. For example, the compiler might convert some regex
+constructs into an equivalent construct which \fBpcre2_match()\fP can execute
+faster. By default, all available optimizations are enabled. However, in rare
+cases, one might wish to disable specific optimizations. For example, if it is
+known that some optimizations cannot benefit a certain regex, it might be
+desirable to disable them, in order to speed up compilation.
+.P
+The permitted values of \fIdirective\fP are as follows:
+.sp
+ PCRE2_OPTIMIZATION_FULL
+.sp
+Enable all optional performance optimizations. This is the default value.
+.sp
+ PCRE2_OPTIMIZATION_NONE
+.sp
+Disable all optional performance optimizations.
+.sp
+ PCRE2_AUTO_POSSESS
+ PCRE2_AUTO_POSSESS_OFF
+.sp
+Enable/disable "auto-possessification" of variable quantifiers such as * and +.
+This optimization, for example, turns a+b into a++b in order to avoid
+backtracks into a+ that can never be successful. However, if callouts are in
+use, auto-possessification means that some callouts are never taken. You can
+disable this optimization if you want the matching functions to do a full,
+unoptimized search and run all the callouts.
+.sp
+ PCRE2_DOTSTAR_ANCHOR
+ PCRE2_DOTSTAR_ANCHOR_OFF
+.sp
+Enable/disable an optimization that is applied when .* is the first significant
+item in a top-level branch of a pattern, and all the other branches also start
+with .* or with \eA or \eG or ^. Such a pattern is automatically anchored if
+PCRE2_DOTALL is set for all the .* items and PCRE2_MULTILINE is not set for any
+^ items. Otherwise, the fact that any match must start either at the start of
+the subject or following a newline is remembered. Like other optimizations,
+this can cause callouts to be skipped.
+.P
+Dotstar anchor optimization is automatically disabled for .* if it is inside an
+atomic group or a capture group that is the subject of a backreference, or if
+the pattern contains (*PRUNE) or (*SKIP).
+.sp
+ PCRE2_START_OPTIMIZE
+ PCRE2_START_OPTIMIZE_OFF
+.sp
+Enable/disable optimizations which cause matching functions to scan the subject
+string for specific code unit values before attempting a match. For example, if
+it is known that an unanchored match must start with a specific value, the
+matching code searches the subject for that value, and fails immediately if it
+cannot find it, without actually running the main matching function. This means
+that a special item such as (*COMMIT) at the start of a pattern is not
+considered until after a suitable starting point for the match has been found.
+Also, when callouts or (*MARK) items are in use, these "start-up" optimizations
+can cause them to be skipped if the pattern is never actually used. The start-up
+optimizations are in effect a pre-scan of the subject that takes place before
+the pattern is run.
+.P
+Disabling start-up optimizations ensures that in cases where the result is "no
+match", the callouts do occur, and that items such as (*COMMIT) and (*MARK) are
+considered at every possible starting position in the subject string.
+.P
+Disabling start-up optimizations may change the outcome of a matching operation.
+Consider the pattern
+.sp
+ (*COMMIT)ABC
+.sp
+When this is compiled, PCRE2 records the fact that a match must start with the
+character "A". Suppose the subject string is "DEFABC". The start-up
+optimization scans along the subject, finds "A" and runs the first match
+attempt from there. The (*COMMIT) item means that the pattern must match the
+current starting position, which in this case, it does. However, if the same
+match is run without start-up optimizations, the initial scan along the subject
+string does not happen. The first match attempt is run starting from "D" and
+when this fails, (*COMMIT) prevents any further matches being tried, so the
+overall result is "no match".
+.P
+Another start-up optimization makes use of a minimum length for a matching
+subject, which is recorded when possible. Consider the pattern
+.sp
+ (*MARK:1)B(*MARK:2)(X|Y)
+.sp
+The minimum length for a match is two characters. If the subject is "XXBB", the
+"starting character" optimization skips "XX", then tries to match "BB", which
+is long enough. In the process, (*MARK:2) is encountered and remembered. When
+the match attempt fails, the next "B" is found, but there is only one character
+left, so there are no more attempts, and "no match" is returned with the "last
+mark seen" set to "2". Without start-up optimizations, however, matches are
+tried at every possible starting position, including at the end of the subject,
+where (*MARK:1) is encountered, but there is no "B", so the "last mark seen"
+that is returned is "1". In this case, the optimizations do not affect the
+overall match result, which is still "no match", but they do affect the
+auxiliary information that is returned.
+.
+.
+.\" HTML
+.SS "The match context"
+.rs
+.sp
+A match context is required if you want to:
+.sp
+ Set up a callout function
+ Set an offset limit for matching an unanchored pattern
+ Change the limit on the amount of heap used when matching
+ Change the backtracking match limit
+ Change the backtracking depth limit
+ Set custom memory management specifically for the match
+.sp
+If none of these apply, just pass NULL as the context argument of
+\fBpcre2_match()\fP, \fBpcre2_dfa_match()\fP, or \fBpcre2_jit_match()\fP.
+.P
+A match context is created, copied, and freed by the following functions:
+.sp
+.nf
+.B pcre2_match_context *pcre2_match_context_create(
+.B " pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B pcre2_match_context *pcre2_match_context_copy(
+.B " pcre2_match_context *\fImcontext\fP);"
+.sp
+.B void pcre2_match_context_free(pcre2_match_context *\fImcontext\fP);
+.fi
+.sp
+A match context is created with default values for its parameters. These can
+be changed by calling the following functions, which return 0 on success, or
+PCRE2_ERROR_BADDATA if invalid data is detected.
+.sp
+.nf
+.B int pcre2_set_callout(pcre2_match_context *\fImcontext\fP,
+.B " int (*\fIcallout_function\fP)(pcre2_callout_block *, void *),"
+.B " void *\fIcallout_data\fP);"
+.fi
+.sp
+This sets up a callout function for PCRE2 to call at specified points
+during a matching operation. Details are given in the
+.\" HREF
+\fBpcre2callout\fP
+.\"
+documentation.
+.sp
+.nf
+.B int pcre2_set_substitute_callout(pcre2_match_context *\fImcontext\fP,
+.B " int (*\fIcallout_function\fP)(pcre2_substitute_callout_block *, void *),"
+.B " void *\fIcallout_data\fP);"
+.fi
+.sp
+This sets up a callout function for PCRE2 to call after each substitution
+made by \fBpcre2_substitute()\fP. Details are given in the section entitled
+"Creating a new string with substitutions"
+.\" HTML
+.\"
+below.
+.\"
+.sp
+.nf
+.B int pcre2_set_substitute_case_callout(pcre2_match_context *\fImcontext\fP,
+.B " PCRE2_SIZE (*\fIcallout_function\fP)(PCRE2_SPTR, PCRE2_SIZE,"
+.B " PCRE2_UCHAR *, PCRE2_SIZE,"
+.B " int, void *),"
+.B " void *\fIcallout_data\fP);"
+.fi
+.sp
+This sets up a callout function for PCRE2 to call when performing case
+transformations inside \fBpcre2_substitute()\fP. Details are given in the
+section entitled "Creating a new string with substitutions"
+.\" HTML
+.\"
+below.
+.\"
+.sp
+.nf
+.B int pcre2_set_offset_limit(pcre2_match_context *\fImcontext\fP,
+.B " PCRE2_SIZE \fIvalue\fP);"
+.fi
+.sp
+The \fIoffset_limit\fP parameter limits how far an unanchored search can
+advance in the subject string. The default value is PCRE2_UNSET. The
+\fBpcre2_match()\fP and \fBpcre2_dfa_match()\fP functions return
+PCRE2_ERROR_NOMATCH if a match with a starting point before or at the given
+offset is not found. The \fBpcre2_substitute()\fP function makes no more
+substitutions.
+.P
+For example, if the pattern /abc/ is matched against "123abc" with an offset
+limit less than 3, the result is PCRE2_ERROR_NOMATCH. A match can never be
+found if the \fIstartoffset\fP argument of \fBpcre2_match()\fP,
+\fBpcre2_dfa_match()\fP, or \fBpcre2_substitute()\fP is greater than the offset
+limit set in the match context.
+.P
+When using this facility, you must set the PCRE2_USE_OFFSET_LIMIT option when
+calling \fBpcre2_compile()\fP so that when JIT is in use, different code can be
+compiled. If a match is started with a non-default match limit when
+PCRE2_USE_OFFSET_LIMIT is not set, an error is generated.
+.P
+The offset limit facility can be used to track progress when searching large
+subject strings or to limit the extent of global substitutions. See also the
+PCRE2_FIRSTLINE option, which requires a match to start before or at the first
+newline that follows the start of matching in the subject. If this is set with
+an offset limit, a match must occur in the first line and also within the
+offset limit. In other words, whichever limit comes first is used.
+.sp
+.nf
+.B int pcre2_set_heap_limit(pcre2_match_context *\fImcontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.sp
+The \fIheap_limit\fP parameter specifies, in units of kibibytes (1024 bytes),
+the maximum amount of heap memory that \fBpcre2_match()\fP may use to hold
+backtracking information when running an interpretive match. This limit also
+applies to \fBpcre2_dfa_match()\fP, which may use the heap when processing
+patterns with a lot of nested pattern recursion or lookarounds or atomic
+groups. This limit does not apply to matching with the JIT optimization, which
+has its own memory control arrangements (see the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+documentation for more details). If the limit is reached, the negative error
+code PCRE2_ERROR_HEAPLIMIT is returned. The default limit can be set when PCRE2
+is built; if it is not, the default is set very large and is essentially
+unlimited.
+.P
+A value for the heap limit may also be supplied by an item at the start of a
+pattern of the form
+.sp
+ (*LIMIT_HEAP=ddd)
+.sp
+where ddd is a decimal number. However, such a setting is ignored unless ddd is
+less than the limit set by the caller of \fBpcre2_match()\fP or, if no such
+limit is set, less than the default.
+.P
+The \fBpcre2_match()\fP function always needs some heap memory, so setting a
+value of zero guarantees a "heap limit exceeded" error. Details of how
+\fBpcre2_match()\fP uses the heap are given in the
+.\" HREF
+\fBpcre2perform\fP
+.\"
+documentation.
+.P
+For \fBpcre2_dfa_match()\fP, a vector on the system stack is used when
+processing pattern recursions, lookarounds, or atomic groups, and only if this
+is not big enough is heap memory used. In this case, setting a value of zero
+disables the use of the heap.
+.sp
+.nf
+.B int pcre2_set_match_limit(pcre2_match_context *\fImcontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.sp
+The \fImatch_limit\fP parameter provides a means of preventing PCRE2 from using
+up too many computing resources when processing patterns that are not going to
+match, but which have a very large number of possibilities in their search
+trees. The classic example is a pattern that uses nested unlimited repeats.
+.P
+There is an internal counter in \fBpcre2_match()\fP that is incremented each
+time round its main matching loop. If this value reaches the match limit,
+\fBpcre2_match()\fP returns the negative value PCRE2_ERROR_MATCHLIMIT. This has
+the effect of limiting the amount of backtracking that can take place. For
+patterns that are not anchored, the count restarts from zero for each position
+in the subject string. This limit also applies to \fBpcre2_dfa_match()\fP,
+though the counting is done in a different way.
+.P
+When \fBpcre2_match()\fP is called with a pattern that was successfully
+processed by \fBpcre2_jit_compile()\fP, the way in which matching is executed
+is entirely different. However, there is still the possibility of runaway
+matching that goes on for a very long time, and so the \fImatch_limit\fP value
+is also used in this case (but in a different way) to limit how long the
+matching can continue.
+.P
+The default value for the limit can be set when PCRE2 is built; the default is
+10 million, which handles all but the most extreme cases. A value for the match
+limit may also be supplied by an item at the start of a pattern of the form
+.sp
+ (*LIMIT_MATCH=ddd)
+.sp
+where ddd is a decimal number. However, such a setting is ignored unless ddd is
+less than the limit set by the caller of \fBpcre2_match()\fP or
+\fBpcre2_dfa_match()\fP or, if no such limit is set, less than the default.
+.sp
+.nf
+.B int pcre2_set_depth_limit(pcre2_match_context *\fImcontext\fP,
+.B " uint32_t \fIvalue\fP);"
+.fi
+.sp
+This parameter limits the depth of nested backtracking in \fBpcre2_match()\fP.
+Each time a nested backtracking point is passed, a new memory frame is used
+to remember the state of matching at that point. Thus, this parameter
+indirectly limits the amount of memory that is used in a match. However,
+because the size of each memory frame depends on the number of capturing
+parentheses, the actual memory limit varies from pattern to pattern. This limit
+was more useful in versions before 10.30, where function recursion was used for
+backtracking.
+.P
+The depth limit is not relevant, and is ignored, when matching is done using
+JIT compiled code. However, it is supported by \fBpcre2_dfa_match()\fP, which
+uses it to limit the depth of nested internal recursive function calls that
+implement atomic groups, lookaround assertions, and pattern recursions. This
+limits, indirectly, the amount of system stack that is used. It was more useful
+in versions before 10.32, when stack memory was used for local workspace
+vectors for recursive function calls. From version 10.32, only local variables
+are allocated on the stack and as each call uses only a few hundred bytes, even
+a small stack can support quite a lot of recursion.
+.P
+If the depth of internal recursive function calls is great enough, local
+workspace vectors are allocated on the heap from version 10.32 onwards, so the
+depth limit also indirectly limits the amount of heap memory that is used. A
+recursive pattern such as /(.(?2))((?1)|)/, when matched to a very long string
+using \fBpcre2_dfa_match()\fP, can use a great deal of memory. However, it is
+probably better to limit heap usage directly by calling
+\fBpcre2_set_heap_limit()\fP.
+.P
+The default value for the depth limit can be set when PCRE2 is built; if it is
+not, the default is set to the same value as the default for the match limit.
+If the limit is exceeded, \fBpcre2_match()\fP or \fBpcre2_dfa_match()\fP
+returns PCRE2_ERROR_DEPTHLIMIT. A value for the depth limit may also be
+supplied by an item at the start of a pattern of the form
+.sp
+ (*LIMIT_DEPTH=ddd)
+.sp
+where ddd is a decimal number. However, such a setting is ignored unless ddd is
+less than the limit set by the caller of \fBpcre2_match()\fP or
+\fBpcre2_dfa_match()\fP or, if no such limit is set, less than the default.
+.
+.
+.SH "CHECKING BUILD-TIME OPTIONS"
+.rs
+.sp
+.B int pcre2_config(uint32_t \fIwhat\fP, void *\fIwhere\fP);
+.P
+The function \fBpcre2_config()\fP makes it possible for a PCRE2 client to find
+the value of certain configuration parameters and to discover which optional
+features have been compiled into the PCRE2 library. The
+.\" HREF
+\fBpcre2build\fP
+.\"
+documentation has more details about these features.
+.P
+The first argument for \fBpcre2_config()\fP specifies which information is
+required. The second argument is a pointer to memory into which the information
+is placed. If NULL is passed, the function returns the amount of memory that is
+needed for the requested information. For calls that return numerical values,
+the value is in bytes; when requesting these values, \fIwhere\fP should point
+to appropriately aligned memory. For calls that return strings, the required
+length is given in code units, not counting the terminating zero.
+.P
+When requesting information, the returned value from \fBpcre2_config()\fP is
+non-negative on success, or the negative error code PCRE2_ERROR_BADOPTION if
+the value in the first argument is not recognized. The following information is
+available:
+.sp
+ PCRE2_CONFIG_BSR
+.sp
+The output is a uint32_t integer whose value indicates what character
+sequences the \eR escape sequence matches by default. A value of
+PCRE2_BSR_UNICODE means that \eR matches any Unicode line ending sequence; a
+value of PCRE2_BSR_ANYCRLF means that \eR matches only CR, LF, or CRLF. The
+default can be overridden when a pattern is compiled.
+.sp
+ PCRE2_CONFIG_COMPILED_WIDTHS
+.sp
+The output is a uint32_t integer whose lower bits indicate which code unit
+widths were selected when PCRE2 was built. The 1-bit indicates 8-bit support,
+and the 2-bit and 4-bit indicate 16-bit and 32-bit support, respectively.
+.sp
+ PCRE2_CONFIG_DEPTHLIMIT
+.sp
+The output is a uint32_t integer that gives the default limit for the depth of
+nested backtracking in \fBpcre2_match()\fP or the depth of nested recursions,
+lookarounds, and atomic groups in \fBpcre2_dfa_match()\fP. Further details are
+given with \fBpcre2_set_depth_limit()\fP above.
+.sp
+ PCRE2_CONFIG_EFFECTIVE_LINKSIZE
+.sp
+The output is a uint32_t integer that contains the number of bytes the library
+uses for internal linkage in compiled regular expressions. Its value is derived
+from the value that was provided at build time and that is described below by
+PCRE2_CONFIG_LINKSIZE.
+.sp
+ PCRE2_CONFIG_HEAPLIMIT
+.sp
+The output is a uint32_t integer that gives, in kibibytes, the default limit
+for the amount of heap memory used by \fBpcre2_match()\fP or
+\fBpcre2_dfa_match()\fP. Further details are given with
+\fBpcre2_set_heap_limit()\fP above.
+.sp
+ PCRE2_CONFIG_JIT
+.sp
+The output is a uint32_t integer that is set to one if support for just-in-time
+compiling is included in the library; otherwise it is set to zero. Note that
+having the support in the library does not guarantee that JIT will be used for
+any given match, and neither does it guarantee that JIT will actually be able
+to function, because it may not be able to allocate executable memory in some
+environments. There is a special call to \fBpcre2_jit_compile()\fP that can be
+used to check this. See the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+documentation for more details.
+.sp
+ PCRE2_CONFIG_JITTARGET
+.sp
+The \fIwhere\fP argument should point to a code-unit-aligned buffer. All
+previous versions of PCRE2 have required no more than 128 code units of buffer
+capacity. However, this requirement is not guaranteed to be maintained, so
+applications should call \fBpcre2_config()\fP with \fBwhere\fP set to NULL to
+receive the required buffer size, then assert or allocate a suitably-size buffer
+for a second call to \fBpcre2_config()\fP. The buffer is filled with a string
+that contains the name of the architecture for which the JIT compiler is
+configured at build time, for example, a 64-bit ARM CPU that supports the
+Armv8.1 extension writes "ARM-64 (LSE) 64bit (little endian + unaligned)". If
+JIT support is not available, PCRE2_ERROR_BADOPTION is returned; otherwise the
+number of code units used is returned. This is the length of the string plus one
+unit for the terminating zero.
+.sp
+ PCRE2_CONFIG_LINKSIZE
+.sp
+The output is a uint32_t integer that contains the number of bytes the library
+was instructed to use for internal linkage in compiled regular expressions.
+When PCRE2 is configured, the value can be set to 2, 3, or 4, with the default
+being 2 for most libraries.
+.P
+The actual number of bytes used depends on the size of the code units that the
+library supports and can be higher. See PCRE2_CONFIG_EFFECTIVE_LINKSIZE above
+for details.
+.P
+The default value of 2 for the 8-bit and 16-bit libraries is sufficient for all
+but the most massive patterns, since it allows the size of the compiled pattern
+to be up to 65535 code units. Larger values allow larger regular expressions to
+be compiled by those two libraries, but at the expense of slower matching.
+.sp
+ PCRE2_CONFIG_MATCHLIMIT
+.sp
+The output is a uint32_t integer that gives the default match limit for
+\fBpcre2_match()\fP. Further details are given with
+\fBpcre2_set_match_limit()\fP above.
+.sp
+ PCRE2_CONFIG_NEWLINE
+.sp
+The output is a uint32_t integer whose value specifies the default character
+sequence that is recognized as meaning "newline". The values are:
+.sp
+ PCRE2_NEWLINE_CR Carriage return (CR)
+ PCRE2_NEWLINE_LF Linefeed (LF)
+ PCRE2_NEWLINE_CRLF Carriage return, linefeed (CRLF)
+ PCRE2_NEWLINE_ANY Any Unicode line ending
+ PCRE2_NEWLINE_ANYCRLF Any of CR, LF, or CRLF
+ PCRE2_NEWLINE_NUL The NUL character (binary zero)
+.sp
+The default should normally correspond to the standard sequence for your
+operating system.
+.sp
+ PCRE2_CONFIG_NEVER_BACKSLASH_C
+.sp
+The output is a uint32_t integer that is set to one if the use of \eC was
+permanently disabled when PCRE2 was built; otherwise it is set to zero.
+.sp
+ PCRE2_CONFIG_PARENSLIMIT
+.sp
+The output is a uint32_t integer that gives the maximum depth of nesting
+of parentheses (of any kind) in a pattern. This limit is imposed to cap the
+amount of system stack used when a pattern is compiled. It is specified when
+PCRE2 is built; the default is 250. This limit does not take into account the
+stack that may already be used by the calling application. For finer control
+over compilation stack usage, see \fBpcre2_set_compile_recursion_guard()\fP.
+.sp
+ PCRE2_CONFIG_STACKRECURSE
+.sp
+This parameter is obsolete and should not be used in new code. The output is a
+uint32_t integer that is always set to zero.
+.sp
+ PCRE2_CONFIG_TABLES_LENGTH
+.sp
+The output is a uint32_t integer that gives the length of PCRE2's character
+processing tables in bytes. For details of these tables see the
+.\" HTML
+.\"
+section on locale support
+.\"
+below.
+.sp
+ PCRE2_CONFIG_UNICODE_VERSION
+.sp
+The \fIwhere\fP argument should point to a code-unit-aligned buffer. All
+previous versions of PCRE2 have required no more than 24 code units of buffer
+capacity. However, applications should call \fBpcre2_config()\fP with
+\fBwhere\fP set to NULL to receive the required buffer size, then assert or
+allocate a suitably-size buffer for a second call to \fBpcre2_config()\fP. If
+PCRE2 has been compiled without Unicode support, the buffer is filled with the
+text "Unicode not supported". Otherwise, the Unicode version string (for
+example, "8.0.0") is written. The number of code units used is returned. This is
+the length of the string plus one unit for the terminating zero.
+.sp
+ PCRE2_CONFIG_UNICODE
+.sp
+The output is a uint32_t integer that is set to one if Unicode support is
+available; otherwise it is set to zero. Unicode support implies UTF support.
+.sp
+ PCRE2_CONFIG_VERSION
+.sp
+The \fIwhere\fP argument should point to a code-unit-aligned buffer. All
+previous versions of PCRE2 have required no more than 24 code units of buffer
+capacity. However, applications should call \fBpcre2_config()\fP with
+\fBwhere\fP set to NULL to receive the required buffer size, then assert or
+allocate a suitably-size buffer for a second call to \fBpcre2_config()\fP. The
+buffer is filled with the PCRE2 version string, zero-terminated. The number of
+code units used is returned. This is the length of the string plus one unit for
+the terminating zero.
+.
+.
+.\" HTML
+.SH "COMPILING A PATTERN"
+.rs
+.sp
+.nf
+.B pcre2_code *pcre2_compile(PCRE2_SPTR \fIpattern\fP, PCRE2_SIZE \fIlength\fP,
+.B " uint32_t \fIoptions\fP, int *\fIerrorcode\fP, PCRE2_SIZE *\fIerroroffset,\fP"
+.B " pcre2_compile_context *\fIccontext\fP);"
+.sp
+.B void pcre2_code_free(pcre2_code *\fIcode\fP);
+.sp
+.B pcre2_code *pcre2_code_copy(const pcre2_code *\fIcode\fP);
+.sp
+.B pcre2_code *pcre2_code_copy_with_tables(const pcre2_code *\fIcode\fP);
+.fi
+.P
+The \fBpcre2_compile()\fP function compiles a pattern into an internal form.
+The pattern is defined by a pointer to a string of code units and a length in
+code units. If the pattern is zero-terminated, the length can be specified as
+PCRE2_ZERO_TERMINATED. A NULL pattern pointer with a length of zero is treated
+as an empty string (NULL with a non-zero length causes an error return). The
+function returns a pointer to a block of memory that contains the compiled
+pattern and related data, or NULL if an error occurred.
+.P
+If the compile context argument \fIccontext\fP is NULL, memory for the compiled
+pattern is obtained by calling \fBmalloc()\fP. Otherwise, it is obtained from
+the same memory function that was used for the compile context. The caller must
+free the memory by calling \fBpcre2_code_free()\fP when it is no longer needed.
+If \fBpcre2_code_free()\fP is called with a NULL argument, it returns
+immediately, without doing anything.
+.P
+The function \fBpcre2_code_copy()\fP makes a copy of the compiled code in new
+memory, using the same memory allocator as was used for the original. However,
+if the code has been processed by the JIT compiler (see
+.\" HTML
+.\"
+below),
+.\"
+the JIT information cannot be copied (because it is position-dependent).
+The new copy can initially be used only for non-JIT matching, though it can be
+passed to \fBpcre2_jit_compile()\fP if required. If \fBpcre2_code_copy()\fP is
+called with a NULL argument, it returns NULL.
+.P
+The \fBpcre2_code_copy()\fP function provides a way for individual threads in a
+multithreaded application to acquire a private copy of shared compiled code.
+However, it does not make a copy of the character tables used by the compiled
+pattern; the new pattern code points to the same tables as the original code.
+(See
+.\" HTML
+.\"
+"Locale Support"
+.\"
+below for details of these character tables.) In many applications the same
+tables are used throughout, so this behaviour is appropriate. Nevertheless,
+there are occasions when a copy of a compiled pattern and the relevant tables
+are needed. The \fBpcre2_code_copy_with_tables()\fP provides this facility.
+Copies of both the code and the tables are made, with the new code pointing to
+the new tables. The memory for the new tables is automatically freed when
+\fBpcre2_code_free()\fP is called for the new copy of the compiled code. If
+\fBpcre2_code_copy_with_tables()\fP is called with a NULL argument, it returns
+NULL.
+.P
+NOTE: When one of the matching functions is called, pointers to the compiled
+pattern and the subject string are set in the match data block so that they can
+be referenced by the substring extraction functions after a successful match.
+After running a match, you must not free a compiled pattern or a subject string
+until after all operations on the
+.\" HTML
+.\"
+match data block
+.\"
+have taken place, unless, in the case of the subject string, you have used the
+PCRE2_COPY_MATCHED_SUBJECT option, which is described in the section entitled
+"Option bits for \fBpcre2_match()\fP"
+.\" HTML
+.\"
+below.
+.\"
+.P
+The \fIoptions\fP argument for \fBpcre2_compile()\fP contains various bit
+settings that affect the compilation. It should be zero if none of them are
+required. The available options are described below. Some of them (in
+particular, those that are compatible with Perl, but some others as well) can
+also be set and unset from within the pattern (see the detailed description in
+the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+documentation).
+.P
+For those options that can be different in different parts of the pattern, the
+contents of the \fIoptions\fP argument specifies their settings at the start of
+compilation. The PCRE2_ANCHORED, PCRE2_ENDANCHORED, and PCRE2_NO_UTF_CHECK
+options can be set at the time of matching as well as at compile time.
+.P
+Some additional options and less frequently required compile-time parameters
+(for example, the newline setting) can be provided in a compile context (as
+described
+.\" HTML
+.\"
+above).
+.\"
+.P
+If \fIerrorcode\fP or \fIerroroffset\fP is NULL, \fBpcre2_compile()\fP returns
+NULL immediately. Otherwise, the variables to which these point are set to an
+error code and an offset (number of code units) within the pattern,
+respectively, when \fBpcre2_compile()\fP returns NULL because a compilation
+error has occurred.
+.P
+There are over 100 positive error codes that \fBpcre2_compile()\fP may return
+if it finds an error in the pattern. There are also some negative error codes
+that are used for invalid UTF strings when validity checking is in force. These
+are the same as given by \fBpcre2_match()\fP and \fBpcre2_dfa_match()\fP, and
+are described in the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+documentation. There is no separate documentation for the positive error codes,
+because the textual error messages that are obtained by calling the
+\fBpcre2_get_error_message()\fP function (see "Obtaining a textual error
+message"
+.\" HTML
+.\"
+below)
+.\"
+should be self-explanatory. Macro names starting with PCRE2_ERROR_ are defined
+for both positive and negative error codes in \fBpcre2.h\fP. When compilation
+is successful \fIerrorcode\fP is set to a value that returns the message "no
+error" if passed to \fBpcre2_get_error_message()\fP.
+.P
+The value returned in \fIerroroffset\fP is an indication of where in the
+pattern an error occurred. When there is no error, zero is returned. A non-zero
+value is not necessarily the furthest point in the pattern that was read. For
+example, after the error "lookbehind assertion is not fixed length", the error
+offset points to the start of the failing assertion. For an invalid UTF-8 or
+UTF-16 string, the offset is that of the first code unit of the failing
+character.
+.P
+Some errors are not detected until the whole pattern has been scanned; in these
+cases, the offset passed back is the length of the pattern. Note that the
+offset is in code units, not characters, even in a UTF mode. It may sometimes
+point into the middle of a UTF-8 or UTF-16 character.
+.P
+This code fragment shows a typical straightforward call to
+\fBpcre2_compile()\fP:
+.sp
+ pcre2_code *re;
+ PCRE2_SIZE erroffset;
+ int errorcode;
+ re = pcre2_compile(
+ "^A.*Z", /* the pattern */
+ PCRE2_ZERO_TERMINATED, /* the pattern is zero-terminated */
+ 0, /* default options */
+ &errorcode, /* for error code */
+ &erroffset, /* for error offset */
+ NULL); /* no compile context */
+.sp
+.
+.
+.SS "Main compile options"
+.rs
+.sp
+The following names for option bits are defined in the \fBpcre2.h\fP header
+file:
+.sp
+ PCRE2_ANCHORED
+.sp
+If this bit is set, the pattern is forced to be "anchored", that is, it is
+constrained to match only at the first matching point in the string that is
+being searched (the "subject string"). This effect can also be achieved by
+appropriate constructs in the pattern itself, which is the only way to do it in
+Perl.
+.sp
+ PCRE2_ALLOW_EMPTY_CLASS
+.sp
+By default, for compatibility with Perl, a closing square bracket that
+immediately follows an opening one is treated as a data character for the
+class. When PCRE2_ALLOW_EMPTY_CLASS is set, it terminates the class, which
+therefore contains no characters and so can never match.
+.sp
+ PCRE2_ALT_BSUX
+.sp
+This option request alternative handling of three escape sequences, which
+makes PCRE2's behaviour more like ECMAscript (aka JavaScript). When it is set:
+.P
+(1) \eU matches an upper case "U" character; by default \eU causes a compile
+time error (Perl uses \eU to upper case subsequent characters).
+.P
+(2) \eu matches a lower case "u" character unless it is followed by four
+hexadecimal digits, in which case the hexadecimal number defines the code point
+to match. By default, \eu causes a compile time error (Perl uses it to upper
+case the following character).
+.P
+(3) \ex matches a lower case "x" character unless it is followed by two
+hexadecimal digits, in which case the hexadecimal number defines the code point
+to match. By default, as in Perl, a hexadecimal number is always expected after
+\ex, but it may have one or two digits.
+.P
+ECMAscript 6 added additional functionality to \eu. This can be accessed using
+the PCRE2_EXTRA_ALT_BSUX extra option (see "Extra compile options"
+.\" HTML
+.\"
+below).
+.\"
+Note that this alternative escape handling applies only to patterns. Neither of
+these options affects the processing of replacement strings passed to
+\fBpcre2_substitute()\fP.
+.sp
+ PCRE2_ALT_CIRCUMFLEX
+.sp
+In multiline mode (when PCRE2_MULTILINE is set), the circumflex metacharacter
+matches at the start of the subject (unless PCRE2_NOTBOL is set), and also
+after any internal newline. However, it does not match after a newline at the
+end of the subject, for compatibility with Perl. If you want a multiline
+circumflex also to match after a terminating newline, you must set
+PCRE2_ALT_CIRCUMFLEX.
+.sp
+ PCRE2_ALT_EXTENDED_CLASS
+.sp
+Alters the parsing of character classes to follow the extended syntax
+described by Unicode UTS#18. The PCRE2_ALT_EXTENDED_CLASS option has no impact
+on the behaviour of the Perl-specific "(?[...])" syntax for extended classes,
+but instead enables the alternative syntax of extended class behaviour inside
+ordinary "[...]" character classes. See the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+documentation for details of the character classes supported.
+.sp
+ PCRE2_ALT_VERBNAMES
+.sp
+By default, for compatibility with Perl, the name in any verb sequence such as
+(*MARK:NAME) is any sequence of characters that does not include a closing
+parenthesis. The name is not processed in any way, and it is not possible to
+include a closing parenthesis in the name. However, if the PCRE2_ALT_VERBNAMES
+option is set, normal backslash processing is applied to verb names and only an
+unescaped closing parenthesis terminates the name. A closing parenthesis can be
+included in a name either as \e) or between \eQ and \eE. If the PCRE2_EXTENDED
+or PCRE2_EXTENDED_MORE option is set with PCRE2_ALT_VERBNAMES, unescaped
+white space in verb names is skipped and #-comments are recognized, exactly as
+in the rest of the pattern.
+.sp
+ PCRE2_AUTO_CALLOUT
+.sp
+If this bit is set, \fBpcre2_compile()\fP automatically inserts callout items,
+all with number 255, before each pattern item, except immediately before or
+after an explicit callout in the pattern. For discussion of the callout
+facility, see the
+.\" HREF
+\fBpcre2callout\fP
+.\"
+documentation.
+.sp
+ PCRE2_CASELESS
+.sp
+If this bit is set, letters in the pattern match both upper and lower case
+letters in the subject. It is equivalent to Perl's /i option, and it can be
+changed within a pattern by a (?i) option setting. If either PCRE2_UTF or
+PCRE2_UCP is set, Unicode properties are used for all characters with more than
+one other case, and for all characters whose code points are greater than
+U+007F.
+.P
+Note that there are two ASCII characters, K and S, that, in addition to
+their lower case ASCII equivalents, are case-equivalent with U+212A (Kelvin
+sign) and U+017F (long S) respectively. If you do not want this case
+equivalence, you can suppress it by setting PCRE2_EXTRA_CASELESS_RESTRICT.
+.P
+One language family, Turkish and Azeri, has its own case-insensitivity rules,
+which can be selected by setting PCRE2_EXTRA_TURKISH_CASING. This alters the
+behaviour of the 'i', 'I', U+0130 (capital I with dot above), and U+0131
+(small dotless i) characters.
+.P
+For lower valued characters with only one other case, a lookup table is used
+for speed. When neither PCRE2_UTF nor PCRE2_UCP is set, a lookup table is used
+for all code points less than 256, and higher code points (available only in
+16-bit or 32-bit mode) are treated as not having another case.
+.P
+From release 10.45 PCRE2_CASELESS also affects what some of the letter-related
+Unicode property escapes (\ep and \eP) match. The properties Lu (upper case
+letter), Ll (lower case letter), and Lt (title case letter) are all treated as
+LC (cased letter) when PCRE2_CASELESS is set.
+.sp
+ PCRE2_DOLLAR_ENDONLY
+.sp
+If this bit is set, a dollar metacharacter in the pattern matches only at the
+end of the subject string. Without this option, a dollar also matches
+immediately before a newline at the end of the string (but not before any other
+newlines). The PCRE2_DOLLAR_ENDONLY option is ignored if PCRE2_MULTILINE is
+set. There is no equivalent to this option in Perl, and no way to set it within
+a pattern.
+.sp
+ PCRE2_DOTALL
+.sp
+If this bit is set, a dot metacharacter in the pattern matches any character,
+including one that indicates a newline. However, it only ever matches one
+character, even if newlines are coded as CRLF. Without this option, a dot does
+not match when the current position in the subject is at a newline. This option
+is equivalent to Perl's /s option, and it can be changed within a pattern by a
+(?s) option setting. A negative class such as [^a] always matches newline
+characters, and the \eN escape sequence always matches a non-newline character,
+independent of the setting of PCRE2_DOTALL.
+.sp
+ PCRE2_DUPNAMES
+.sp
+If this bit is set, names used to identify capture groups need not be unique.
+This can be helpful for certain types of pattern when it is known that only one
+instance of the named group can ever be matched. There are more details of
+named capture groups below; see also the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+documentation.
+.sp
+ PCRE2_ENDANCHORED
+.sp
+If this bit is set, the end of any pattern match must be right at the end of
+the string being searched (the "subject string"). If the pattern match
+succeeds by reaching (*ACCEPT), but does not reach the end of the subject, the
+match fails at the current starting point. For unanchored patterns, a new match
+is then tried at the next starting point. However, if the match succeeds by
+reaching the end of the pattern, but not the end of the subject, backtracking
+occurs and an alternative match may be found. Consider these two patterns:
+.sp
+ .(*ACCEPT)|..
+ .|..
+.sp
+If matched against "abc" with PCRE2_ENDANCHORED set, the first matches "c"
+whereas the second matches "bc". The effect of PCRE2_ENDANCHORED can also be
+achieved by appropriate constructs in the pattern itself, which is the only way
+to do it in Perl.
+.P
+For DFA matching with \fBpcre2_dfa_match()\fP, PCRE2_ENDANCHORED applies only
+to the first (that is, the longest) matched string. Other parallel matches,
+which are necessarily substrings of the first one, must obviously end before
+the end of the subject.
+.sp
+ PCRE2_EXTENDED
+.sp
+If this bit is set, most white space characters in the pattern are totally
+ignored except when escaped, inside a character class, or inside a \eQ...\eE
+sequence. However, white space is not allowed within sequences such as (?> that
+introduce various parenthesized groups, nor within numerical quantifiers such
+as {1,3}. Ignorable white space is permitted between an item and a following
+quantifier and between a quantifier and a following + that indicates
+possessiveness. PCRE2_EXTENDED is equivalent to Perl's /x option, and it can be
+changed within a pattern by a (?x) option setting.
+.P
+When PCRE2 is compiled without Unicode support, PCRE2_EXTENDED recognizes as
+white space only those characters with code points less than 256 that are
+flagged as white space in its low-character table. The table is normally
+created by
+.\" HREF
+\fBpcre2_maketables()\fP,
+.\"
+which uses the \fBisspace()\fP function to identify space characters. In most
+ASCII environments, the relevant characters are those with code points 0x0009
+(tab), 0x000A (linefeed), 0x000B (vertical tab), 0x000C (formfeed), 0x000D
+(carriage return), and 0x0020 (space).
+.P
+When PCRE2 is compiled with Unicode support, in addition to these characters,
+five more Unicode "Pattern White Space" characters are recognized by
+PCRE2_EXTENDED. These are U+0085 (next line), U+200E (left-to-right mark),
+U+200F (right-to-left mark), U+2028 (line separator), and U+2029 (paragraph
+separator). This set of characters is the same as recognized by Perl's /x
+option. Note that the horizontal and vertical space characters that are matched
+by the \eh and \ev escapes in patterns are a much bigger set.
+.P
+As well as ignoring most white space, PCRE2_EXTENDED also causes characters
+between an unescaped # outside a character class and the next newline,
+inclusive, to be ignored, which makes it possible to include comments inside
+complicated patterns. Note that the end of this type of comment is a literal
+newline sequence in the pattern; escape sequences that happen to represent a
+newline do not count.
+.P
+Which characters are interpreted as newlines can be specified by a setting in
+the compile context that is passed to \fBpcre2_compile()\fP or by a special
+sequence at the start of the pattern, as described in the section entitled
+.\" HTML
+.\"
+"Newline conventions"
+.\"
+in the \fBpcre2pattern\fP documentation. A default is defined when PCRE2 is
+built.
+.sp
+ PCRE2_EXTENDED_MORE
+.sp
+This option has the effect of PCRE2_EXTENDED, but, in addition, unescaped space
+and horizontal tab characters are ignored inside a character class. Note: only
+these two characters are ignored, not the full set of pattern white space
+characters that are ignored outside a character class. PCRE2_EXTENDED_MORE is
+equivalent to Perl's /xx option, and it can be changed within a pattern by a
+(?xx) option setting.
+.sp
+ PCRE2_FIRSTLINE
+.sp
+If this option is set, the start of an unanchored pattern match must be before
+or at the first newline in the subject string following the start of matching,
+though the matched text may continue over the newline. If \fIstartoffset\fP is
+non-zero, the limiting newline is not necessarily the first newline in the
+subject. For example, if the subject string is "abc\enxyz" (where \en
+represents a single-character newline) a pattern match for "yz" succeeds with
+PCRE2_FIRSTLINE if \fIstartoffset\fP is greater than 3. See also
+PCRE2_USE_OFFSET_LIMIT, which provides a more general limiting facility. If
+PCRE2_FIRSTLINE is set with an offset limit, a match must occur in the first
+line and also within the offset limit. In other words, whichever limit comes
+first is used. This option has no effect for anchored patterns.
+.sp
+ PCRE2_LITERAL
+.sp
+If this option is set, all meta-characters in the pattern are disabled, and it
+is treated as a literal string. Matching literal strings with a regular
+expression engine is not the most efficient way of doing it. If you are doing a
+lot of literal matching and are worried about efficiency, you should consider
+using other approaches. The only other main options that are allowed with
+PCRE2_LITERAL are: PCRE2_ANCHORED, PCRE2_ENDANCHORED, PCRE2_AUTO_CALLOUT,
+PCRE2_CASELESS, PCRE2_FIRSTLINE, PCRE2_MATCH_INVALID_UTF,
+PCRE2_NO_START_OPTIMIZE, PCRE2_NO_UTF_CHECK, PCRE2_UTF, and
+PCRE2_USE_OFFSET_LIMIT. The extra options PCRE2_EXTRA_MATCH_LINE and
+PCRE2_EXTRA_MATCH_WORD are also supported. Any other options cause an error.
+.sp
+ PCRE2_MATCH_INVALID_UTF
+.sp
+This option forces PCRE2_UTF (see below) and also enables support for matching
+by \fBpcre2_match()\fP in subject strings that contain invalid UTF sequences.
+Note, however, that the 16-bit and 32-bit PCRE2 libraries process strings as
+sequences of uint16_t or uint32_t code points. They cannot find valid UTF
+sequences within an arbitrary string of bytes unless such sequences are
+suitably aligned. This facility is not supported for DFA matching. For details,
+see the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+documentation.
+.sp
+ PCRE2_MATCH_UNSET_BACKREF
+.sp
+If this option is set, a backreference to an unset capture group matches an
+empty string (by default this causes the current matching alternative to fail).
+A pattern such as (\e1)(a) succeeds when this option is set (assuming it can
+find an "a" in the subject), whereas it fails by default, for Perl
+compatibility. Setting this option makes PCRE2 behave more like ECMAscript (aka
+JavaScript).
+.sp
+ PCRE2_MULTILINE
+.sp
+By default, for the purposes of matching "start of line" and "end of line",
+PCRE2 treats the subject string as consisting of a single line of characters,
+even if it actually contains newlines. The "start of line" metacharacter (^)
+matches only at the start of the string, and the "end of line" metacharacter
+($) matches only at the end of the string, or before a terminating newline
+(except when PCRE2_DOLLAR_ENDONLY is set). Note, however, that unless
+PCRE2_DOTALL is set, the "any character" metacharacter (.) does not match at a
+newline. This behaviour (for ^, $, and dot) is the same as Perl.
+.P
+When PCRE2_MULTILINE it is set, the "start of line" and "end of line"
+constructs match immediately following or immediately before internal newlines
+in the subject string, respectively, as well as at the very start and end. This
+is equivalent to Perl's /m option, and it can be changed within a pattern by a
+(?m) option setting. Note that the "start of line" metacharacter does not match
+after a newline at the end of the subject, for compatibility with Perl.
+However, you can change this by setting the PCRE2_ALT_CIRCUMFLEX option. If
+there are no newlines in a subject string, or no occurrences of ^ or $ in a
+pattern, setting PCRE2_MULTILINE has no effect.
+.sp
+ PCRE2_NEVER_BACKSLASH_C
+.sp
+This option locks out the use of \eC in the pattern that is being compiled.
+This escape can cause unpredictable behaviour in UTF-8 or UTF-16 modes, because
+it may leave the current matching point in the middle of a multi-code-unit
+character. This option may be useful in applications that process patterns from
+external sources. Note that there is also a build-time option that permanently
+locks out the use of \eC.
+.sp
+ PCRE2_NEVER_UCP
+.sp
+This option locks out the use of Unicode properties for handling \eB, \eb, \eD,
+\ed, \eS, \es, \eW, \ew, and some of the POSIX character classes, as described
+for the PCRE2_UCP option below. In particular, it prevents the creator of the
+pattern from enabling this facility by starting the pattern with (*UCP). This
+option may be useful in applications that process patterns from external
+sources. The option combination PCRE2_UCP and PCRE2_NEVER_UCP causes an error.
+.sp
+ PCRE2_NEVER_UTF
+.sp
+This option locks out interpretation of the pattern as UTF-8, UTF-16, or
+UTF-32, depending on which library is in use. In particular, it prevents the
+creator of the pattern from switching to UTF interpretation by starting the
+pattern with (*UTF). This option may be useful in applications that process
+patterns from external sources. The combination of PCRE2_UTF and
+PCRE2_NEVER_UTF causes an error.
+.sp
+ PCRE2_NO_AUTO_CAPTURE
+.sp
+If this option is set, it disables the use of numbered capturing parentheses in
+the pattern. Any opening parenthesis that is not followed by ? behaves as if it
+were followed by ?: but named parentheses can still be used for capturing (and
+they acquire numbers in the usual way). This is the same as Perl's /n option.
+Note that, when this option is set, references to capture groups
+(backreferences or recursion/subroutine calls) may only refer to named groups,
+though the reference can be by name or by number.
+.sp
+ PCRE2_NO_AUTO_POSSESS
+.sp
+If this (deprecated) option is set, it disables "auto-possessification", which
+is an optimization that, for example, turns a+b into a++b in order to avoid
+backtracks into a+ that can never be successful. However, if callouts are in
+use, auto-possessification means that some callouts are never taken. You can
+set this option if you want the matching functions to do a full unoptimized
+search and run all the callouts, but it is mainly provided for testing
+purposes.
+.P
+If a compile context is available, it is recommended to use
+\fBpcre2_set_optimize()\fP with the \fIdirective\fP PCRE2_AUTO_POSSESS_OFF rather
+than the compile option PCRE2_NO_AUTO_POSSESS. Note that PCRE2_NO_AUTO_POSSESS
+takes precedence over the \fBpcre2_set_optimize()\fP optimization directives
+PCRE2_AUTO_POSSESS and PCRE2_AUTO_POSSESS_OFF.
+.sp
+ PCRE2_NO_DOTSTAR_ANCHOR
+.sp
+If this (deprecated) option is set, it disables an optimization that is applied
+when .* is the first significant item in a top-level branch of a pattern, and
+all the other branches also start with .* or with \eA or \eG or ^. The
+optimization is automatically disabled for .* if it is inside an atomic group
+or a capture group that is the subject of a backreference, or if the pattern
+contains (*PRUNE) or (*SKIP). When the optimization is not disabled, such a
+pattern is automatically anchored if PCRE2_DOTALL is set for all the .* items
+and PCRE2_MULTILINE is not set for any ^ items. Otherwise, the fact that any
+match must start either at the start of the subject or following a newline is
+remembered. Like other optimizations, this can cause callouts to be skipped.
+(If a compile context is available, it is recommended to use
+\fBpcre2_set_optimize()\fP with the \fIdirective\fP PCRE2_DOTSTAR_ANCHOR_OFF
+instead.)
+.sp
+ PCRE2_NO_START_OPTIMIZE
+.sp
+This is an option whose main effect is at matching time. It does not change
+what \fBpcre2_compile()\fP generates, but it does affect the output of the JIT
+compiler. Setting this option is equivalent to calling
+\fBpcre2_set_optimize()\fP with the \fIdirective\fP parameter set to
+PCRE2_START_OPTIMIZE_OFF.
+.P
+There are a number of optimizations that may occur at the start of a match, in
+order to speed up the process. For example, if it is known that an unanchored
+match must start with a specific code unit value, the matching code searches
+the subject for that value, and fails immediately if it cannot find it, without
+actually running the main matching function. The start-up optimizations are
+in effect a pre-scan of the subject that takes place before the pattern is run.
+.P
+Disabling the start-up optimizations may cause performance to suffer. However,
+this may be desirable for patterns which contain callouts or items such as
+(*COMMIT) and (*MARK). See the above description of PCRE2_START_OPTIMIZE_OFF
+for further details.
+.sp
+ PCRE2_NO_UTF_CHECK
+.sp
+When PCRE2_UTF is set, the validity of the pattern as a UTF string is
+automatically checked. There are discussions about the validity of
+.\" HTML
+.\"
+UTF-8 strings,
+.\"
+.\" HTML
+.\"
+UTF-16 strings,
+.\"
+and
+.\" HTML
+.\"
+UTF-32 strings
+.\"
+in the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+document. If an invalid UTF sequence is found, \fBpcre2_compile()\fP returns a
+negative error code.
+.P
+If you know that your pattern is a valid UTF string, and you want to skip this
+check for performance reasons, you can set the PCRE2_NO_UTF_CHECK option. When
+it is set, the effect of passing an invalid UTF string as a pattern is
+undefined. It may cause your program to crash or loop.
+.P
+Note that this option can also be passed to \fBpcre2_match()\fP and
+\fBpcre2_dfa_match()\fP, to suppress UTF validity checking of the subject
+string.
+.P
+Note also that setting PCRE2_NO_UTF_CHECK at compile time does not disable the
+error that is given if an escape sequence for an invalid Unicode code point is
+encountered in the pattern. In particular, the so-called "surrogate" code
+points (0xd800 to 0xdfff) are invalid. If you want to allow escape sequences
+such as \ex{d800} you can set the PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES extra
+option, as described in the section entitled "Extra compile options"
+.\" HTML
+.\"
+below.
+.\"
+However, this is possible only in UTF-8 and UTF-32 modes, because these values
+are not representable in UTF-16.
+.sp
+ PCRE2_UCP
+.sp
+This option has two effects. Firstly, it change the way PCRE2 processes \eB,
+\eb, \eD, \ed, \eS, \es, \eW, \ew, and some of the POSIX character classes. By
+default, only ASCII characters are recognized, but if PCRE2_UCP is set, Unicode
+properties are used to classify characters. There are some PCRE2_EXTRA
+options (see below) that add finer control to this behaviour. More details are
+given in the section on
+.\" HTML
+.\"
+generic character types
+.\"
+in the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+page.
+.P
+The second effect of PCRE2_UCP is to force the use of Unicode properties for
+upper/lower casing operations, even when PCRE2_UTF is not set. This makes it
+possible to process strings in the 16-bit UCS-2 code. This option is available
+only if PCRE2 has been compiled with Unicode support (which is the default).
+.P
+The PCRE2_EXTRA_CASELESS_RESTRICT option (see above) restricts caseless
+matching such that ASCII characters match only ASCII characters and non-ASCII
+characters match only non-ASCII characters. The PCRE2_EXTRA_TURKISH_CASING
+option (see above) alters the matching of the 'i' characters to follow their
+behaviour in Turkish and Azeri languages. For further details on
+PCRE2_EXTRA_CASELESS_RESTRICT and PCRE2_EXTRA_TURKISH_CASING, see the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+page.
+.sp
+ PCRE2_UNGREEDY
+.sp
+This option inverts the "greediness" of the quantifiers so that they are not
+greedy by default, but become greedy if followed by "?". It is not compatible
+with Perl. It can also be set by a (?U) option setting within the pattern.
+.sp
+ PCRE2_USE_OFFSET_LIMIT
+.sp
+This option must be set for \fBpcre2_compile()\fP if
+\fBpcre2_set_offset_limit()\fP is going to be used to set a non-default offset
+limit in a match context for matches that use this pattern. An error is
+generated if an offset limit is set without this option. For more details, see
+the description of \fBpcre2_set_offset_limit()\fP in the
+.\" HTML
+.\"
+section
+.\"
+that describes match contexts. See also the PCRE2_FIRSTLINE
+option above.
+.sp
+ PCRE2_UTF
+.sp
+This option causes PCRE2 to regard both the pattern and the subject strings
+that are subsequently processed as strings of UTF characters instead of
+single-code-unit strings. It is available when PCRE2 is built to include
+Unicode support (which is the default). If Unicode support is not available,
+the use of this option provokes an error. Details of how PCRE2_UTF changes the
+behaviour of PCRE2 are given in the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+page. In particular, note that it changes the way PCRE2_CASELESS works.
+.
+.
+.\" HTML
+.SS "Extra compile options"
+.rs
+.sp
+The option bits that can be set in a compile context by calling the
+\fBpcre2_set_compile_extra_options()\fP function are as follows:
+.sp
+ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK
+.sp
+Since release 10.38 PCRE2 has forbidden the use of \eK within lookaround
+assertions, following Perl's lead. This option is provided to re-enable the
+previous behaviour (act in positive lookarounds, ignore in negative ones) in
+case anybody is relying on it.
+.sp
+ PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES
+.sp
+This option applies when compiling a pattern in UTF-8 or UTF-32 mode. It is
+forbidden in UTF-16 mode, and ignored in non-UTF modes. Unicode "surrogate"
+code points in the range 0xd800 to 0xdfff are used in pairs in UTF-16 to encode
+code points with values in the range 0x10000 to 0x10ffff. The surrogates cannot
+therefore be represented in UTF-16. They can be represented in UTF-8 and
+UTF-32, but are defined as invalid code points, and cause errors if encountered
+in a UTF-8 or UTF-32 string that is being checked for validity by PCRE2.
+.P
+These values also cause errors if encountered in escape sequences such as
+\ex{d912} within a pattern. However, it seems that some applications, when
+using PCRE2 to check for unwanted characters in UTF-8 strings, explicitly test
+for the surrogates using escape sequences. The PCRE2_NO_UTF_CHECK option does
+not disable the error that occurs, because it applies only to the testing of
+input strings for UTF validity.
+.P
+If the extra option PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES is set, surrogate code
+point values in UTF-8 and UTF-32 patterns no longer provoke errors and are
+incorporated in the compiled pattern. However, they can only match subject
+characters if the matching function is called with PCRE2_NO_UTF_CHECK set.
+.sp
+ PCRE2_EXTRA_ALT_BSUX
+.sp
+The original option PCRE2_ALT_BSUX causes PCRE2 to process \eU, \eu, and \ex in
+the way that ECMAscript (aka JavaScript) does. Additional functionality was
+defined by ECMAscript 6; setting PCRE2_EXTRA_ALT_BSUX has the effect of
+PCRE2_ALT_BSUX, but in addition it recognizes \eu{hhh..} as a hexadecimal
+character code, where hhh.. is any number of hexadecimal digits.
+.sp
+ PCRE2_EXTRA_ASCII_BSD
+.sp
+This option forces \ed to match only ASCII digits, even when PCRE2_UCP is set.
+It can be changed within a pattern by means of the (?aD) option setting.
+.sp
+ PCRE2_EXTRA_ASCII_BSS
+.sp
+This option forces \es to match only ASCII space characters, even when
+PCRE2_UCP is set. It can be changed within a pattern by means of the (?aS)
+option setting.
+.sp
+ PCRE2_EXTRA_ASCII_BSW
+.sp
+This option forces \ew to match only ASCII word characters, even when PCRE2_UCP
+is set. It can be changed within a pattern by means of the (?aW) option
+setting.
+.sp
+ PCRE2_EXTRA_ASCII_DIGIT
+.sp
+This option forces the POSIX character classes [:digit:] and [:xdigit:] to
+match only ASCII digits, even when PCRE2_UCP is set. It can be changed within
+a pattern by means of the (?aT) option setting.
+.sp
+ PCRE2_EXTRA_ASCII_POSIX
+.sp
+This option forces all the POSIX character classes, including [:digit:] and
+[:xdigit:], to match only ASCII characters, even when PCRE2_UCP is set. It can
+be changed within a pattern by means of the (?aP) option setting, but note that
+this also sets PCRE2_EXTRA_ASCII_DIGIT in order to ensure that (?-aP) unsets
+all ASCII restrictions for POSIX classes.
+.sp
+ PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL
+.sp
+This is a dangerous option. Use with care. By default, an unrecognized escape
+such as \ej or a malformed one such as \ex{2z} causes a compile-time error when
+detected by \fBpcre2_compile()\fP. Perl is somewhat inconsistent in handling
+such items: for example, \ej is treated as a literal "j", and non-hexadecimal
+digits in \ex{} are just ignored, though warnings are given in both cases if
+Perl's warning switch is enabled. However, a malformed octal number after \eo{
+always causes an error in Perl.
+.P
+If the PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL extra option is passed to
+\fBpcre2_compile()\fP, all unrecognized or malformed escape sequences are
+treated as single-character escapes. For example, \ej is a literal "j" and
+\ex{2z} is treated as the literal string "x{2z}". Setting this option means
+that typos in patterns may go undetected and have unexpected results. Also note
+that a sequence such as [\eN{] is interpreted as a malformed attempt at
+[\eN{...}] and so is treated as [N{] whereas [\eN] gives an error because an
+unqualified \eN is a valid escape sequence but is not supported in a character
+class. To reiterate: this is a dangerous option. Use with great care.
+.sp
+ PCRE2_EXTRA_CASELESS_RESTRICT
+.sp
+When either PCRE2_UCP or PCRE2_UTF is set, caseless matching follows Unicode
+rules, which allow for more than two cases per character. There are two
+case-equivalent character sets that contain both ASCII and non-ASCII
+characters. The ASCII letter S is case-equivalent to U+017f (long S) and the
+ASCII letter K is case-equivalent to U+212a (Kelvin sign). This option disables
+recognition of case-equivalences that cross the ASCII/non-ASCII boundary. In a
+caseless match, both characters must either be ASCII or non-ASCII. The option
+can be changed within a pattern by the (*CASELESS_RESTRICT) or (?r) option
+settings.
+.sp
+ PCRE2_EXTRA_ESCAPED_CR_IS_LF
+.sp
+There are some legacy applications where the escape sequence \er in a pattern
+is expected to match a newline. If this option is set, \er in a pattern is
+converted to \en so that it matches a LF (linefeed) instead of a CR (carriage
+return) character. The option does not affect a literal CR in the pattern, nor
+does it affect CR specified as an explicit code point such as \ex{0D}.
+.sp
+ PCRE2_EXTRA_MATCH_LINE
+.sp
+This option is provided for use by the \fB-x\fP option of \fBpcre2grep\fP. It
+causes the pattern only to match complete lines. This is achieved by
+automatically inserting the code for "^(?:" at the start of the compiled
+pattern and ")$" at the end. Thus, when PCRE2_MULTILINE is set, the matched
+line may be in the middle of the subject string. This option can be used with
+PCRE2_LITERAL.
+.sp
+ PCRE2_EXTRA_MATCH_WORD
+.sp
+This option is provided for use by the \fB-w\fP option of \fBpcre2grep\fP. It
+causes the pattern only to match strings that have a word boundary at the start
+and the end. This is achieved by automatically inserting the code for "\eb(?:"
+at the start of the compiled pattern and ")\eb" at the end. The option may be
+used with PCRE2_LITERAL. However, it is ignored if PCRE2_EXTRA_MATCH_LINE is
+also set.
+.sp
+ PCRE2_EXTRA_NO_BS0
+.sp
+If this option is set (note that its final character is the digit 0) it locks
+out the use of the sequence \e0 unless at least one more octal digit follows.
+.sp
+ PCRE2_EXTRA_PYTHON_OCTAL
+.sp
+If this option is set, PCRE2 follows Python's rules for interpreting octal
+escape sequences. The rules for handling sequences such as \e14, which could
+be an octal number or a back reference are different. Details are given in the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+documentation.
+.sp
+ PCRE2_EXTRA_NEVER_CALLOUT
+.sp
+If this option is set, PCRE2 treats callouts in the pattern as a syntax error,
+returning PCRE2_ERROR_CALLOUT_CALLER_DISABLED. This is useful if the application
+knows that a callout will not be provided to \fBpcre2_match()\fP, so that
+callouts in the pattern are not silently ignored.
+.sp
+ PCRE2_EXTRA_TURKISH_CASING
+.sp
+This option alters case-equivalence of the 'i' letters to follow the
+alphabet used by Turkish and Azeri languages. The option can be changed within
+a pattern by the (*TURKISH_CASING) start-of-pattern setting. Either the UTF or
+UCP options must be set. In the 8-bit library, UTF must be set. This option
+cannot be combined with PCRE2_EXTRA_CASELESS_RESTRICT.
+.
+.
+.\" HTML
+.SH "JUST-IN-TIME (JIT) COMPILATION"
+.rs
+.sp
+.nf
+.B int pcre2_jit_compile(pcre2_code *\fIcode\fP, uint32_t \fIoptions\fP);
+.sp
+.B int pcre2_jit_match(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
+.B " PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
+.B " uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
+.B " pcre2_match_context *\fImcontext\fP);"
+.sp
+.B void pcre2_jit_free_unused_memory(pcre2_general_context *\fIgcontext\fP);
+.sp
+.B pcre2_jit_stack *pcre2_jit_stack_create(size_t \fIstartsize\fP,
+.B " size_t \fImaxsize\fP, pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B void pcre2_jit_stack_assign(pcre2_match_context *\fImcontext\fP,
+.B " pcre2_jit_callback \fIcallback_function\fP, void *\fIcallback_data\fP);"
+.sp
+.B void pcre2_jit_stack_free(pcre2_jit_stack *\fIjit_stack\fP);
+.fi
+.P
+These functions provide support for JIT compilation, which, if the just-in-time
+compiler is available, further processes a compiled pattern into machine code
+that executes much faster than the \fBpcre2_match()\fP interpretive matching
+function. Full details are given in the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+documentation.
+.P
+JIT compilation is a heavyweight optimization. It can take some time for
+patterns to be analyzed, and for one-off matches and simple patterns the
+benefit of faster execution might be offset by a much slower compilation time.
+Most (but not all) patterns can be optimized by the JIT compiler.
+.
+.
+.\" HTML
+.SH "LOCALE SUPPORT"
+.rs
+.sp
+.nf
+.B const uint8_t *pcre2_maketables(pcre2_general_context *\fIgcontext\fP);
+.sp
+.B void pcre2_maketables_free(pcre2_general_context *\fIgcontext\fP,
+.B " const uint8_t *\fItables\fP);"
+.fi
+.P
+PCRE2 handles caseless matching, and determines whether characters are letters,
+digits, or whatever, by reference to a set of tables, indexed by character code
+point. However, this applies only to characters whose code points are less than
+256. By default, higher-valued code points never match escapes such as \ew or
+\ed.
+.P
+When PCRE2 is built with Unicode support (the default), certain Unicode
+character properties can be tested with \ep and \eP, or, alternatively, the
+PCRE2_UCP option can be set when a pattern is compiled; this causes \ew and
+friends to use Unicode property support instead of the built-in tables.
+PCRE2_UCP also causes upper/lower casing operations on characters with code
+points greater than 127 to use Unicode properties. These effects apply even
+when PCRE2_UTF is not set. There are, however, some PCRE2_EXTRA options (see
+above) that can be used to modify or suppress them.
+.P
+The use of locales with Unicode is discouraged. If you are handling characters
+with code points greater than 127, you should either use Unicode support, or
+use locales, but not try to mix the two.
+.P
+PCRE2 contains a built-in set of character tables that are used by default.
+These are sufficient for many applications. Normally, the internal tables
+recognize only ASCII characters. However, when PCRE2 is built, it is possible
+to cause the internal tables to be rebuilt in the default "C" locale of the
+local system, which may cause them to be different.
+.P
+The built-in tables can be overridden by tables supplied by the application
+that calls PCRE2. These may be created in a different locale from the default.
+As more and more applications change to using Unicode, the need for this locale
+support is expected to die away.
+.P
+External tables are built by calling the \fBpcre2_maketables()\fP function, in
+the relevant locale. The only argument to this function is a general context,
+which can be used to pass a custom memory allocator. If the argument is NULL,
+the system \fBmalloc()\fP is used. The result can be passed to
+\fBpcre2_compile()\fP as often as necessary, by creating a compile context and
+calling \fBpcre2_set_character_tables()\fP to set the tables pointer therein.
+.P
+For example, to build and use tables that are appropriate for the French locale
+(where accented characters with values greater than 127 are treated as
+letters), the following code could be used:
+.sp
+ setlocale(LC_CTYPE, "fr_FR");
+ tables = pcre2_maketables(NULL);
+ ccontext = pcre2_compile_context_create(NULL);
+ pcre2_set_character_tables(ccontext, tables);
+ re = pcre2_compile(..., ccontext);
+.sp
+The locale name "fr_FR" is used on Linux and other Unix-like systems; if you
+are using Windows, the name for the French locale is "french".
+.P
+The pointer that is passed (via the compile context) to \fBpcre2_compile()\fP
+is saved with the compiled pattern, and the same tables are used by the
+matching functions. Thus, for any single pattern, compilation and matching both
+happen in the same locale, but different patterns can be processed in different
+locales.
+.P
+It is the caller's responsibility to ensure that the memory containing the
+tables remains available while they are still in use. When they are no longer
+needed, you can discard them using \fBpcre2_maketables_free()\fP, which should
+pass as its first parameter the same global context that was used to create the
+tables.
+.
+.
+.SS "Saving locale tables"
+.rs
+.sp
+The tables described above are just a sequence of binary bytes, which makes
+them independent of hardware characteristics such as endianness or whether the
+processor is 32-bit or 64-bit. A copy of the result of \fBpcre2_maketables()\fP
+can therefore be saved in a file or elsewhere and re-used later, even in a
+different program or on another computer. The size of the tables (number of
+bytes) must be obtained by calling \fBpcre2_config()\fP with the
+PCRE2_CONFIG_TABLES_LENGTH option because \fBpcre2_maketables()\fP does not
+return this value. Note that the \fBpcre2_dftables\fP program, which is part of
+the PCRE2 build system, can be used stand-alone to create a file that contains
+a set of binary tables. See the
+.\" HTML
+.\"
+\fBpcre2build\fP
+.\"
+documentation for details.
+.
+.
+.\" HTML
+.SH "INFORMATION ABOUT A COMPILED PATTERN"
+.rs
+.sp
+.nf
+.B int pcre2_pattern_info(const pcre2 *\fIcode\fP, uint32_t \fIwhat\fP, void *\fIwhere\fP);
+.fi
+.P
+The \fBpcre2_pattern_info()\fP function returns general information about a
+compiled pattern. For information about callouts, see the
+.\" HTML
+.\"
+next section.
+.\"
+The first argument for \fBpcre2_pattern_info()\fP is a pointer to the compiled
+pattern. The second argument specifies which piece of information is required,
+and the third argument is a pointer to a variable to receive the data. If the
+third argument is NULL, the first argument is ignored, and the function returns
+the size in bytes of the variable that is required for the information
+requested. Otherwise, the yield of the function is zero for success, or one of
+the following negative numbers:
+.sp
+ PCRE2_ERROR_NULL the argument \fIcode\fP was NULL
+ PCRE2_ERROR_BADMAGIC the "magic number" was not found
+ PCRE2_ERROR_BADOPTION the value of \fIwhat\fP was invalid
+ PCRE2_ERROR_UNSET the requested field is not set
+.sp
+The "magic number" is placed at the start of each compiled pattern as a simple
+check against passing an arbitrary memory pointer. Here is a typical call of
+\fBpcre2_pattern_info()\fP, to obtain the length of the compiled pattern:
+.sp
+ int rc;
+ size_t length;
+ rc = pcre2_pattern_info(
+ re, /* result of pcre2_compile() */
+ PCRE2_INFO_SIZE, /* what is required */
+ &length); /* where to put the data */
+.sp
+The possible values for the second argument are defined in \fBpcre2.h\fP, and
+are as follows:
+.sp
+ PCRE2_INFO_ALLOPTIONS
+ PCRE2_INFO_ARGOPTIONS
+ PCRE2_INFO_EXTRAOPTIONS
+.sp
+Return copies of the pattern's options. The third argument should point to a
+\fBuint32_t\fP variable. PCRE2_INFO_ARGOPTIONS returns exactly the options that
+were passed to \fBpcre2_compile()\fP, whereas PCRE2_INFO_ALLOPTIONS returns
+the compile options as modified by any top-level (*XXX) option settings such as
+(*UTF) at the start of the pattern itself. PCRE2_INFO_EXTRAOPTIONS returns the
+extra options that were set in the compile context by calling the
+pcre2_set_compile_extra_options() function.
+.P
+For example, if the pattern /(*UTF)abc/ is compiled with the PCRE2_EXTENDED
+option, the result for PCRE2_INFO_ALLOPTIONS is PCRE2_EXTENDED and PCRE2_UTF.
+Option settings such as (?i) that can change within a pattern do not affect the
+result of PCRE2_INFO_ALLOPTIONS, even if they appear right at the start of the
+pattern. (This was different in some earlier releases.)
+.P
+A pattern compiled without PCRE2_ANCHORED is automatically anchored by PCRE2 if
+the first significant item in every top-level branch is one of the following:
+.sp
+ ^ unless PCRE2_MULTILINE is set
+ \eA always
+ \eG always
+ .* sometimes - see below
+.sp
+When .* is the first significant item, anchoring is possible only when all the
+following are true:
+.sp
+ .* is not in an atomic group
+.\" JOIN
+ .* is not in a capture group that is the subject
+ of a backreference
+ PCRE2_DOTALL is in force for .*
+ Neither (*PRUNE) nor (*SKIP) appears in the pattern
+ PCRE2_NO_DOTSTAR_ANCHOR is not set
+ Dotstar anchoring has not been disabled with PCRE2_DOTSTAR_ANCHOR_OFF
+.sp
+For patterns that are auto-anchored, the PCRE2_ANCHORED bit is set in the
+options returned for PCRE2_INFO_ALLOPTIONS.
+.sp
+ PCRE2_INFO_BACKREFMAX
+.sp
+Return the number of the highest backreference in the pattern. The third
+argument should point to a \fBuint32_t\fP variable. Named capture groups
+acquire numbers as well as names, and these count towards the highest
+backreference. Backreferences such as \e4 or \eg{12} match the captured
+characters of the given group, but in addition, the check that a capture
+group is set in a conditional group such as (?(3)a|b) is also a backreference.
+Zero is returned if there are no backreferences.
+.sp
+ PCRE2_INFO_BSR
+.sp
+The output is a uint32_t integer whose value indicates what character sequences
+the \eR escape sequence matches. A value of PCRE2_BSR_UNICODE means that \eR
+matches any Unicode line ending sequence; a value of PCRE2_BSR_ANYCRLF means
+that \eR matches only CR, LF, or CRLF.
+.sp
+ PCRE2_INFO_CAPTURECOUNT
+.sp
+Return the highest capture group number in the pattern. In patterns where (?|
+is not used, this is also the total number of capture groups. The third
+argument should point to a \fBuint32_t\fP variable.
+.sp
+ PCRE2_INFO_DEPTHLIMIT
+.sp
+If the pattern set a backtracking depth limit by including an item of the form
+(*LIMIT_DEPTH=nnnn) at the start, the value is returned. The third argument
+should point to a uint32_t integer. If no such value has been set, the call to
+\fBpcre2_pattern_info()\fP returns the error PCRE2_ERROR_UNSET. Note that this
+limit will only be used during matching if it is less than the limit set or
+defaulted by the caller of the match function.
+.sp
+ PCRE2_INFO_FIRSTBITMAP
+.sp
+In the absence of a single first code unit for a non-anchored pattern,
+\fBpcre2_compile()\fP may construct a 256-bit table that defines a fixed set of
+values for the first code unit in any match. For example, a pattern that starts
+with [abc] results in a table with three bits set. When code unit values
+greater than 255 are supported, the flag bit for 255 means "any code unit of
+value 255 or above". If such a table was constructed, a pointer to it is
+returned. Otherwise NULL is returned. The third argument should point to a
+\fBconst uint8_t *\fP variable.
+.sp
+ PCRE2_INFO_FIRSTCODETYPE
+.sp
+Return information about the first code unit of any matched string, for a
+non-anchored pattern. The third argument should point to a \fBuint32_t\fP
+variable. If there is a fixed first value, for example, the letter "c" from a
+pattern such as (cat|cow|coyote), 1 is returned, and the value can be retrieved
+using PCRE2_INFO_FIRSTCODEUNIT. If there is no fixed first value, but it is
+known that a match can occur only at the start of the subject or following a
+newline in the subject, 2 is returned. Otherwise, and for anchored patterns, 0
+is returned.
+.sp
+ PCRE2_INFO_FIRSTCODEUNIT
+.sp
+Return the value of the first code unit of any matched string for a pattern
+where PCRE2_INFO_FIRSTCODETYPE returns 1; otherwise return 0. The third
+argument should point to a \fBuint32_t\fP variable. In the 8-bit library, the
+value is always less than 256. In the 16-bit library the value can be up to
+0xffff. In the 32-bit library in UTF-32 mode the value can be up to 0x10ffff,
+and up to 0xffffffff when not using UTF-32 mode.
+.sp
+ PCRE2_INFO_FRAMESIZE
+.sp
+Return the size (in bytes) of the data frames that are used to remember
+backtracking positions when the pattern is processed by \fBpcre2_match()\fP
+without the use of JIT. The third argument should point to a \fBsize_t\fP
+variable. The frame size depends on the number of capturing parentheses in the
+pattern. Each additional capture group adds two PCRE2_SIZE variables.
+.sp
+ PCRE2_INFO_HASBACKSLASHC
+.sp
+Return 1 if the pattern contains any instances of \eC, otherwise 0. The third
+argument should point to a \fBuint32_t\fP variable.
+.sp
+ PCRE2_INFO_HASCRORLF
+.sp
+Return 1 if the pattern contains any explicit matches for CR or LF characters,
+otherwise 0. The third argument should point to a \fBuint32_t\fP variable. An
+explicit match is either a literal CR or LF character, or \er or \en or one of
+the equivalent hexadecimal or octal escape sequences.
+.sp
+ PCRE2_INFO_HEAPLIMIT
+.sp
+If the pattern set a heap memory limit by including an item of the form
+(*LIMIT_HEAP=nnnn) at the start, the value is returned. The third argument
+should point to a uint32_t integer. If no such value has been set, the call to
+\fBpcre2_pattern_info()\fP returns the error PCRE2_ERROR_UNSET. Note that this
+limit will only be used during matching if it is less than the limit set or
+defaulted by the caller of the match function.
+.sp
+ PCRE2_INFO_JCHANGED
+.sp
+Return 1 if the (?J) or (?-J) option setting is used in the pattern, otherwise
+0. The third argument should point to a \fBuint32_t\fP variable. (?J) and
+(?-J) set and unset the local PCRE2_DUPNAMES option, respectively.
+.sp
+ PCRE2_INFO_JITSIZE
+.sp
+If the compiled pattern was successfully processed by
+\fBpcre2_jit_compile()\fP, return the size of the JIT compiled code, otherwise
+return zero. The third argument should point to a \fBsize_t\fP variable.
+.sp
+ PCRE2_INFO_LASTCODETYPE
+.sp
+Returns 1 if there is a rightmost literal code unit that must exist in any
+matched string, other than at its start. The third argument should point to a
+\fBuint32_t\fP variable. If there is no such value, 0 is returned. When 1 is
+returned, the code unit value itself can be retrieved using
+PCRE2_INFO_LASTCODEUNIT. For anchored patterns, a last literal value is
+recorded only if it follows something of variable length. For example, for the
+pattern /^a\ed+z\ed+/ the returned value is 1 (with "z" returned from
+PCRE2_INFO_LASTCODEUNIT), but for /^a\edz\ed/ the returned value is 0.
+.sp
+ PCRE2_INFO_LASTCODEUNIT
+.sp
+Return the value of the rightmost literal code unit that must exist in any
+matched string, other than at its start, for a pattern where
+PCRE2_INFO_LASTCODETYPE returns 1. Otherwise, return 0. The third argument
+should point to a \fBuint32_t\fP variable.
+.sp
+ PCRE2_INFO_MATCHEMPTY
+.sp
+Return 1 if the pattern might match an empty string, otherwise 0. The third
+argument should point to a \fBuint32_t\fP variable. When a pattern contains
+recursive subroutine calls it is not always possible to determine whether or
+not it can match an empty string. PCRE2 takes a cautious approach and returns 1
+in such cases.
+.sp
+ PCRE2_INFO_MATCHLIMIT
+.sp
+If the pattern set a match limit by including an item of the form
+(*LIMIT_MATCH=nnnn) at the start, the value is returned. The third argument
+should point to a uint32_t integer. If no such value has been set, the call to
+\fBpcre2_pattern_info()\fP returns the error PCRE2_ERROR_UNSET. Note that this
+limit will only be used during matching if it is less than the limit set or
+defaulted by the caller of the match function.
+.sp
+ PCRE2_INFO_MAXLOOKBEHIND
+.sp
+A lookbehind assertion moves back a certain number of characters (not code
+units) when it starts to process each of its branches. This request returns the
+largest of these backward moves. The third argument should point to a uint32_t
+integer. The simple assertions \eb and \eB require a one-character lookbehind
+and cause PCRE2_INFO_MAXLOOKBEHIND to return 1 in the absence of anything
+longer. \eA also registers a one-character lookbehind, though it does not
+actually inspect the previous character.
+.P
+Note that this information is useful for multi-segment matching only
+if the pattern contains no nested lookbehinds. For example, the pattern
+(?<=a(?<=ba)c) returns a maximum lookbehind of 2, but when it is processed, the
+first lookbehind moves back by two characters, matches one character, then the
+nested lookbehind also moves back by two characters. This puts the matching
+point three characters earlier than it was at the start.
+PCRE2_INFO_MAXLOOKBEHIND is really only useful as a debugging tool. See the
+.\" HREF
+\fBpcre2partial\fP
+.\"
+documentation for a discussion of multi-segment matching.
+.sp
+ PCRE2_INFO_MINLENGTH
+.sp
+If a minimum length for matching subject strings was computed, its value is
+returned. Otherwise the returned value is 0. This value is not computed when
+PCRE2_NO_START_OPTIMIZE is set. The value is a number of characters, which in
+UTF mode may be different from the number of code units. The third argument
+should point to a \fBuint32_t\fP variable. The value is a lower bound to the
+length of any matching string. There may not be any strings of that length that
+do actually match, but every string that does match is at least that long.
+.sp
+ PCRE2_INFO_NAMECOUNT
+ PCRE2_INFO_NAMEENTRYSIZE
+ PCRE2_INFO_NAMETABLE
+.sp
+PCRE2 supports the use of named as well as numbered capturing parentheses. The
+names are just an additional way of identifying the parentheses, which still
+acquire numbers. Several convenience functions such as
+\fBpcre2_substring_get_byname()\fP are provided for extracting captured
+substrings by name. It is also possible to extract the data directly, by first
+converting the name to a number in order to access the correct pointers in the
+output vector (described with \fBpcre2_match()\fP below). To do the conversion,
+you need to use the name-to-number map, which is described by these three
+values.
+.P
+The map consists of a number of fixed-size entries. PCRE2_INFO_NAMECOUNT gives
+the number of entries, and PCRE2_INFO_NAMEENTRYSIZE gives the size of each
+entry in code units; both of these return a \fBuint32_t\fP value. The entry
+size depends on the length of the longest name.
+.P
+PCRE2_INFO_NAMETABLE returns a pointer to the first entry of the table. This is
+a PCRE2_SPTR pointer to a block of code units. In the 8-bit library, the first
+two bytes of each entry are the number of the capturing parenthesis, most
+significant byte first. In the 16-bit library, the pointer points to 16-bit
+code units, the first of which contains the parenthesis number. In the 32-bit
+library, the pointer points to 32-bit code units, the first of which contains
+the parenthesis number. The rest of the entry is the corresponding name, zero
+terminated.
+.P
+The names are in alphabetical order. If (?| is used to create multiple capture
+groups with the same number, as described in the
+.\" HTML
+.\"
+section on duplicate group numbers
+.\"
+in the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+page, the groups may be given the same name, but there is only one entry in the
+table. Different names for groups of the same number are not permitted.
+.P
+Duplicate names for capture groups with different numbers are permitted, but
+only if PCRE2_DUPNAMES is set. They appear in the table in the order in which
+they were found in the pattern. In the absence of (?| this is the order of
+increasing number; when (?| is used this is not necessarily the case because
+later capture groups may have lower numbers.
+.P
+As a simple example of the name/number table, consider the following pattern
+after compilation by the 8-bit library (assume PCRE2_EXTENDED is set, so white
+space - including newlines - is ignored):
+.sp
+.\" JOIN
+ (? (?(\ed\ed)?\ed\ed) -
+ (?\ed\ed) - (?\ed\ed) )
+.sp
+There are four named capture groups, so the table has four entries, and each
+entry in the table is eight bytes long. The table is as follows, with
+non-printing bytes shows in hexadecimal, and undefined bytes shown as ??:
+.sp
+ 00 01 d a t e 00 ??
+ 00 05 d a y 00 ?? ??
+ 00 04 m o n t h 00
+ 00 02 y e a r 00 ??
+.sp
+When writing code to extract data from named capture groups using the
+name-to-number map, remember that the length of the entries is likely to be
+different for each compiled pattern.
+.sp
+ PCRE2_INFO_NEWLINE
+.sp
+The output is one of the following \fBuint32_t\fP values:
+.sp
+ PCRE2_NEWLINE_CR Carriage return (CR)
+ PCRE2_NEWLINE_LF Linefeed (LF)
+ PCRE2_NEWLINE_CRLF Carriage return, linefeed (CRLF)
+ PCRE2_NEWLINE_ANY Any Unicode line ending
+ PCRE2_NEWLINE_ANYCRLF Any of CR, LF, or CRLF
+ PCRE2_NEWLINE_NUL The NUL character (binary zero)
+.sp
+This identifies the character sequence that will be recognized as meaning
+"newline" while matching.
+.sp
+ PCRE2_INFO_SIZE
+.sp
+Return the size of the compiled pattern in bytes (for all three libraries). The
+third argument should point to a \fBsize_t\fP variable. This value includes the
+size of the general data block that precedes the code units of the compiled
+pattern itself. The value that is used when \fBpcre2_compile()\fP is getting
+memory in which to place the compiled pattern may be slightly larger than the
+value returned by this option, because there are cases where the code that
+calculates the size has to over-estimate. Processing a pattern with the JIT
+compiler does not alter the value returned by this option.
+.
+.
+.\" HTML
+.SH "INFORMATION ABOUT A PATTERN'S CALLOUTS"
+.rs
+.sp
+.nf
+.B int pcre2_callout_enumerate(const pcre2_code *\fIcode\fP,
+.B " int (*\fIcallback\fP)(pcre2_callout_enumerate_block *, void *),"
+.B " void *\fIuser_data\fP);"
+.fi
+.sp
+A script language that supports the use of string arguments in callouts might
+like to scan all the callouts in a pattern before running the match. This can
+be done by calling \fBpcre2_callout_enumerate()\fP. The first argument is a
+pointer to a compiled pattern, the second points to a callback function, and
+the third is arbitrary user data. The callback function is called for every
+callout in the pattern in the order in which they appear. Its first argument is
+a pointer to a callout enumeration block, and its second argument is the
+\fIuser_data\fP value that was passed to \fBpcre2_callout_enumerate()\fP. The
+contents of the callout enumeration block are described in the
+.\" HREF
+\fBpcre2callout\fP
+.\"
+documentation, which also gives further details about callouts.
+.
+.
+.SH "SERIALIZATION AND PRECOMPILING"
+.rs
+.sp
+It is possible to save compiled patterns on disc or elsewhere, and reload them
+later, subject to a number of restrictions. The host on which the patterns are
+reloaded must be running the same version of PCRE2, with the same code unit
+width, and must also have the same endianness, pointer width, and PCRE2_SIZE
+type. Before compiled patterns can be saved, they must be converted to a
+"serialized" form, which in the case of PCRE2 is really just a bytecode dump.
+The functions whose names begin with \fBpcre2_serialize_\fP are used for
+converting to and from the serialized form. They are described in the
+.\" HREF
+\fBpcre2serialize\fP
+.\"
+documentation. Note that PCRE2 serialization does not convert compiled patterns
+to an abstract format like Java or .NET serialization.
+.
+.
+.\" HTML
+.SH "THE MATCH DATA BLOCK"
+.rs
+.sp
+.nf
+.B pcre2_match_data *pcre2_match_data_create(uint32_t \fIovecsize\fP,
+.B " pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B pcre2_match_data *pcre2_match_data_create_from_pattern(
+.B " const pcre2_code *\fIcode\fP, pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B void pcre2_match_data_free(pcre2_match_data *\fImatch_data\fP);
+.fi
+.P
+Information about a successful or unsuccessful match is placed in a match
+data block, which is an opaque structure that is accessed by function calls. In
+particular, the match data block contains a vector of offsets into the subject
+string that define the matched parts of the subject. This is known as the
+\fIovector\fP.
+.P
+Before calling \fBpcre2_match()\fP, \fBpcre2_dfa_match()\fP, or
+\fBpcre2_jit_match()\fP you must create a match data block by calling one of
+the creation functions above. For \fBpcre2_match_data_create()\fP, the first
+argument is the number of pairs of offsets in the \fIovector\fP.
+.P
+When using \fBpcre2_match()\fP, one pair of offsets is required to identify the
+string that matched the whole pattern, with an additional pair for each
+captured substring. For example, a value of 4 creates enough space to record
+the matched portion of the subject plus three captured substrings.
+.P
+When using \fBpcre2_dfa_match()\fP there may be multiple matched substrings of
+different lengths at the same point in the subject. The ovector should be made
+large enough to hold as many as are expected.
+.P
+A minimum of at least 1 pair is imposed by \fBpcre2_match_data_create()\fP, so
+it is always possible to return the overall matched string in the case of
+\fBpcre2_match()\fP or the longest match in the case of
+\fBpcre2_dfa_match()\fP. The maximum number of pairs is 65535; if the first
+argument of \fBpcre2_match_data_create()\fP is greater than this, 65535 is
+used.
+.P
+The second argument of \fBpcre2_match_data_create()\fP is a pointer to a
+general context, which can specify custom memory management for obtaining the
+memory for the match data block. If you are not using custom memory management,
+pass NULL, which causes \fBmalloc()\fP to be used.
+.P
+For \fBpcre2_match_data_create_from_pattern()\fP, the first argument is a
+pointer to a compiled pattern. The ovector is created to be exactly the right
+size to hold all the substrings a pattern might capture when matched using
+\fBpcre2_match()\fP. You should not use this call when matching with
+\fBpcre2_dfa_match()\fP. The second argument is again a pointer to a general
+context, but in this case if NULL is passed, the memory is obtained using the
+same allocator that was used for the compiled pattern (custom or default).
+.P
+A match data block can be used many times, with the same or different compiled
+patterns. You can extract information from a match data block after a match
+operation has finished, using functions that are described in the sections on
+.\" HTML
+.\"
+matched strings
+.\"
+and
+.\" HTML
+.\"
+other match data
+.\"
+below.
+.P
+When a call of \fBpcre2_match()\fP fails, valid data is available in the match
+block only when the error is PCRE2_ERROR_NOMATCH, PCRE2_ERROR_PARTIAL, or one
+of the error codes for an invalid UTF string. Exactly what is available depends
+on the error, and is detailed below.
+.P
+When one of the matching functions is called, pointers to the compiled pattern
+and the subject string are set in the match data block so that they can be
+referenced by the extraction functions after a successful match. After running
+a match, you must not free a compiled pattern or a subject string until after
+all operations on the match data block (for that match) have taken place,
+unless, in the case of the subject string, you have used the
+PCRE2_COPY_MATCHED_SUBJECT option, which is described in the section entitled
+"Option bits for \fBpcre2_match()\fP"
+.\" HTML
+.\"
+below.
+.\"
+.P
+When a match data block itself is no longer needed, it should be freed by
+calling \fBpcre2_match_data_free()\fP. If this function is called with a NULL
+argument, it returns immediately, without doing anything.
+.
+.
+.SH "MEMORY USE FOR MATCH DATA BLOCKS"
+.rs
+.sp
+.nf
+.B PCRE2_SIZE pcre2_get_match_data_size(pcre2_match_data *\fImatch_data\fP);
+.sp
+.B PCRE2_SIZE pcre2_get_match_data_heapframes_size(
+.B " pcre2_match_data *\fImatch_data\fP);"
+.fi
+.P
+The size of a match data block depends on the size of the ovector that it
+contains. The function \fBpcre2_get_match_data_size()\fP returns the size, in
+bytes, of the block that is its argument.
+.P
+When \fBpcre2_match()\fP runs interpretively (that is, without using JIT), it
+makes use of a vector of data frames for remembering backtracking positions.
+The size of each individual frame depends on the number of capturing
+parentheses in the pattern and can be obtained by calling
+\fBpcre2_pattern_info()\fP with the PCRE2_INFO_FRAMESIZE option (see the
+section entitled "Information about a compiled pattern"
+.\" HTML
+.\"
+above).
+.\"
+.P
+Heap memory is used for the frames vector; if the initial memory block turns
+out to be too small during matching, it is automatically expanded. When
+\fBpcre2_match()\fP returns, the memory is not freed, but remains attached to
+the match data block, for use by any subsequent matches that use the same
+block. It is automatically freed when the match data block itself is freed.
+.P
+You can find the current size of the frames vector that a match data block owns
+by calling \fBpcre2_get_match_data_heapframes_size()\fP. For a newly created
+match data block the size will be zero. Some types of match may require a lot
+of frames and thus a large vector; applications that run in environments where
+memory is constrained can check this and free the match data block if the heap
+frames vector has become too big.
+.
+.
+.SH "MATCHING A PATTERN: THE TRADITIONAL FUNCTION"
+.rs
+.sp
+.nf
+.B int pcre2_match(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
+.B " PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
+.B " uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
+.B " pcre2_match_context *\fImcontext\fP);"
+.fi
+.P
+The function \fBpcre2_match()\fP is called to match a subject string against a
+compiled pattern, which is passed in the \fIcode\fP argument. You can call
+\fBpcre2_match()\fP with the same \fIcode\fP argument as many times as you
+like, in order to find multiple matches in the subject string or to match
+different subject strings with the same pattern.
+.P
+This function is the main matching facility of the library, and it operates in
+a Perl-like manner. For specialist use there is also an alternative matching
+function, which is described
+.\" HTML
+.\"
+below
+.\"
+in the section about the \fBpcre2_dfa_match()\fP function.
+.P
+Here is an example of a simple call to \fBpcre2_match()\fP:
+.sp
+ pcre2_match_data *md = pcre2_match_data_create(4, NULL);
+ int rc = pcre2_match(
+ re, /* result of pcre2_compile() */
+ "some string", /* the subject string */
+ 11, /* the length of the subject string */
+ 0, /* start at offset 0 in the subject */
+ 0, /* default options */
+ md, /* the match data block */
+ NULL); /* a match context; NULL means use defaults */
+.sp
+If the subject string is zero-terminated, the length can be given as
+PCRE2_ZERO_TERMINATED. A match context must be provided if certain less common
+matching parameters are to be changed. For details, see the section on
+.\" HTML
+.\"
+the match context
+.\"
+above.
+.
+.
+.SS "The string to be matched by \fBpcre2_match()\fP"
+.rs
+.sp
+The subject string is passed to \fBpcre2_match()\fP as a pointer in
+\fIsubject\fP, a length in \fIlength\fP, and a starting offset in
+\fIstartoffset\fP. The length and offset are in code units, not characters.
+That is, they are in bytes for the 8-bit library, 16-bit code units for the
+16-bit library, and 32-bit code units for the 32-bit library, whether or not
+UTF processing is enabled. As a special case, if \fIsubject\fP is NULL and
+\fIlength\fP is zero, the subject is assumed to be an empty string. If
+\fIlength\fP is non-zero, an error occurs if \fIsubject\fP is NULL.
+.P
+If \fIstartoffset\fP is greater than the length of the subject,
+\fBpcre2_match()\fP returns PCRE2_ERROR_BADOFFSET. When the starting offset is
+zero, the search for a match starts at the beginning of the subject, and this
+is by far the most common case. In UTF-8 or UTF-16 mode, the starting offset
+must point to the start of a character, or to the end of the subject (in UTF-32
+mode, one code unit equals one character, so all offsets are valid). Like the
+pattern string, the subject may contain binary zeros.
+.P
+A non-zero starting offset is useful when searching for another match in the
+same subject by calling \fBpcre2_match()\fP again after a previous success.
+Setting \fIstartoffset\fP differs from passing over a shortened string and
+setting PCRE2_NOTBOL in the case of a pattern that begins with any kind of
+lookbehind. For example, consider the pattern
+.sp
+ \eBiss\eB
+.sp
+which finds occurrences of "iss" in the middle of words. (\eB matches only if
+the current position in the subject is not a word boundary.) When applied to
+the string "Mississippi" the first call to \fBpcre2_match()\fP finds the first
+occurrence. If \fBpcre2_match()\fP is called again with just the remainder of
+the subject, namely "issippi", it does not match, because \eB is always false
+at the start of the subject, which is deemed to be a word boundary. However, if
+\fBpcre2_match()\fP is passed the entire string again, but with
+\fIstartoffset\fP set to 4, it finds the second occurrence of "iss" because it
+is able to look behind the starting point to discover that it is preceded by a
+letter.
+.P
+Finding all the matches in a subject is tricky when the pattern can match an
+empty string. PCRE2 includes a helper API to assist with this; see the
+section entitled "Iterating over all matches"
+.\" HTML
+.\"
+below
+.\"
+for details.
+.P
+If a non-zero starting offset is passed when the pattern is anchored, a single
+attempt to match at the given offset is made. This can only succeed if the
+pattern does not require the match to be at the start of the subject. In other
+words, the anchoring must be the result of setting the PCRE2_ANCHORED option or
+the use of .* with PCRE2_DOTALL, not by starting the pattern with ^ or \eA.
+.
+.
+.\" HTML
+.SS "Option bits for \fBpcre2_match()\fP"
+.rs
+.sp
+The unused bits of the \fIoptions\fP argument for \fBpcre2_match()\fP must be
+zero. The only bits that may be set are PCRE2_ANCHORED,
+PCRE2_COPY_MATCHED_SUBJECT, PCRE2_DISABLE_RECURSELOOP_CHECK, PCRE2_ENDANCHORED,
+PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART,
+PCRE2_NO_JIT, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and PCRE2_PARTIAL_SOFT.
+Their action is described below.
+.P
+Setting PCRE2_ANCHORED or PCRE2_ENDANCHORED at match time is not supported by
+the just-in-time (JIT) compiler. If it is set, JIT matching is disabled and the
+interpretive code in \fBpcre2_match()\fP is run.
+PCRE2_DISABLE_RECURSELOOP_CHECK is ignored by JIT, but apart from PCRE2_NO_JIT
+(obviously), the remaining options are supported for JIT matching.
+.sp
+ PCRE2_ANCHORED
+.sp
+The PCRE2_ANCHORED option limits \fBpcre2_match()\fP to matching at the first
+matching position. If a pattern was compiled with PCRE2_ANCHORED, or turned out
+to be anchored by virtue of its contents, it cannot be made unanchored at
+matching time. Note that setting the option at match time disables JIT
+matching.
+.sp
+ PCRE2_COPY_MATCHED_SUBJECT
+.sp
+By default, a pointer to the subject is remembered in the match data block so
+that, after a successful match, it can be referenced by the substring
+extraction functions. This means that the subject's memory must not be freed
+until all such operations are complete. For some applications where the
+lifetime of the subject string is not guaranteed, it may be necessary to make a
+copy of the subject string, but it is wasteful to do this unless the match is
+successful. After a successful match, if PCRE2_COPY_MATCHED_SUBJECT is set, the
+subject is copied and the new pointer is remembered in the match data block
+instead of the original subject pointer. The memory allocator that was used for
+the match block itself is used. The copy is automatically freed when
+\fBpcre2_match_data_free()\fP is called to free the match data block. It is also
+automatically freed if the match data block is re-used for another match
+operation.
+.sp
+ PCRE2_DISABLE_RECURSELOOP_CHECK
+.sp
+This option is relevant only to \fBpcre2_match()\fP for interpretive matching.
+It is ignored when JIT is used, and is forbidden for \fBpcre2_dfa_match()\fP.
+.P
+The use of recursion in patterns can lead to infinite loops. In the
+interpretive matcher these would be eventually caught by the match or heap
+limits, but this could take a long time and/or use a lot of memory if the
+limits are large. There is therefore a check at the start of each recursion.
+If the same group is still active from a previous call, and the current subject
+pointer is the same as it was at the start of that group, and the furthest
+inspected character of the subject has not changed, an error is generated.
+.P
+There are rare cases of matches that would complete, but nevertheless trigger
+this error. This option disables the check. It is provided mainly for testing
+when comparing JIT and interpretive behaviour.
+.sp
+ PCRE2_ENDANCHORED
+.sp
+If the PCRE2_ENDANCHORED option is set, any string that \fBpcre2_match()\fP
+matches must be right at the end of the subject string. Note that setting the
+option at match time disables JIT matching.
+.sp
+ PCRE2_NOTBOL
+.sp
+This option specifies that first character of the subject string is not the
+beginning of a line, so the circumflex metacharacter should not match before
+it. Setting this without having set PCRE2_MULTILINE at compile time causes
+circumflex never to match. This option affects only the behaviour of the
+circumflex metacharacter. It does not affect \eA.
+.sp
+ PCRE2_NOTEOL
+.sp
+This option specifies that the end of the subject string is not the end of a
+line, so the dollar metacharacter should not match it nor (except in multiline
+mode) a newline immediately before it. Setting this without having set
+PCRE2_MULTILINE at compile time causes dollar never to match. This option
+affects only the behaviour of the dollar metacharacter. It does not affect \eZ
+or \ez.
+.sp
+ PCRE2_NOTEMPTY
+.sp
+An empty string is not considered to be a valid match if this option is set. If
+there are alternatives in the pattern, they are tried. If all the alternatives
+match the empty string, the entire match fails. For example, if the pattern
+.sp
+ a?b?
+.sp
+is applied to a string not beginning with "a" or "b", it matches an empty
+string at the start of the subject. With PCRE2_NOTEMPTY set, this match is not
+valid, so \fBpcre2_match()\fP searches further into the string for occurrences
+of "a" or "b".
+.sp
+ PCRE2_NOTEMPTY_ATSTART
+.sp
+This is like PCRE2_NOTEMPTY, except that it locks out an empty string match
+only at the first matching position, that is, at the start of the subject plus
+the starting offset. An empty string match later in the subject is permitted.
+If the pattern is anchored, such a match can occur only if the pattern contains
+\eK.
+.sp
+ PCRE2_NO_JIT
+.sp
+By default, if a pattern has been successfully processed by
+\fBpcre2_jit_compile()\fP, JIT is automatically used when \fBpcre2_match()\fP
+is called with options that JIT supports. Setting PCRE2_NO_JIT disables the use
+of JIT; it forces matching to be done by the interpreter.
+.sp
+ PCRE2_NO_UTF_CHECK
+.sp
+When PCRE2_UTF is set at compile time, the validity of the subject as a UTF
+string is checked unless PCRE2_NO_UTF_CHECK is passed to \fBpcre2_match()\fP or
+PCRE2_MATCH_INVALID_UTF was passed to \fBpcre2_compile()\fP. The latter special
+case is discussed in detail in the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+documentation.
+.P
+In the default case, if a non-zero starting offset is given, the check is
+applied only to that part of the subject that could be inspected during
+matching, and there is a check that the starting offset points to the first
+code unit of a character or to the end of the subject. If there are no
+lookbehind assertions in the pattern, the check starts at the starting offset.
+Otherwise, it starts at the length of the longest lookbehind before the
+starting offset, or at the start of the subject if there are not that many
+characters before the starting offset. Note that the sequences \eb and \eB are
+one-character lookbehinds.
+.P
+The check is carried out before any other processing takes place, and a
+negative error code is returned if the check fails. There are several UTF error
+codes for each code unit width, corresponding to different problems with the
+code unit sequence. There are discussions about the validity of
+.\" HTML
+.\"
+UTF-8 strings,
+.\"
+.\" HTML
+.\"
+UTF-16 strings,
+.\"
+and
+.\" HTML
+.\"
+UTF-32 strings
+.\"
+in the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+documentation.
+.P
+If you know that your subject is valid, and you want to skip this check for
+performance reasons, you can set the PCRE2_NO_UTF_CHECK option when calling
+\fBpcre2_match()\fP. You might want to do this for the second and subsequent
+calls to \fBpcre2_match()\fP if you are making repeated calls to find multiple
+matches in the same subject string.
+.P
+\fBWarning:\fP Unless PCRE2_MATCH_INVALID_UTF was set at compile time, when
+PCRE2_NO_UTF_CHECK is set at match time the effect of passing an invalid
+string as a subject, or an invalid value of \fIstartoffset\fP, is undefined.
+Your program may crash or loop indefinitely or give wrong results.
+.sp
+ PCRE2_PARTIAL_HARD
+ PCRE2_PARTIAL_SOFT
+.sp
+These options turn on the partial matching feature. A partial match occurs if
+the end of the subject string is reached successfully, but there are not enough
+subject characters to complete the match. In addition, either at least one
+character must have been inspected or the pattern must contain a lookbehind, or
+the pattern must be one that could match an empty string.
+.P
+If this situation arises when PCRE2_PARTIAL_SOFT (but not PCRE2_PARTIAL_HARD)
+is set, matching continues by testing any remaining alternatives. Only if no
+complete match can be found is PCRE2_ERROR_PARTIAL returned instead of
+PCRE2_ERROR_NOMATCH. In other words, PCRE2_PARTIAL_SOFT specifies that the
+caller is prepared to handle a partial match, but only if no complete match can
+be found.
+.P
+If PCRE2_PARTIAL_HARD is set, it overrides PCRE2_PARTIAL_SOFT. In this case, if
+a partial match is found, \fBpcre2_match()\fP immediately returns
+PCRE2_ERROR_PARTIAL, without considering any other alternatives. In other
+words, when PCRE2_PARTIAL_HARD is set, a partial match is considered to be more
+important than an alternative complete match.
+.P
+There is a more detailed discussion of partial and multi-segment matching, with
+examples, in the
+.\" HREF
+\fBpcre2partial\fP
+.\"
+documentation.
+.
+.
+.
+.SH "NEWLINE HANDLING WHEN MATCHING"
+.rs
+.sp
+When PCRE2 is built, a default newline convention is set; this is usually the
+standard convention for the operating system. The default can be overridden in
+a
+.\" HTML
+.\"
+compile context
+.\"
+by calling \fBpcre2_set_newline()\fP. It can also be overridden by starting a
+pattern string with, for example, (*CRLF), as described in the
+.\" HTML
+.\"
+section on newline conventions
+.\"
+in the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+page. During matching, the newline choice affects the behaviour of the dot,
+circumflex, and dollar metacharacters. It may also alter the way the match
+starting position is advanced after a match failure for an unanchored pattern.
+.P
+When PCRE2_NEWLINE_CRLF, PCRE2_NEWLINE_ANYCRLF, or PCRE2_NEWLINE_ANY is set as
+the newline convention, and a match attempt for an unanchored pattern fails
+when the current starting position is at a CRLF sequence, and the pattern
+contains no explicit matches for CR or LF characters, the match position is
+advanced by two characters instead of one, in other words, to after the CRLF.
+.P
+The above rule is a compromise that makes the most common cases work as
+expected. For example, if the pattern is .+A (and the PCRE2_DOTALL option is
+not set), it does not match the string "\er\enA" because, after failing at the
+start, it skips both the CR and the LF before retrying. However, the pattern
+[\er\en]A does match that string, because it contains an explicit CR or LF
+reference, and so advances only by one character after the first failure.
+.P
+An explicit match for CR of LF is either a literal appearance of one of those
+characters in the pattern, or one of the \er or \en or equivalent octal or
+hexadecimal escape sequences. Implicit matches such as [^X] do not count, nor
+does \es, even though it includes CR and LF in the characters that it matches.
+.P
+Notwithstanding the above, anomalous effects may still occur when CRLF is a
+valid newline sequence and explicit \er or \en escapes appear in the pattern.
+.
+.
+.\" HTML
+.SH "HOW PCRE2_MATCH() RETURNS A STRING AND CAPTURED SUBSTRINGS"
+.rs
+.sp
+.nf
+.B uint32_t pcre2_get_ovector_count(pcre2_match_data *\fImatch_data\fP);
+.sp
+.B PCRE2_SIZE *pcre2_get_ovector_pointer(pcre2_match_data *\fImatch_data\fP);
+.fi
+.P
+In general, a pattern matches a certain portion of the subject, and in
+addition, further substrings from the subject may be picked out by
+parenthesized parts of the pattern. Following the usage in Jeffrey Friedl's
+book, this is called "capturing" in what follows, and the phrase "capture
+group" (Perl terminology) is used for a fragment of a pattern that picks out a
+substring. PCRE2 supports several other kinds of parenthesized group that do
+not cause substrings to be captured. The \fBpcre2_pattern_info()\fP function
+can be used to find out how many capture groups there are in a compiled
+pattern.
+.P
+You can use auxiliary functions for accessing captured substrings
+.\" HTML
+.\"
+by number
+.\"
+or
+.\" HTML
+.\"
+by name,
+.\"
+as described in sections below.
+.P
+Alternatively, you can make direct use of the vector of PCRE2_SIZE values,
+called the \fBovector\fP, which contains the offsets of captured strings. It is
+part of the
+.\" HTML
+.\"
+match data block.
+.\"
+The function \fBpcre2_get_ovector_pointer()\fP returns the address of the
+ovector, and \fBpcre2_get_ovector_count()\fP returns the number of pairs of
+values it contains.
+.P
+Within the ovector, the first in each pair of values is set to the offset of
+the first code unit of a substring, and the second is set to the offset of the
+first code unit after the end of a substring. These values are always code unit
+offsets, not character offsets. That is, they are byte offsets in the 8-bit
+library, 16-bit offsets in the 16-bit library, and 32-bit offsets in the 32-bit
+library.
+.P
+After a partial match (error return PCRE2_ERROR_PARTIAL), only the first pair
+of offsets (that is, \fIovector[0]\fP and \fIovector[1]\fP) are set. They
+identify the part of the subject that was partially matched. See the
+.\" HREF
+\fBpcre2partial\fP
+.\"
+documentation for details of partial matching.
+.P
+After a fully successful match, the first pair of offsets identifies the
+portion of the subject string that was matched by the entire pattern. The next
+pair is used for the first captured substring, and so on. The value returned by
+\fBpcre2_match()\fP is one more than the highest numbered pair that has been
+set. For example, if two substrings have been captured, the returned value is
+3. If there are no captured substrings, the return value from a successful
+match is 1, indicating that just the first pair of offsets has been set.
+.P
+If a pattern uses the \eK escape sequence within a positive lookahead assertion,
+the reported start of a successful match can be greater than the end of the
+match. For example, if the pattern (?=ab\eK) is matched against "ab", the start
+and end offset values for the match are 2 and 0.
+.P
+If a capture group is matched repeatedly within a single match operation, it is
+the last portion of the subject that it matched that is returned.
+.P
+If the ovector is too small to hold all the captured substring offsets, as much
+as possible is filled in, and the function returns a value of zero. If captured
+substrings are not of interest, \fBpcre2_match()\fP may be called with a match
+data block whose ovector is of minimum length (that is, one pair).
+.P
+It is possible for capture group number \fIn+1\fP to match some part of the
+subject when group \fIn\fP has not been used at all. For example, if the string
+"abc" is matched against the pattern (a|(z))(bc) the return from the function
+is 4, and groups 1 and 3 are matched, but 2 is not. When this happens, both
+values in the offset pairs corresponding to unused groups are set to
+PCRE2_UNSET.
+.P
+Offset values that correspond to unused groups at the end of the expression are
+also set to PCRE2_UNSET. For example, if the string "abc" is matched against
+the pattern (abc)(x(yz)?)? groups 2 and 3 are not matched. The return from the
+function is 2, because the highest used capture group number is 1. The offsets
+for the second and third capture groups (assuming the vector is large enough,
+of course) are set to PCRE2_UNSET.
+.P
+Elements in the ovector that do not correspond to capturing parentheses in the
+pattern are never changed. That is, if a pattern contains \fIn\fP capturing
+parentheses, no more than \fIovector[0]\fP to \fIovector[2n+1]\fP are set by
+\fBpcre2_match()\fP. The other elements retain whatever values they previously
+had. After a failed match attempt, the contents of the ovector are unchanged.
+.
+.
+.\" HTML
+.SH "OTHER INFORMATION ABOUT A MATCH"
+.rs
+.sp
+.nf
+.B PCRE2_SPTR pcre2_get_mark(pcre2_match_data *\fImatch_data\fP);
+.sp
+.B PCRE2_SIZE pcre2_get_startchar(pcre2_match_data *\fImatch_data\fP);
+.fi
+.P
+As well as the offsets in the ovector, other information about a match is
+retained in the match data block and can be retrieved by the above functions in
+appropriate circumstances. If they are called at other times, the result is
+undefined.
+.P
+After a successful match, a partial match (PCRE2_ERROR_PARTIAL), or a failure
+to match (PCRE2_ERROR_NOMATCH), a mark name may be available. The function
+\fBpcre2_get_mark()\fP can be called to access this name, which can be
+specified in the pattern by any of the backtracking control verbs, not just
+(*MARK). The same function applies to all the verbs. It returns a pointer to
+the zero-terminated name, which is within the compiled pattern. If no name is
+available, NULL is returned. The length of the name (excluding the terminating
+zero) is stored in the code unit that precedes the name. You should use this
+length instead of relying on the terminating zero if the name might contain a
+binary zero.
+.P
+After a successful match, the name that is returned is the last mark name
+encountered on the matching path through the pattern. Instances of backtracking
+verbs without names do not count. Thus, for example, if the matching path
+contains (*MARK:A)(*PRUNE), the name "A" is returned. After a "no match" or a
+partial match, the last encountered name is returned. For example, consider
+this pattern:
+.sp
+ ^(*MARK:A)((*MARK:B)a|b)c
+.sp
+When it matches "bc", the returned name is A. The B mark is "seen" in the first
+branch of the group, but it is not on the matching path. On the other hand,
+when this pattern fails to match "bx", the returned name is B.
+.P
+\fBWarning:\fP By default, certain start-of-match optimizations are used to
+give a fast "no match" result in some situations. For example, if the anchoring
+is removed from the pattern above, there is an initial check for the presence
+of "c" in the subject before running the matching engine. This check fails for
+"bx", causing a match failure without seeing any marks. You can disable the
+start-of-match optimizations by setting the PCRE2_NO_START_OPTIMIZE option for
+\fBpcre2_compile()\fP or by starting the pattern with (*NO_START_OPT).
+.P
+After a successful match, a partial match, or one of the invalid UTF errors
+(for example, PCRE2_ERROR_UTF8_ERR5), \fBpcre2_get_startchar()\fP can be
+called. After a successful or partial match it returns the code unit offset of
+the character at which the match started. For a non-partial match, this can be
+different to the value of \fIovector[0]\fP if the pattern contains the \eK
+escape sequence. After a partial match, however, this value is always the same
+as \fIovector[0]\fP because \eK does not affect the result of a partial match.
+.P
+After a UTF check failure, \fBpcre2_get_startchar()\fP can be used to obtain
+the code unit offset of the invalid UTF character. Details are given in the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+page.
+.
+.
+.\" HTML
+.SH "ERROR RETURNS FROM \fBpcre2_match()\fP"
+.rs
+.sp
+If \fBpcre2_match()\fP fails, it returns a negative number. This can be
+converted to a text string by calling the \fBpcre2_get_error_message()\fP
+function (see "Obtaining a textual error message"
+.\" HTML
+.\"
+below).
+.\"
+Negative error codes are also returned by other functions, and are documented
+with them. The codes are given names in the header file. If UTF checking is in
+force and an invalid UTF subject string is detected, one of a number of
+UTF-specific negative error codes is returned. Details are given in the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+page. The following are the other errors that may be returned by
+\fBpcre2_match()\fP:
+.sp
+ PCRE2_ERROR_NOMATCH
+.sp
+The subject string did not match the pattern.
+.sp
+ PCRE2_ERROR_PARTIAL
+.sp
+The subject string did not match, but it did match partially. See the
+.\" HREF
+\fBpcre2partial\fP
+.\"
+documentation for details of partial matching.
+.sp
+ PCRE2_ERROR_BADMAGIC
+.sp
+PCRE2 stores a 4-byte "magic number" at the start of the compiled code, to
+catch the case when it is passed a junk pointer. This is the error that is
+returned when the magic number is not present.
+.sp
+ PCRE2_ERROR_BADMODE
+.sp
+This error is given when a compiled pattern is passed to a function in a
+library of a different code unit width, for example, a pattern compiled by
+the 8-bit library is passed to a 16-bit or 32-bit library function.
+.sp
+ PCRE2_ERROR_BADOFFSET
+.sp
+The value of \fIstartoffset\fP was greater than the length of the subject.
+.sp
+ PCRE2_ERROR_BADOPTION
+.sp
+An unrecognized bit was set in the \fIoptions\fP argument.
+.sp
+ PCRE2_ERROR_BADUTFOFFSET
+.sp
+The UTF code unit sequence that was passed as a subject was checked and found
+to be valid (the PCRE2_NO_UTF_CHECK option was not set), but the value of
+\fIstartoffset\fP did not point to the beginning of a UTF character or the end
+of the subject.
+.sp
+ PCRE2_ERROR_CALLOUT
+.sp
+This error is never generated by \fBpcre2_match()\fP itself. It is provided for
+use by callout functions that want to cause \fBpcre2_match()\fP or
+\fBpcre2_callout_enumerate()\fP to return a distinctive error code. See the
+.\" HREF
+\fBpcre2callout\fP
+.\"
+documentation for details.
+.sp
+ PCRE2_ERROR_DEPTHLIMIT
+.sp
+The nested backtracking depth limit was reached.
+.sp
+ PCRE2_ERROR_HEAPLIMIT
+.sp
+The heap limit was reached.
+.sp
+ PCRE2_ERROR_INTERNAL
+.sp
+An unexpected internal error has occurred. This error could be caused by a bug
+in PCRE2 or by overwriting of the compiled pattern.
+.sp
+ PCRE2_ERROR_JIT_STACKLIMIT
+.sp
+This error is returned when a pattern that was successfully studied using JIT
+is being matched, but the memory available for the just-in-time processing
+stack is not large enough. See the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+documentation for more details.
+.sp
+ PCRE2_ERROR_MATCHLIMIT
+.sp
+The backtracking match limit was reached.
+.sp
+ PCRE2_ERROR_NOMEMORY
+.sp
+Heap memory is used to remember backtracking points. This error is given when
+the memory allocation function (default or custom) fails. Note that a different
+error, PCRE2_ERROR_HEAPLIMIT, is given if the amount of memory needed exceeds
+the heap limit. PCRE2_ERROR_NOMEMORY is also returned if
+PCRE2_COPY_MATCHED_SUBJECT is set and memory allocation fails.
+.sp
+ PCRE2_ERROR_NULL
+.sp
+Either the \fIcode\fP, \fIsubject\fP, or \fImatch_data\fP argument was passed
+as NULL.
+.sp
+ PCRE2_ERROR_RECURSELOOP
+.sp
+This error is returned when \fBpcre2_match()\fP detects a recursion loop within
+the pattern. Specifically, it means that either the whole pattern or a
+capture group has been called recursively for the second time at the same
+position in the subject string. Some simple patterns that might do this are
+detected and faulted at compile time, but more complicated cases, in particular
+mutual recursions between two different groups, cannot be detected until
+matching is attempted.
+.
+.
+.\" HTML
+.SH "OBTAINING A TEXTUAL ERROR MESSAGE"
+.rs
+.sp
+.nf
+.B int pcre2_get_error_message(int \fIerrorcode\fP, PCRE2_UCHAR *\fIbuffer\fP,
+.B " PCRE2_SIZE \fIbufflen\fP);"
+.fi
+.P
+A text message for an error code from any PCRE2 function (compile, match, or
+auxiliary) can be obtained by calling \fBpcre2_get_error_message()\fP. The code
+is passed as the first argument, with the remaining two arguments specifying a
+code unit buffer and its length in code units, into which the text message is
+placed. The message is returned in code units of the appropriate width for the
+library that is being used.
+.P
+The returned message is terminated with a trailing zero, and the function
+returns the number of code units used, excluding the trailing zero. If the
+error number is unknown, the negative error code PCRE2_ERROR_BADDATA is
+returned. If the buffer is too small, the message is truncated (but still with
+a trailing zero), and the negative error code PCRE2_ERROR_NOMEMORY is returned.
+None of the messages is very long; a buffer size of 120 code units is ample.
+.
+.
+.\" HTML
+.SH "ITERATING OVER ALL MATCHES"
+.rs
+.sp
+.nf
+.B int pcre2_next_match(pcre2_match_data *\fImatch_data\fP,
+.B " PCRE2_SIZE *\fIpstart_offset\fP, uint32_t *\fIpoptions\fP);"
+.fi
+.P
+A common task for applications is to implement "global" matching behaviour,
+for example, replacing all matches in the subject; splitting the subject on all
+matches; or simply counting the number of matches. The \fBpcre2_next_match()\fP
+function helps with this task by providing the appropriate parameters for the
+next match attempt (available since PCRE2 10.47).
+.P
+First, a match attempt should be made using one of the matching functions
+(\fBpcre2_match()\fP, \fBpcre2_dfa_match()\fP, or \fBpcre2_jit_match()\fP).
+Then, \fBpcre2_next_match()\fP can be called, providing the same
+\fImatch_data\fP parameter.
+.P
+It returns 0 ("false") if there is no need to make a further match attempt, or
+1 ("true") if another match should be attempted. Returning 1 does not imply that
+there is another match, only that another match should be attempted (which may
+return PCRE2_ERROR_NOMATCH).
+.P
+The *\fIpstart_offset\fP and *\fIpoptions\fP are set if the function returns 1.
+The *\fIpstart_offset\fP should be passed to the next match attempt directly,
+and the *\fIpoptions\fP should be passed to the next match attempt by combining
+with the application's match options using OR.
+.P
+There is some code that demonstrates how to do this in the
+.\" HREF
+\fBpcre2demo\fP
+.\"
+sample program. The general pattern is:
+.sp
+.nf
+ uint32_t app_options = ...;
+ uint32_t global_options = 0;
+ PCRE2_SIZE start_offset = 0;
+ while (1)
+ {
+ int rc = pcre2_match(re, subject, subject_len, start_offset,
+ app_options | global_options, match_data,
+ match_context);
+\&
+ if (rc == PCRE2_ERROR_NOMATCH) break; /* no match, and no more attempts */
+ if (rc < 0) { ... exit }
+\&
+ ...handle the match
+\&
+ if (!pcre2_next_match(match_data, &start_offset, &global_options))
+ break; /* no more attempts */
+ }
+.fi
+.P
+The guarantees provided by \fBpcre2_next_match()\fP are that the start_offset
+will advance, so the loop will definitely terminate. The conditions which
+ensure this are that either: (a) pcre2_next_match() returns 0 (false); or
+(b) the returned *\fIpstart_offset\fP is strictly greater than the previous
+start_offset; or (c) if the previous match was a successful match of the empty
+string then the returned *\fIpstart_offset\fP is equal to the previous
+ovector[1], and *\fIpoptions\fP will be set to PCRE2_NOTEMPTY_ATSTART to prevent
+another empty match from being returned.
+.P
+A loop implemented as shown above will always terminate, unless there is a bug
+in PCRE2. As a measure of "defensive programming", applications are encouraged
+to add an assertion or check to break their loop if it does not make progress
+(and report the issue as a bug).
+.P
+If an application does not use the flag PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK, then
+each match is "well-behaved" and satisfies:
+.sp
+ start_offset <= ovector[0] <= ovector[1].
+.sp
+In this case, the matches found by pcre2_match() with pcre2_next_match() will be
+sorted, non-overlapping (possibly touching), and with no duplicates.
+.P
+Otherwise, if PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK is used, then the guarantees are
+considerably weaker. We do not guarantee that the matches will always advance:
+only that the start_offset will. The matches found by pcre2_match() with
+pcre2_next_match() will be a finite sequence (as pcre2_next_match() ensures that
+start_offset advances, so the search will terminate). The matches can however be
+overlapping, can contain duplicates, and (in truly pathological examples) may
+not even be sorted by ovector[0]. Additionally, each match itself can end before
+it starts (ovector[1] < ovector[0]). We recommend that applications do not set
+PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK.
+.
+.
+.\" HTML
+.SH "EXTRACTING CAPTURED SUBSTRINGS BY NUMBER"
+.rs
+.sp
+.nf
+.B int pcre2_substring_length_bynumber(pcre2_match_data *\fImatch_data\fP,
+.B " uint32_t \fInumber\fP, PCRE2_SIZE *\fIlength\fP);"
+.sp
+.B int pcre2_substring_copy_bynumber(pcre2_match_data *\fImatch_data\fP,
+.B " uint32_t \fInumber\fP, PCRE2_UCHAR *\fIbuffer\fP,"
+.B " PCRE2_SIZE *\fIbufflen\fP);"
+.sp
+.B int pcre2_substring_get_bynumber(pcre2_match_data *\fImatch_data\fP,
+.B " uint32_t \fInumber\fP, PCRE2_UCHAR **\fIbufferptr\fP,"
+.B " PCRE2_SIZE *\fIbufflen\fP);"
+.sp
+.B void pcre2_substring_free(PCRE2_UCHAR *\fIbuffer\fP);
+.fi
+.P
+Captured substrings can be accessed directly by using the ovector as described
+.\" HTML
+.\"
+above.
+.\"
+For convenience, auxiliary functions are provided for extracting captured
+substrings as new, separate, zero-terminated strings. A substring that contains
+a binary zero is correctly extracted and has a further zero added on the end,
+but the result is not, of course, a C string.
+.P
+The functions in this section identify substrings by number. The number zero
+refers to the entire matched substring, with higher numbers referring to
+substrings captured by parenthesized groups. After a partial match, only
+substring zero is available. An attempt to extract any other substring gives
+the error PCRE2_ERROR_PARTIAL. The next section describes similar functions for
+extracting captured substrings by name.
+.P
+If a pattern uses the \eK escape sequence within a positive lookahead assertion,
+the reported start of a successful match can be greater than the end of the
+match. For example, if the pattern (?=ab\eK) is matched against "ab", the start
+and end offset values for the match are 2 and 0. In this situation, calling
+these functions with a zero substring number extracts a zero-length empty
+string.
+.P
+You can find the length in code units of a captured substring without
+extracting it by calling \fBpcre2_substring_length_bynumber()\fP. The first
+argument is a pointer to the match data block, the second is the group number,
+and the third is a pointer to a variable into which the length is placed. If
+you just want to know whether or not the substring has been captured, you can
+pass the third argument as NULL.
+.P
+The \fBpcre2_substring_copy_bynumber()\fP function copies a captured substring
+into a supplied buffer, whereas \fBpcre2_substring_get_bynumber()\fP copies it
+into new memory, obtained using the same memory allocation function that was
+used for the match data block. The first two arguments of these functions are a
+pointer to the match data block and a capture group number.
+.P
+The final arguments of \fBpcre2_substring_copy_bynumber()\fP are a pointer to
+the buffer and a pointer to a variable that contains its length in code units.
+This is updated to contain the actual number of code units used for the
+extracted substring, excluding the terminating zero.
+.P
+For \fBpcre2_substring_get_bynumber()\fP the third and fourth arguments point
+to variables that are updated with a pointer to the new memory and the number
+of code units that comprise the substring, again excluding the terminating
+zero. When the substring is no longer needed, the memory should be freed by
+calling \fBpcre2_substring_free()\fP.
+.P
+The return value from all these functions is zero for success, or a negative
+error code. If the pattern match failed, the match failure code is returned.
+If a substring number greater than zero is used after a partial match,
+PCRE2_ERROR_PARTIAL is returned. Other possible error codes are:
+.sp
+ PCRE2_ERROR_NOMEMORY
+.sp
+The buffer was too small for \fBpcre2_substring_copy_bynumber()\fP, or the
+attempt to get memory failed for \fBpcre2_substring_get_bynumber()\fP.
+.sp
+ PCRE2_ERROR_NOSUBSTRING
+.sp
+There is no substring with that number in the pattern, that is, the number is
+greater than the number of capturing parentheses.
+.sp
+ PCRE2_ERROR_UNAVAILABLE
+.sp
+The substring number, though not greater than the number of captures in the
+pattern, is greater than the number of slots in the ovector, so the substring
+could not be captured.
+.sp
+ PCRE2_ERROR_UNSET
+.sp
+The substring did not participate in the match. For example, if the pattern is
+(abc)|(def) and the subject is "def", and the ovector contains at least two
+capturing slots, substring number 1 is unset.
+.
+.
+.SH "EXTRACTING A LIST OF ALL CAPTURED SUBSTRINGS"
+.rs
+.sp
+.nf
+.B int pcre2_substring_list_get(pcre2_match_data *\fImatch_data\fP,
+.B " PCRE2_UCHAR ***\fIlistptr\fP, PCRE2_SIZE **\fIlengthsptr\fP);"
+.sp
+.B void pcre2_substring_list_free(PCRE2_UCHAR **\fIlist\fP);
+.fi
+.P
+The \fBpcre2_substring_list_get()\fP function extracts all available substrings
+and builds a list of pointers to them. It also (optionally) builds a second
+list that contains their lengths (in code units), excluding a terminating zero
+that is added to each of them. All this is done in a single block of memory
+that is obtained using the same memory allocation function that was used to get
+the match data block.
+.P
+This function must be called only after a successful match. If called after a
+partial match, the error code PCRE2_ERROR_PARTIAL is returned.
+.P
+The address of the memory block is returned via \fIlistptr\fP, which is also
+the start of the list of string pointers. The end of the list is marked by a
+NULL pointer. The address of the list of lengths is returned via
+\fIlengthsptr\fP. If your strings do not contain binary zeros and you do not
+therefore need the lengths, you may supply NULL as the \fBlengthsptr\fP
+argument to disable the creation of a list of lengths. The yield of the
+function is zero if all went well, or PCRE2_ERROR_NOMEMORY if the memory block
+could not be obtained. When the list is no longer needed, it should be freed by
+calling \fBpcre2_substring_list_free()\fP.
+.P
+If this function encounters a substring that is unset, which can happen when
+capture group number \fIn+1\fP matches some part of the subject, but group
+\fIn\fP has not been used at all, it returns an empty string. This can be
+distinguished from a genuine zero-length substring by inspecting the
+appropriate offset in the ovector, which contain PCRE2_UNSET for unset
+substrings, or by calling \fBpcre2_substring_length_bynumber()\fP.
+.
+.
+.\" HTML
+.SH "EXTRACTING CAPTURED SUBSTRINGS BY NAME"
+.rs
+.sp
+.nf
+.B int pcre2_substring_number_from_name(const pcre2_code *\fIcode\fP,
+.B " PCRE2_SPTR \fIname\fP);"
+.sp
+.B int pcre2_substring_length_byname(pcre2_match_data *\fImatch_data\fP,
+.B " PCRE2_SPTR \fIname\fP, PCRE2_SIZE *\fIlength\fP);"
+.sp
+.B int pcre2_substring_copy_byname(pcre2_match_data *\fImatch_data\fP,
+.B " PCRE2_SPTR \fIname\fP, PCRE2_UCHAR *\fIbuffer\fP, PCRE2_SIZE *\fIbufflen\fP);"
+.sp
+.B int pcre2_substring_get_byname(pcre2_match_data *\fImatch_data\fP,
+.B " PCRE2_SPTR \fIname\fP, PCRE2_UCHAR **\fIbufferptr\fP, PCRE2_SIZE *\fIbufflen\fP);"
+.sp
+.B void pcre2_substring_free(PCRE2_UCHAR *\fIbuffer\fP);
+.fi
+.P
+To extract a substring by name, you first have to find associated number.
+For example, for this pattern:
+.sp
+ (a+)b(?\ed+)...
+.sp
+the number of the capture group called "xxx" is 2. If the name is known to be
+unique (PCRE2_DUPNAMES was not set), you can find the number from the name by
+calling \fBpcre2_substring_number_from_name()\fP. The first argument is the
+compiled pattern, and the second is the name. The yield of the function is the
+group number, PCRE2_ERROR_NOSUBSTRING if there is no group with that name, or
+PCRE2_ERROR_NOUNIQUESUBSTRING if there is more than one group with that name.
+Given the number, you can extract the substring directly from the ovector, or
+use one of the "bynumber" functions described above.
+.P
+For convenience, there are also "byname" functions that correspond to the
+"bynumber" functions, the only difference being that the second argument is a
+name instead of a number. If PCRE2_DUPNAMES is set and there are duplicate
+names, these functions scan all the groups with the given name, and return the
+captured substring from the first named group that is set.
+.P
+If there are no groups with the given name, PCRE2_ERROR_NOSUBSTRING is
+returned. If all groups with the name have numbers that are greater than the
+number of slots in the ovector, PCRE2_ERROR_UNAVAILABLE is returned. If there
+is at least one group with a slot in the ovector, but no group is found to be
+set, PCRE2_ERROR_UNSET is returned.
+.P
+\fBWarning:\fP If the pattern uses the (?| feature to set up multiple
+capture groups with the same number, as described in the
+.\" HTML
+.\"
+section on duplicate group numbers
+.\"
+in the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+page, you cannot use names to distinguish the different capture groups, because
+names are not included in the compiled code. The matching process uses only
+numbers. For this reason, the use of different names for groups with the
+same number causes an error at compile time.
+.
+.
+.\" HTML
+.SH "CREATING A NEW STRING WITH SUBSTITUTIONS"
+.rs
+.sp
+.nf
+.B int pcre2_substitute(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
+.B " PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
+.B " uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
+.B " pcre2_match_context *\fImcontext\fP, PCRE2_SPTR \fIreplacement\fP,"
+.B " PCRE2_SIZE \fIrlength\fP, PCRE2_UCHAR *\fIoutputbuffer\fP,"
+.B " PCRE2_SIZE *\fIoutlengthptr\fP);"
+.fi
+.P
+This function optionally calls \fBpcre2_match()\fP and then makes a copy of the
+subject string in \fIoutputbuffer\fP, replacing parts that were matched with
+the \fIreplacement\fP string, whose length is supplied in \fBrlength\fP, which
+can be given as PCRE2_ZERO_TERMINATED for a zero-terminated string. As a
+special case, if \fIreplacement\fP is NULL and \fIrlength\fP is zero, the
+replacement is assumed to be an empty string. If \fIrlength\fP is non-zero, an
+error occurs if \fIreplacement\fP is NULL.
+.P
+There is an option (see PCRE2_SUBSTITUTE_REPLACEMENT_ONLY below) to return just
+the replacement string(s). The default action is to perform just one
+replacement if the pattern matches, but there is an option that requests
+multiple replacements (see PCRE2_SUBSTITUTE_GLOBAL below).
+.P
+If successful, \fBpcre2_substitute()\fP returns the number of substitutions
+that were carried out. This may be zero if no match was found, and is never
+greater than one unless PCRE2_SUBSTITUTE_GLOBAL is set. A negative value is
+returned if an error is detected.
+.P
+Matches in which a \eK item in a lookahead in the pattern causes the match to
+end before it starts are not supported, and give rise to an error return. For
+global replacements, matches in which \eK in a lookbehind causes the match to
+start earlier than the point that was reached in the previous iteration are
+also not supported. (These cases are only possible if the pattern was compiled
+with the backwards-compatibility option PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK.)
+.P
+The first seven arguments of \fBpcre2_substitute()\fP are the same as for
+\fBpcre2_match()\fP, except that the partial matching options are not
+permitted, and \fImatch_data\fP may be passed as NULL, in which case a match
+data block is obtained and freed within this function, using memory management
+functions from the match context, if provided, or else those that were used to
+allocate memory for the compiled code.
+.P
+If \fImatch_data\fP is not NULL and PCRE2_SUBSTITUTE_MATCHED is not set, the
+provided block is used for all calls to \fBpcre2_match()\fP, and its contents
+afterwards are the result of the final call made internally by
+\fBpcre2_substitute()\fP to the matching function. For global changes, this will
+always be a no-match error. The contents of the ovector within the match data
+block may or may not have been changed.
+.P
+As well as the usual options for \fBpcre2_match()\fP, a number of additional
+options can be set in the \fIoptions\fP argument of \fBpcre2_substitute()\fP.
+One such option is PCRE2_SUBSTITUTE_MATCHED. When this is set, an external
+\fImatch_data\fP block must be provided, and it must have already been used for
+an external call to \fBpcre2_match()\fP (or \fBpcre2_jit_match()\fP) with the
+same pattern, subject pointer, effective subject length, start offset, and match
+option arguments (substitute-specific options can be added to the \fIoptions\fP
+argument). If any of these parameters is changed, \fBpcre2_substitute()\fP
+returns an error. The data in the \fImatch_data\fP block (return code, offset
+vector) is used for the first substitution instead of calling
+\fBpcre2_match()\fP from within \fBpcre2_substitute()\fP. This allows an
+application to check for a match before choosing to substitute, without having
+to repeat the match.
+.P
+If the contents of the subject buffer are mutated in between \fBpcre2_match()\fP
+and a call to \fBpcre2_substitute()\fP with PCRE2_SUBSTITUTE_MATCHED, the
+behaviour is unsafe; in particular, in this case, PCRE2 is unable to ensure that
+the offsets in the ovector point to the start of characters (with UTF-encoded
+input).
+.P
+The contents of the externally supplied match data block are not changed when
+PCRE2_SUBSTITUTE_MATCHED is set, and so the match block is permitted for use in
+another call using PCRE2_SUBSTITUTE_MATCHED. If PCRE2_SUBSTITUTE_GLOBAL is also
+set, \fBpcre2_match()\fP is called after the first substitution to check for
+furthe matches, but this is done using an internally obtained match data block,
+thus always leaving the external block unchanged.
+.P
+The \fIcode\fP argument is not used for matching before the first substitution
+when PCRE2_SUBSTITUTE_MATCHED is set, but it must be provided, even when
+PCRE2_SUBSTITUTE_GLOBAL is not set, because it contains information such as the
+UTF setting and the number of capturing parentheses in the pattern.
+.P
+When using PCRE2_SUBSTITUTE_MATCHED, you should not modify the subject string
+in between the prior call to \fBpcre2_match()\fP and \fBpcre2_substitute()\fP,
+as the substitution assumes that the passed-in ovector is compatible with the
+subject string. Although PCRE2 does verify that the subject is a pointer to the
+same buffer, it cannot in general verify whether the contents of the buffer have
+changed. For example, if the subject buffer is mutated from one valid UTF-8
+string to another valid string, of the same length in code units, the ovector
+offsets are no longer guaranteed to point to the start of a character. Beware
+that with PCRE2_SUBSTITUTE_MATCHED in UTF mode, the subject string is not
+re-scanned for UTF validity when \fBpcre2_substitute()\fP first uses it.
+.P
+The default action of \fBpcre2_substitute()\fP is to return a copy of the
+subject string with matched substrings replaced. However, if
+PCRE2_SUBSTITUTE_REPLACEMENT_ONLY is set, only the replacement substrings are
+returned. In the global case, multiple replacements are concatenated in the
+output buffer. Substitution callouts (see
+.\" HTML
+.\"
+below)
+.\"
+can be used to separate them if necessary.
+.P
+Partial matching is supported, with limitations: if matching succeeds but with a
+partial match, then pcre2_substitute returns PCRE2_ERROR_PARTIAL. When
+partial-matching (either of PCRE2_PARTIAL_HARD or PCRE2_PARTIAL_SOFT is passed),
+then PCRE2_SUBSTITUTE_REPLACEMENT_ONLY must also be set, or else
+PCRE2_ERROR_BADOPTION is returned. Similarly, certain replacement items
+($' and $_) cause PCRE2_ERROR_PARTIALSUBS to be returned when partial-matching,
+even if a complete match is found.
+.P
+The \fIoutlengthptr\fP argument of \fBpcre2_substitute()\fP must point to a
+variable that contains the length, in code units, of the output buffer. If the
+function is successful, the value is updated to contain the length in code
+units of the new string, excluding the trailing zero that is automatically
+added.
+.P
+If the function is not successful, the value set via \fIoutlengthptr\fP depends
+on the type of error. For syntax errors in the replacement string, the value is
+the offset in the replacement string where the error was detected. For other
+errors, the value is PCRE2_UNSET by default. This includes the case of the
+output buffer being too small, unless PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set.
+.P
+PCRE2_SUBSTITUTE_OVERFLOW_LENGTH changes what happens when the output buffer is
+too small. The default action is to return PCRE2_ERROR_NOMEMORY immediately. If
+this option is set, however, \fBpcre2_substitute()\fP continues to go through
+the motions of matching and substituting (without, of course, writing anything)
+in order to compute the size of buffer that is needed, which will include the
+extra space for the terminating NUL. This value is passed back via the
+\fIoutlengthptr\fP variable, with the result of the function still being
+PCRE2_ERROR_NOMEMORY.
+.P
+Passing a buffer size of zero is a permitted way of finding out how much memory
+is needed for given substitution. However, this does mean that the entire
+operation is carried out twice. Depending on the application, it may be more
+efficient to allocate a large buffer and free the excess afterwards, instead of
+using PCRE2_SUBSTITUTE_OVERFLOW_LENGTH.
+.P
+The replacement string, which is interpreted as a UTF string in UTF mode, is
+checked for UTF validity unless PCRE2_NO_UTF_CHECK is set. An invalid UTF
+replacement string causes an immediate return with the relevant UTF error code.
+.P
+If PCRE2_SUBSTITUTE_LITERAL is set, the replacement string is not interpreted
+in any way. By default, however, a dollar character is an escape character that
+can specify the insertion of characters from capture groups and names from
+(*MARK) or other control verbs in the pattern. Dollar is the only escape
+character (backslash is treated as literal). The following forms are
+recognized:
+.sp
+ $$ insert a dollar character
+ $n or ${n} insert the contents of group \fIn\fP
+ $0 or $& insert the entire matched substring
+ $` insert the substring that precedes the match
+ $' insert the substring that follows the match
+ $_ insert the entire input string
+ $+ insert the highest-numbered capture group which matched
+ $*MARK or ${*MARK} insert a control verb name
+.sp
+Either a group number or a group name can be given for \fIn\fP, for example $2
+or $NAME. Curly brackets are required only if the following character would be
+interpreted as part of the number or name. The number may be zero to include
+the entire matched string. For example, if the pattern a(b)c is matched with
+"=abc=" and the replacement string "+$1$0$1+", the result is "=+babcb+=".
+.P
+The JavaScript form $, where the angle brackets are part of the syntax,
+is also recognized for group names, but not for group numbers or *MARK.
+.P
+$*MARK inserts the name from the last encountered backtracking control verb on
+the matching path that has a name. (*MARK) must always include a name, but the
+other verbs need not. For example, in the case of (*MARK:A)(*PRUNE) the name
+inserted is "A", but for (*MARK:A)(*PRUNE:B) the relevant name is "B". This
+facility can be used to perform simple simultaneous substitutions, as this
+\fBpcre2test\fP example shows:
+.sp
+ /(*MARK:pear)apple|(*MARK:orange)lemon/g,replace=${*MARK}
+ apple lemon
+ 2: pear orange
+.sp
+PCRE2_SUBSTITUTE_GLOBAL causes the function to iterate over the subject string,
+replacing every matching substring. If this option is not set, only the first
+matching substring is replaced. The search for matches takes place in the
+original subject string (that is, previous replacements do not affect it).
+Iteration is implemented by advancing the \fIstartoffset\fP value for each
+search, which is always passed the entire subject string. If an offset limit is
+set in the match context, searching stops when that limit is reached.
+.P
+Because global substitutions apply the pattern repeatedly to the subject string,
+and always iterate over non-overlapping matches, the substitutions done by
+\fBpcre2_substitute()\fP do not match and substitute text inside the replacement
+strings themselves (no recursive/iterative substitution). However, applications
+can easily implement other alternative replacement strategies, such as
+iteratively replacing, then matching and replacing on the result. The
+replacement loop inside \fBpcre2_substitute()\fP is simple and can be emulated
+in client code by allocating a buffer, searching for matches in a loop, and
+calling \fBpcre2_substitute()\fP with PCRE2_SUBSTITUTE_REPLACEMENT_ONLY an
+PCRE2_SUBSTITUTE_MATCHED, and without PCRE2_SUBSTITUTE_GLOBAL.
+.P
+You can restrict the effect of a global substitution to a portion of the
+subject string by setting either or both of \fIstartoffset\fP and an offset
+limit. Here is a \fBpcre2test\fP example:
+.sp
+ /B/g,replace=!,use_offset_limit
+ ABC ABC ABC ABC\e=offset=3,offset_limit=12
+ 2: ABC A!C A!C ABC
+.sp
+When continuing with global substitutions after matching a substring with zero
+length, an attempt to find a non-empty match at the same offset is performed.
+If this is not successful, the offset is advanced by one character except when
+CRLF is a valid newline sequence and the next two characters are CR, LF. In
+this case, the offset is advanced by two characters.
+.P
+PCRE2_SUBSTITUTE_UNKNOWN_UNSET causes references to capture groups that do
+not appear in the pattern to be treated as unset groups. This option should be
+used with care, because it means that a typo in a group name or number no
+longer causes the PCRE2_ERROR_NOSUBSTRING error.
+.P
+PCRE2_SUBSTITUTE_UNSET_EMPTY causes unset capture groups (including unknown
+groups when PCRE2_SUBSTITUTE_UNKNOWN_UNSET is set) to be treated as empty
+strings when inserted as described above. If this option is not set, an attempt
+to insert an unset group causes the PCRE2_ERROR_UNSET error. This option does
+not influence the extended substitution syntax described below.
+.P
+PCRE2_SUBSTITUTE_EXTENDED causes extra processing to be applied to the
+replacement string. Without this option, only the dollar character is special,
+and only the group insertion forms listed above are valid. When
+PCRE2_SUBSTITUTE_EXTENDED is set, several things change:
+.P
+Firstly, backslash in a replacement string is interpreted as an escape
+character. The usual forms such as \ex{ddd} can be used to specify particular
+character codes, and backslash followed by any non-alphanumeric character
+quotes that character. Extended quoting can be coded using \eQ...\eE, exactly
+as in pattern strings. The escapes \eb and \ev are interpreted as the
+characters backspace and vertical tab, respectively.
+.P
+The interpretation of backslash followed by one or more digits is the same as
+in a pattern, which in Perl has some ambiguities. Details are given in the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+page.
+.P
+The Python form \eg, where the angle brackets are part of the syntax and
+\fIn\fP is either a group name or number, is recognized as an alternative way
+of inserting the contents of a group, for example \eg<3>.
+.P
+There are also four escape sequences for forcing the case of inserted letters.
+Case forcing applies to all inserted characters, including those from capture
+groups and letters within \eQ...\eE quoted sequences. The insertion mechanism
+has three states: no case forcing, force upper case, and force lower case. The
+escape sequences change the current state: \eU and \eL change to upper or lower
+case forcing, respectively, and \eE (when not terminating a \eQ quoted
+sequence) reverts to no case forcing. The sequences \eu and \el force the next
+character (if it is a letter) to upper or lower case, respectively, and then
+the state automatically reverts to no case forcing.
+.P
+However, if \eu is immediately followed by \eL or \el is immediately followed
+by \eU, the next character's case is forced by the first escape sequence, and
+subsequent characters by the second. This provides a "title casing" facility
+that can be applied to group captures. For example, if group 1 has captured
+"heLLo", the replacement string "\eu\eL$1" becomes "Hello".
+.P
+If either PCRE2_UTF or PCRE2_UCP was set when the pattern was compiled, Unicode
+properties are used for case forcing characters whose code points are greater
+than 127. However, only simple case folding, as determined by the Unicode file
+\fBCaseFolding.txt\fP is supported. PCRE2 does not support language-specific
+special casing rules such as using different lower case Greek sigmas in the
+middle and ends of words (as defined in the Unicode file
+\fBSpecialCasing.txt\fP).
+.P
+Note that case forcing sequences such as \eU...\eE do not nest. For example,
+the result of processing "\eUaa\eLBB\eEcc\eE" is "AAbbcc"; the final \eE has no
+effect. Note also that the PCRE2_ALT_BSUX and PCRE2_EXTRA_ALT_BSUX options do
+not apply to replacement strings.
+.P
+The final effect of setting PCRE2_SUBSTITUTE_EXTENDED is to add more
+flexibility to capture group substitution. The syntax is similar to that used
+by Bash:
+.sp
+ ${n:-string}
+ ${n:+string1:string2}
+.sp
+As in the simple case, \fIn\fP may be a group number or a name. The first form
+specifies a default value. If group \fIn\fP is set, its value is inserted; if
+not, the string is expanded and the result inserted. The second form specifies
+strings that are expanded and inserted when group \fIn\fP is set or unset,
+respectively. The first form is just a convenient shorthand for
+.sp
+ ${n:+${n}:string}
+.sp
+Backslash can be used to escape colons and closing curly brackets in the
+replacement strings. A change of the case forcing state within a replacement
+string remains in force afterwards, as shown in this \fBpcre2test\fP example:
+.sp
+ /(some)?(body)/substitute_extended,replace=${1:+\eU:\eL}HeLLo
+ body
+ 1: hello
+ somebody
+ 1: HELLO
+.sp
+The PCRE2_SUBSTITUTE_UNSET_EMPTY option does not affect these extended
+substitutions. However, PCRE2_SUBSTITUTE_UNKNOWN_UNSET does cause unknown
+groups in the extended syntax forms to be treated as unset.
+.P
+If PCRE2_SUBSTITUTE_LITERAL is set, PCRE2_SUBSTITUTE_UNKNOWN_UNSET,
+PCRE2_SUBSTITUTE_UNSET_EMPTY, and PCRE2_SUBSTITUTE_EXTENDED are irrelevant and
+are ignored.
+.
+.
+.SS "Substitution errors"
+.rs
+.sp
+In the event of an error, \fBpcre2_substitute()\fP returns a negative error
+code. Except for PCRE2_ERROR_NOMATCH (which is never returned), errors from
+\fBpcre2_match()\fP are passed straight back.
+.P
+PCRE2_ERROR_NOSUBSTRING is returned for a non-existent substring insertion,
+unless PCRE2_SUBSTITUTE_UNKNOWN_UNSET is set.
+.P
+PCRE2_ERROR_UNSET is returned for an unset substring insertion (including an
+unknown substring when PCRE2_SUBSTITUTE_UNKNOWN_UNSET is set) when the simple
+(non-extended) syntax is used and PCRE2_SUBSTITUTE_UNSET_EMPTY is not set.
+.P
+PCRE2_ERROR_NOMEMORY is returned if the output buffer is not big enough. If the
+PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option is set, the size of buffer that is
+needed is returned via \fIoutlengthptr\fP. Note that this does not happen by
+default.
+.P
+PCRE2_ERROR_NULL is returned if PCRE2_SUBSTITUTE_MATCHED is set but the
+\fImatch_data\fP argument is NULL or if the \fIsubject\fP or \fIreplacement\fP
+arguments are NULL. For backward compatibility reasons an exception is made for
+the \fIreplacement\fP argument if the \fIrlength\fP argument is also 0.
+.P
+PCRE2_ERROR_BADREPLACEMENT is used for miscellaneous syntax errors in the
+replacement string, with more particular errors being PCRE2_ERROR_BADREPESCAPE
+(invalid escape sequence), PCRE2_ERROR_REPMISSINGBRACE (closing curly bracket
+not found), PCRE2_ERROR_BADSUBSTITUTION (syntax error in extended group
+substitution), and PCRE2_ERROR_BADSUBSPATTERN (the pattern match ended before
+it started or the match started earlier than the current position in the
+subject, which can happen if \eK is used in a lookaround assertion).
+.P
+As for all PCRE2 errors, a text message that describes the error can be
+obtained by calling the \fBpcre2_get_error_message()\fP function (see
+"Obtaining a textual error message"
+.\" HTML
+.\"
+above).
+.\"
+.
+.
+.\" HTML
+.SS "Substitution callouts"
+.rs
+.sp
+.nf
+.B int pcre2_set_substitute_callout(pcre2_match_context *\fImcontext\fP,
+.B " int (*\fIcallout_function\fP)(pcre2_substitute_callout_block *, void *),"
+.B " void *\fIcallout_data\fP);"
+.fi
+.sp
+The \fBpcre2_set_substitute_callout()\fP function can be used to specify a
+callout function for \fBpcre2_substitute()\fP. This information is passed in
+a match context. The callout function is called after each substitution has
+been processed, but it can cause the replacement not to happen.
+.P
+The callout function is not called for simulated substitutions that happen as a
+result of the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option. In this mode, when
+substitution processing exceeds the buffer space provided by the caller,
+processing continues by counting code units. The simulation is unable to
+populate the callout block, and so the simulation is pessimistic about the
+required buffer size. Whichever is larger of accepted or rejected substitution
+is reported as the required size. Therefore, the returned buffer length may be
+an overestimate (without a substitution callout, it is normally an exact
+measurement).
+.P
+The first argument of the callout function is a pointer to a substitute callout
+block structure, which contains the following fields, not necessarily in this
+order:
+.sp
+ uint32_t \fIversion\fP;
+ uint32_t \fIsubscount\fP;
+ PCRE2_SPTR \fIinput\fP;
+ PCRE2_SPTR \fIoutput\fP;
+ PCRE2_SIZE \fI*ovector\fP;
+ uint32_t \fIoveccount\fP;
+ PCRE2_SIZE \fIoutput_offsets[2]\fP;
+.sp
+The \fIversion\fP field contains the version number of the block format. The
+current version is 0. The version number will increase in future if more fields
+are added, but the intention is never to remove any of the existing fields.
+.P
+The \fIsubscount\fP field is the number of the current match. It is 1 for the
+first callout, 2 for the second, and so on. The \fIinput\fP and \fIoutput\fP
+pointers are copies of the values passed to \fBpcre2_substitute()\fP.
+.P
+The \fIovector\fP field points to the ovector, which contains the result of the
+most recent match. The \fIoveccount\fP field contains the number of pairs that
+are set in the ovector, and is always greater than zero.
+.P
+The \fIoutput_offsets\fP vector contains the offsets of the replacement in the
+output string. This has already been processed for dollar and (if requested)
+backslash substitutions as described above.
+.P
+The second argument of the callout function is the value passed as
+\fIcallout_data\fP when the function was registered. The value returned by the
+callout function is interpreted as follows:
+.P
+If the value is zero, the replacement is accepted, and, if
+PCRE2_SUBSTITUTE_GLOBAL is set, processing continues with a search for the next
+match. If the value is not zero, the current replacement is not accepted. If
+the value is greater than zero, processing continues when
+PCRE2_SUBSTITUTE_GLOBAL is set. Otherwise (the value is less than zero or
+PCRE2_SUBSTITUTE_GLOBAL is not set), the rest of the input is copied to the
+output and the call to \fBpcre2_substitute()\fP exits, returning the number of
+matches so far.
+.
+.
+.SS "Substitution case callouts"
+.rs
+.sp
+.nf
+.B int pcre2_set_substitute_case_callout(pcre2_match_context *\fImcontext\fP,
+.B " PCRE2_SIZE (*\fIcallout_function\fP)(PCRE2_SPTR, PCRE2_SIZE,"
+.B " PCRE2_UCHAR *, PCRE2_SIZE,"
+.B " int, void *),"
+.B " void *\fIcallout_data\fP);"
+.fi
+.sp
+The \fBpcre2_set_substitute_case_callout()\fP function can be used to specify
+a callout function for \fBpcre2_substitute()\fP to use when performing case
+transformations. This does not affect any case insensitivity behaviour when
+performing a match, but only the user-visible transformations performed when
+processing a substitution such as:
+.sp
+ pcre2_substitute(..., "\e\eU$1", ...)
+.P
+The default case transformations applied by PCRE2 are reasonably complete, and,
+in UTF or UCP mode, perform the simple locale-invariant case transformations as
+specified by Unicode. This is suitable for the internal (invisible)
+case-equivalence procedures used during pattern matching, but an application
+may wish to use more sophisticated locale-aware processing for the user-visible
+substitution transformations.
+.P
+One example implementation of the \fIcallout_function\fP using the ICU
+library would be:
+.sp
+.nf
+ PCRE2_SIZE
+ icu_case_callout(
+ PCRE2_SPTR input, PCRE2_SIZE input_len,
+ PCRE2_UCHAR *output, PCRE2_SIZE output_cap,
+ int to_case, void *data_ptr)
+ {
+ UErrorCode err = U_ZERO_ERROR;
+ int32_t r = to_case == PCRE2_SUBSTITUTE_CASE_LOWER
+ ? u_strToLower(output, output_cap, input, input_len, NULL, &err)
+ : to_case == PCRE2_SUBSTITUTE_CASE_UPPER
+ ? u_strToUpper(output, output_cap, input, input_len, NULL, &err)
+ : u_strToTitle(output, output_cap, input, input_len, &first_char_only,
+ NULL, &err);
+ if (U_FAILURE(err)) return (~(PCRE2_SIZE)0);
+ return r;
+ }
+.fi
+.P
+The first and second arguments of the case callout function are the Unicode
+string to transform.
+.P
+The third and fourth arguments are the output buffer and its capacity.
+.P
+The fifth is one of the constants PCRE2_SUBSTITUTE_CASE_LOWER,
+PCRE2_SUBSTITUTE_CASE_UPPER, or PCRE2_SUBSTITUTE_CASE_TITLE_FIRST.
+PCRE2_SUBSTITUTE_CASE_LOWER and PCRE2_SUBSTITUTE_CASE_UPPER are passed to the
+callout to indicate that the case of the entire callout input should be
+case-transformed. PCRE2_SUBSTITUTE_CASE_TITLE_FIRST is passed to indicate that
+only the first character or glyph should be transformed to Unicode titlecase
+and the rest to Unicode lowercase (note that titlecasing sometimes uses Unicode
+properties to titlecase each word in a string; but PCRE2 is requesting that only
+the single leading character is to be titlecased).
+.P
+The sixth argument is the \fIcallout_data\fP supplied to
+\fBpcre2_set_substitute_case_callout()\fP.
+.P
+The resulting string in the destination buffer may be larger or smaller than the
+input, if the casing rules merge or split characters. The return value is the
+length required for the output string. If a buffer of sufficient size was
+provided to the callout, then the result must be written to the buffer and the
+number of code units returned. If the result does not fit in the provided
+buffer, then the required capacity must be returned and PCRE2 will not make use
+of the output buffer. PCRE2 provides input and output buffers which overlap, so
+the callout must support this by suitable internal buffering.
+.P
+Alternatively, if the callout wishes to indicate an error, then it may return
+(~(PCRE2_SIZE)0). In this case pcre2_substitute() will immediately fail with
+error PCRE2_ERROR_REPLACECASE.
+.P
+When a case callout is combined with the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+option, there are situations when pcre2_substitute() will return an
+underestimate of the required buffer size. If you call pcre2_substitute() once
+with PCRE2_SUBSTITUTE_OVERFLOW_LENGTH, and the input buffer is too small for
+the replacement string to be constructed, then instead of calling the case
+callout, pcre2_substitute() will make an estimate of the required buffer size.
+The second call should also pass PCRE2_SUBSTITUTE_OVERFLOW_LENGTH, because that
+second call is not guaranteed to succeed either, if the case callout requires
+more buffer space than expected. The caller must make repeated attempts in a
+loop.
+.
+.
+.SH "DUPLICATE CAPTURE GROUP NAMES"
+.rs
+.sp
+.nf
+.B int pcre2_substring_nametable_scan(const pcre2_code *\fIcode\fP,
+.B " PCRE2_SPTR \fIname\fP, PCRE2_SPTR *\fIfirst\fP, PCRE2_SPTR *\fIlast\fP);"
+.fi
+.P
+When a pattern is compiled with the PCRE2_DUPNAMES option, names for capture
+groups are not required to be unique. Duplicate names are always allowed for
+groups with the same number, created by using the (?| feature. Indeed, if such
+groups are named, they are required to use the same names.
+.P
+Normally, patterns that use duplicate names are such that in any one match,
+only one of each set of identically-named groups participates. An example is
+shown in the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+documentation.
+.P
+When duplicates are present, \fBpcre2_substring_copy_byname()\fP and
+\fBpcre2_substring_get_byname()\fP return the first substring corresponding to
+the given name that is set. Only if none are set is PCRE2_ERROR_UNSET is
+returned. The \fBpcre2_substring_number_from_name()\fP function returns the
+error PCRE2_ERROR_NOUNIQUESUBSTRING when there are duplicate names.
+.P
+If you want to get full details of all captured substrings for a given name,
+you must use the \fBpcre2_substring_nametable_scan()\fP function. The first
+argument is the compiled pattern, and the second is the name. If the third and
+fourth arguments are NULL, the function returns a group number for a unique
+name, or PCRE2_ERROR_NOUNIQUESUBSTRING otherwise.
+.P
+When the third and fourth arguments are not NULL, they must be pointers to
+variables that are updated by the function. After it has run, they point to the
+first and last entries in the name-to-number table for the given name, and the
+function returns the length of each entry in code units. In both cases,
+PCRE2_ERROR_NOSUBSTRING is returned if there are no entries for the given name.
+.P
+The format of the name table is described
+.\" HTML
+.\"
+above
+.\"
+in the section entitled \fIInformation about a pattern\fP. Given all the
+relevant entries for the name, you can extract each of their numbers, and hence
+the captured data.
+.
+.
+.SH "FINDING ALL POSSIBLE MATCHES AT ONE POSITION"
+.rs
+.sp
+The traditional matching function uses a similar algorithm to Perl, which stops
+when it finds the first match at a given point in the subject. If you want to
+find all possible matches, or the longest possible match at a given position,
+consider using the alternative matching function (see below) instead. If you
+cannot use the alternative function, you can kludge it up by making use of the
+callout facility, which is described in the
+.\" HREF
+\fBpcre2callout\fP
+.\"
+documentation.
+.P
+What you have to do is to insert a callout right at the end of the pattern.
+When your callout function is called, extract and save the current matched
+substring. Then return 1, which forces \fBpcre2_match()\fP to backtrack and try
+other alternatives. Ultimately, when it runs out of matches,
+\fBpcre2_match()\fP will yield PCRE2_ERROR_NOMATCH.
+.
+.
+.\" HTML
+.SH "MATCHING A PATTERN: THE ALTERNATIVE FUNCTION"
+.rs
+.sp
+.nf
+.B int pcre2_dfa_match(const pcre2_code *\fIcode\fP, PCRE2_SPTR \fIsubject\fP,
+.B " PCRE2_SIZE \fIlength\fP, PCRE2_SIZE \fIstartoffset\fP,"
+.B " uint32_t \fIoptions\fP, pcre2_match_data *\fImatch_data\fP,"
+.B " pcre2_match_context *\fImcontext\fP,"
+.B " int *\fIworkspace\fP, PCRE2_SIZE \fIwscount\fP);"
+.fi
+.P
+The function \fBpcre2_dfa_match()\fP is called to match a subject string
+against a compiled pattern, using a matching algorithm that scans the subject
+string just once (not counting lookaround assertions), and does not backtrack
+(except when processing lookaround assertions). This has different
+characteristics to the normal algorithm, and is not compatible with Perl. Some
+of the features of PCRE2 patterns are not supported. Nevertheless, there are
+times when this kind of matching can be useful. For a discussion of the two
+matching algorithms, and a list of features that \fBpcre2_dfa_match()\fP does
+not support, see the
+.\" HREF
+\fBpcre2matching\fP
+.\"
+documentation.
+.P
+The arguments for the \fBpcre2_dfa_match()\fP function are the same as for
+\fBpcre2_match()\fP, plus two extras. The ovector within the match data block
+is used in a different way, and this is described below. The other common
+arguments are used in the same way as for \fBpcre2_match()\fP, so their
+description is not repeated here.
+.P
+The two additional arguments provide workspace for the function. The workspace
+vector should contain at least 20 elements. It is used for keeping track of
+multiple paths through the pattern tree. More workspace is needed for patterns
+and subjects where there are a lot of potential matches.
+.P
+Here is an example of a simple call to \fBpcre2_dfa_match()\fP:
+.sp
+ int wspace[20];
+ pcre2_match_data *md = pcre2_match_data_create(4, NULL);
+ int rc = pcre2_dfa_match(
+ re, /* result of pcre2_compile() */
+ "some string", /* the subject string */
+ 11, /* the length of the subject string */
+ 0, /* start at offset 0 in the subject */
+ 0, /* default options */
+ md, /* the match data block */
+ NULL, /* a match context; NULL means use defaults */
+ wspace, /* working space vector */
+ 20); /* number of elements (NOT size in bytes) */
+.
+.SS "Option bits for \fBpcre2_dfa_match()\fP"
+.rs
+.sp
+The unused bits of the \fIoptions\fP argument for \fBpcre2_dfa_match()\fP must
+be zero. The only bits that may be set are PCRE2_ANCHORED,
+PCRE2_COPY_MATCHED_SUBJECT, PCRE2_ENDANCHORED, PCRE2_NOTBOL, PCRE2_NOTEOL,
+PCRE2_NOTEMPTY, PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD,
+PCRE2_PARTIAL_SOFT, PCRE2_DFA_SHORTEST, and PCRE2_DFA_RESTART. All but the last
+four of these are exactly the same as for \fBpcre2_match()\fP, so their
+description is not repeated here.
+.sp
+ PCRE2_PARTIAL_HARD
+ PCRE2_PARTIAL_SOFT
+.sp
+These have the same general effect as they do for \fBpcre2_match()\fP, but the
+details are slightly different. When PCRE2_PARTIAL_HARD is set for
+\fBpcre2_dfa_match()\fP, it returns PCRE2_ERROR_PARTIAL if the end of the
+subject is reached and there is still at least one matching possibility that
+requires additional characters. This happens even if some complete matches have
+already been found. When PCRE2_PARTIAL_SOFT is set, the return code
+PCRE2_ERROR_NOMATCH is converted into PCRE2_ERROR_PARTIAL if the end of the
+subject is reached, there have been no complete matches, but there is still at
+least one matching possibility. The portion of the string that was inspected
+when the longest partial match was found is set as the first matching string in
+both cases. There is a more detailed discussion of partial and multi-segment
+matching, with examples, in the
+.\" HREF
+\fBpcre2partial\fP
+.\"
+documentation.
+.sp
+ PCRE2_DFA_SHORTEST
+.sp
+Setting the PCRE2_DFA_SHORTEST option causes the matching algorithm to stop as
+soon as it has found one match. Because of the way the alternative algorithm
+works, this is necessarily the shortest possible match at the first possible
+matching point in the subject string.
+.sp
+ PCRE2_DFA_RESTART
+.sp
+When \fBpcre2_dfa_match()\fP returns a partial match, it is possible to call it
+again, with additional subject characters, and have it continue with the same
+match. The PCRE2_DFA_RESTART option requests this action; when it is set, the
+\fIworkspace\fP and \fIwscount\fP options must reference the same vector as
+before because data about the match so far is left in them after a partial
+match. There is more discussion of this facility in the
+.\" HREF
+\fBpcre2partial\fP
+.\"
+documentation.
+.
+.
+.SS "Successful returns from \fBpcre2_dfa_match()\fP"
+.rs
+.sp
+When \fBpcre2_dfa_match()\fP succeeds, it may have matched more than one
+substring in the subject. Note, however, that all the matches from one run of
+the function start at the same point in the subject. The shorter matches are
+all initial substrings of the longer matches. For example, if the pattern
+.sp
+ <.*>
+.sp
+is matched against the string
+.sp
+ This is no more
+.sp
+the three matched strings are
+.sp
+
+
+
+.sp
+On success, the yield of the function is a number greater than zero, which is
+the number of matched substrings. The offsets of the substrings are returned in
+the ovector, and can be extracted by number in the same way as for
+\fBpcre2_match()\fP, but the numbers bear no relation to any capture groups
+that may exist in the pattern, because DFA matching does not support capturing.
+.P
+Calls to the convenience functions that extract substrings by name
+return the error PCRE2_ERROR_DFA_UFUNC (unsupported function) if used after a
+DFA match. The convenience functions that extract substrings by number never
+return PCRE2_ERROR_NOSUBSTRING.
+.P
+The matched strings are stored in the ovector in reverse order of length; that
+is, the longest matching string is first. If there were too many matches to fit
+into the ovector, the yield of the function is zero, and the vector is filled
+with the longest matches.
+.P
+NOTE: PCRE2's "auto-possessification" optimization usually applies to character
+repeats at the end of a pattern (as well as internally). For example, the
+pattern "a\ed+" is compiled as if it were "a\ed++". For DFA matching, this
+means that only one possible match is found. If you really do want multiple
+matches in such cases, either use an ungreedy repeat such as "a\ed+?" or set
+the PCRE2_NO_AUTO_POSSESS option when compiling.
+.
+.
+.SS "Error returns from \fBpcre2_dfa_match()\fP"
+.rs
+.sp
+The \fBpcre2_dfa_match()\fP function returns a negative number when it fails.
+Many of the errors are the same as for \fBpcre2_match()\fP, as described
+.\" HTML
+.\"
+above.
+.\"
+There are in addition the following errors that are specific to
+\fBpcre2_dfa_match()\fP:
+.sp
+ PCRE2_ERROR_DFA_UITEM
+.sp
+This return is given if \fBpcre2_dfa_match()\fP encounters an item in the
+pattern that it does not support, for instance, the use of \eC in a UTF mode or
+a backreference.
+.sp
+ PCRE2_ERROR_DFA_UCOND
+.sp
+This return is given if \fBpcre2_dfa_match()\fP encounters a condition item
+that uses a backreference for the condition, or a test for recursion in a
+specific capture group. These are not supported.
+.sp
+ PCRE2_ERROR_DFA_UINVALID_UTF
+.sp
+This return is given if \fBpcre2_dfa_match()\fP is called for a pattern that
+was compiled with PCRE2_MATCH_INVALID_UTF. This is not supported for DFA
+matching.
+.sp
+ PCRE2_ERROR_DFA_WSSIZE
+.sp
+This return is given if \fBpcre2_dfa_match()\fP runs out of space in the
+\fIworkspace\fP vector.
+.sp
+ PCRE2_ERROR_DFA_RECURSE
+.sp
+When a recursion or subroutine call is processed, the matching function calls
+itself recursively, using private memory for the ovector and \fIworkspace\fP.
+This error is given if the internal ovector is not large enough. This should be
+extremely rare, as a vector of size 1000 is used.
+.sp
+ PCRE2_ERROR_DFA_BADRESTART
+.sp
+When \fBpcre2_dfa_match()\fP is called with the \fBPCRE2_DFA_RESTART\fP option,
+some plausibility checks are made on the contents of the workspace, which
+should contain data about the previous partial match. If any of these checks
+fail, this error is given.
+.
+.
+.SH "SEE ALSO"
+.rs
+.sp
+\fBpcre2build\fP(3), \fBpcre2callout\fP(3), \fBpcre2demo(3)\fP,
+\fBpcre2matching\fP(3), \fBpcre2partial\fP(3), \fBpcre2posix\fP(3),
+\fBpcre2sample\fP(3), \fBpcre2unicode\fP(3).
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 08 December 2025
+Copyright (c) 1997-2024 University of Cambridge.
+.fi
diff --git a/doc/pcre2build.3 b/doc/pcre2build.3
new file mode 100644
index 0000000..1b9b712
--- /dev/null
+++ b/doc/pcre2build.3
@@ -0,0 +1,682 @@
+.TH PCRE2BUILD 3 "17 October 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.
+.
+.SH "BUILDING PCRE2"
+.rs
+.sp
+PCRE2 is distributed with a \fBconfigure\fP script that can be used to build
+the library in Unix-like environments using the Autotools applications. Also in
+the distribution are files to support building using \fBCMake\fP instead of
+\fBconfigure\fP. The text file
+.\" HTML
+.\"
+\fBREADME\fP
+.\"
+contains general information about building with Autotools (some of which is
+repeated below), and also has some comments about building on various operating
+systems. The files in the \fBvms\fP directory support building under OpenVMS.
+There is a lot more information about building PCRE2 without using
+Autotools (including information about using \fBCMake\fP and building "by
+hand") in the text file called
+.\" HTML
+.\"
+\fBNON-AUTOTOOLS-BUILD\fP.
+.\"
+You should consult this file as well as the
+.\" HTML
+.\"
+\fBREADME\fP
+.\"
+file if you are building in a non-Unix-like environment.
+.
+.
+.SH "PCRE2 BUILD-TIME OPTIONS"
+.rs
+.sp
+The rest of this document describes the optional features of PCRE2 that can be
+selected when the library is compiled. It assumes use of the \fBconfigure\fP
+script, where the optional features are selected or deselected by providing
+options to \fBconfigure\fP before running the \fBmake\fP command. However, the
+same options can be selected in both Unix-like and non-Unix-like environments
+if you are using \fBCMake\fP instead of \fBconfigure\fP to build PCRE2.
+.P
+If you are not using Autotools or \fBCMake\fP, option selection can be done by
+editing the \fBconfig.h\fP file, or by passing parameter settings to the
+compiler, as described in
+.\" HTML
+.\"
+\fBNON-AUTOTOOLS-BUILD\fP.
+.\"
+.P
+The complete list of options for \fBconfigure\fP (which includes the standard
+ones such as the selection of the installation directory) can be obtained by
+running
+.sp
+ ./configure --help
+.sp
+The following sections include descriptions of "on/off" options whose names
+begin with --enable or --disable. Because of the way that \fBconfigure\fP
+works, --enable and --disable always come in pairs, so the complementary option
+always exists as well, but as it specifies the default, it is not described.
+Options that specify values have names that start with --with. At the end of a
+\fBconfigure\fP run, a summary of the configuration is output.
+.
+.
+.SH "BUILDING 8-BIT, 16-BIT AND 32-BIT LIBRARIES"
+.rs
+.sp
+By default, a library called \fBlibpcre2-8\fP is built, containing functions
+that take string arguments contained in arrays of bytes, interpreted either as
+single-byte characters, or UTF-8 strings. You can also build two other
+libraries, called \fBlibpcre2-16\fP and \fBlibpcre2-32\fP, which process
+strings that are contained in arrays of 16-bit and 32-bit code units,
+respectively. These can be interpreted either as single-unit characters or
+UTF-16/UTF-32 strings. To build these additional libraries, add one or both of
+the following to the \fBconfigure\fP command:
+.sp
+ --enable-pcre2-16
+ --enable-pcre2-32
+.sp
+If you do not want the 8-bit library, add
+.sp
+ --disable-pcre2-8
+.sp
+as well. At least one of the three libraries must be built. Note that the POSIX
+wrapper is for the 8-bit library only, and that \fBpcre2grep\fP is an 8-bit
+program. Neither of these are built if you select only the 16-bit or 32-bit
+libraries.
+.
+.
+.SH "BUILDING SHARED AND STATIC LIBRARIES"
+.rs
+.sp
+The Autotools PCRE2 building process uses \fBlibtool\fP to build both shared
+and static libraries by default. You can suppress an unwanted library by adding
+one of
+.sp
+ --disable-shared
+ --disable-static
+.sp
+to the \fBconfigure\fP command. Setting --disable-shared ensures that PCRE2
+libraries are built as static libraries. The binaries that are then created as
+part of the build process (for example, \fBpcre2test\fP and \fBpcre2grep\fP)
+are linked statically with one or more PCRE2 libraries, but may also be
+dynamically linked with other libraries such as \fBlibc\fP. If you want these
+binaries to be fully statically linked, you can set LDFLAGS like this:
+.sp
+LDFLAGS=--static ./configure --disable-shared
+.sp
+Note the two hyphens in --static. Of course, this works only if static versions
+of all the relevant libraries are available for linking.
+.
+.
+.SH "UNICODE AND UTF SUPPORT"
+.rs
+.sp
+By default, PCRE2 is built with support for Unicode and UTF character strings.
+To build it without Unicode support, add
+.sp
+ --disable-unicode
+.sp
+to the \fBconfigure\fP command. This setting applies to all three libraries. It
+is not possible to build one library with Unicode support and another without
+in the same configuration.
+.P
+Of itself, Unicode support does not make PCRE2 treat strings as UTF-8, UTF-16
+or UTF-32. To do that, applications that use the library can set the PCRE2_UTF
+option when they call \fBpcre2_compile()\fP to compile a pattern.
+Alternatively, patterns may be started with (*UTF) unless the application has
+locked this out by setting PCRE2_NEVER_UTF.
+.P
+UTF support allows the libraries to process character code points up to
+0x10ffff in the strings that they handle. Unicode support also gives access to
+the Unicode properties of characters, using pattern escapes such as \eP, \ep,
+and \eX. Only the general category properties such as \fILu\fP and \fINd\fP,
+script names, and some bi-directional and binary properties are supported.
+Details are given in the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+documentation.
+.P
+Pattern escapes such as \ed and \ew do not by default make use of Unicode
+properties. The application can request that they do by setting the PCRE2_UCP
+option. Unless the application has set PCRE2_NEVER_UCP, a pattern may also
+request this by starting with (*UCP).
+.
+.
+.SH "DISABLING THE USE OF \eC"
+.rs
+.sp
+The \eC escape sequence, which matches a single code unit, even in a UTF mode,
+can cause unpredictable behaviour because it may leave the current matching
+point in the middle of a multi-code-unit character. The application can lock
+it out by setting the PCRE2_NEVER_BACKSLASH_C option when calling
+\fBpcre2_compile()\fP. There is also a build-time option
+.sp
+ --enable-never-backslash-C
+.sp
+(note the upper case C) which locks out the use of \eC entirely.
+.
+.
+.SH "JUST-IN-TIME COMPILER SUPPORT"
+.rs
+.sp
+Just-in-time (JIT) compiler support is included in the build by specifying
+.sp
+ --enable-jit
+.sp
+This support is available only for certain hardware architectures. If this
+option is set for an unsupported architecture, a building error occurs.
+If in doubt, use
+.sp
+ --enable-jit=auto
+.sp
+which enables JIT only if the current hardware is supported. You can check
+if JIT is enabled in the configuration summary that is output at the end of a
+\fBconfigure\fP run. If you are enabling JIT under SELinux you may also want to
+add
+.sp
+ --enable-jit-sealloc
+.sp
+which enables the use of an execmem allocator in JIT that is compatible with
+SELinux. This has no effect if JIT is not enabled. See the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+documentation for a discussion of JIT usage. When JIT support is enabled,
+\fBpcre2grep\fP automatically makes use of it, unless you add
+.sp
+ --disable-pcre2grep-jit
+.sp
+to the \fBconfigure\fP command.
+.
+.
+.SH "NEWLINE RECOGNITION"
+.rs
+.sp
+By default, PCRE2 interprets the linefeed (LF) character as indicating the end
+of a line. This is the normal newline character on Unix-like systems. You can
+compile PCRE2 to use carriage return (CR) instead, by adding
+.sp
+ --enable-newline-is-cr
+.sp
+to the \fBconfigure\fP command. There is also an --enable-newline-is-lf option,
+which explicitly specifies linefeed as the newline character.
+.P
+Alternatively, you can specify that line endings are to be indicated by the
+two-character sequence CRLF (CR immediately followed by LF). If you want this,
+add
+.sp
+ --enable-newline-is-crlf
+.sp
+to the \fBconfigure\fP command. There is a fourth option, specified by
+.sp
+ --enable-newline-is-anycrlf
+.sp
+which causes PCRE2 to recognize any of the three sequences CR, LF, or CRLF as
+indicating a line ending. A fifth option, specified by
+.sp
+ --enable-newline-is-any
+.sp
+causes PCRE2 to recognize any Unicode newline sequence. The Unicode newline
+sequences are the three just mentioned, plus the single characters VT (vertical
+tab, U+000B), FF (form feed, U+000C), NEL (next line, U+0085), LS (line
+separator, U+2028), and PS (paragraph separator, U+2029). The final option is
+.sp
+ --enable-newline-is-nul
+.sp
+which causes NUL (binary zero) to be set as the default line-ending character.
+.P
+Whatever default line ending convention is selected when PCRE2 is built can be
+overridden by applications that use the library. At build time it is
+recommended to use the standard for your operating system.
+.
+.
+.SH "WHAT \eR MATCHES"
+.rs
+.sp
+By default, the sequence \eR in a pattern matches any Unicode newline sequence,
+independently of what has been selected as the line ending sequence. If you
+specify
+.sp
+ --enable-bsr-anycrlf
+.sp
+the default is changed so that \eR matches only CR, LF, or CRLF. Whatever is
+selected when PCRE2 is built can be overridden by applications that use the
+library.
+.
+.
+.SH "HANDLING VERY LARGE PATTERNS"
+.rs
+.sp
+Within a compiled pattern, offset values are used to point from one part to
+another (for example, from an opening parenthesis to an alternation
+metacharacter). By default, in the 8-bit and 16-bit libraries, two-byte values
+are used for these offsets, leading to a maximum size for a compiled pattern of
+around 64 thousand code units. This is sufficient to handle all but the most
+gigantic patterns. Nevertheless, some people do want to process truly enormous
+patterns, so it is possible to compile PCRE2 to use three-byte or four-byte
+offsets by adding a setting such as
+.sp
+ --with-link-size=3
+.sp
+to the \fBconfigure\fP command. The value given must be 2, 3, or 4. For the
+16-bit library, a value of 3 is rounded up to 4. In these libraries, using
+longer offsets slows down the operation of PCRE2 because it has to load
+additional data when handling them. For the 32-bit library the value is always
+4 and cannot be overridden; the value of --with-link-size is ignored.
+.
+.
+.SH "LIMITING PCRE2 RESOURCE USAGE"
+.rs
+.sp
+The \fBpcre2_match()\fP function increments a counter each time it goes round
+its main loop. Putting a limit on this counter controls the amount of computing
+resource used by a single call to \fBpcre2_match()\fP. The limit can be changed
+at run time, as described in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation. The default is 10 million, but this can be changed by adding a
+setting such as
+.sp
+ --with-match-limit=500000
+.sp
+to the \fBconfigure\fP command. This setting also applies to the
+\fBpcre2_dfa_match()\fP matching function, and to JIT matching (though the
+counting is done differently).
+.P
+The \fBpcre2_match()\fP function uses heap memory to record backtracking
+points. The more nested backtracking points there are (that is, the deeper the
+search tree), the more memory is needed. There is an upper limit, specified in
+kibibytes (units of 1024 bytes). This limit can be changed at run time, as
+described in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation. The default limit (in effect unlimited) is 20 million. You can
+change this by a setting such as
+.sp
+ --with-heap-limit=500
+.sp
+which limits the amount of heap to 500 KiB. This limit applies only to
+interpretive matching in \fBpcre2_match()\fP and \fBpcre2_dfa_match()\fP, which
+may also use the heap for internal workspace when processing complicated
+patterns. This limit does not apply when JIT (which has its own memory
+arrangements) is used.
+.P
+You can also explicitly limit the depth of nested backtracking in the
+\fBpcre2_match()\fP interpreter. This limit defaults to the value that is set
+for --with-match-limit. You can set a lower default limit by adding, for
+example,
+.sp
+ --with-match-limit-depth=10000
+.sp
+to the \fBconfigure\fP command. This value can be overridden at run time. This
+depth limit indirectly limits the amount of heap memory that is used, but
+because the size of each backtracking "frame" depends on the number of
+capturing parentheses in a pattern, the amount of heap that is used before the
+limit is reached varies from pattern to pattern. This limit was more useful in
+versions before 10.30, where function recursion was used for backtracking.
+.P
+As well as applying to \fBpcre2_match()\fP, the depth limit also controls
+the depth of recursive function calls in \fBpcre2_dfa_match()\fP. These are
+used for lookaround assertions, atomic groups, and recursion within patterns.
+The limit does not apply to JIT matching.
+.
+.
+.SH "LIMITING VARIABLE-LENGTH LOOKBEHIND ASSERTIONS"
+.rs
+.sp
+Lookbehind assertions in which one or more branches can match a variable number
+of characters are supported only if there is a maximum matching length for each
+top-level branch. There is a limit to this maximum that defaults to 255
+characters. You can alter this default by a setting such as
+.sp
+ --with-max-varlookbehind=100
+.sp
+The limit can be changed at runtime by calling
+\fBpcre2_set_max_varlookbehind()\fP. Lookbehind assertions in which every
+branch matches a fixed number of characters (not necessarily all the same) are
+not constrained by this limit.
+.
+.
+.\" HTML
+.SH "CREATING CHARACTER TABLES AT BUILD TIME"
+.rs
+.sp
+PCRE2 uses fixed tables for processing characters whose code points are less
+than 256. By default, PCRE2 is built with a set of tables that are distributed
+in the file \fIsrc/pcre2_chartables.c.dist\fP. These tables are for ASCII codes
+only. If you add
+.sp
+ --enable-rebuild-chartables
+.sp
+to the \fBconfigure\fP command, the distributed tables are no longer used.
+Instead, a program called \fBpcre2_dftables\fP is compiled and run. This
+outputs the source for new set of tables, created in the default locale of your
+C run-time system. This method of replacing the tables does not work if you are
+cross compiling, because \fBpcre2_dftables\fP needs to be run on the local
+host and therefore not compiled with the cross compiler.
+.P
+If you need to create alternative tables when cross compiling, you will have to
+do so "by hand". There may also be other reasons for creating tables manually.
+To cause \fBpcre2_dftables\fP to be built on the local host, run a normal
+compiling command, and then run the program with the output file as its
+argument, for example:
+.sp
+ cc src/pcre2_dftables.c -o pcre2_dftables
+ ./pcre2_dftables src/pcre2_chartables.c
+.sp
+This builds the tables in the default locale of the local host. If you want to
+specify a locale, you must use the -L option:
+.sp
+ LC_ALL=fr_FR ./pcre2_dftables -L src/pcre2_chartables.c
+.sp
+You can also specify -b (with or without -L). This causes the tables to be
+written in binary instead of as source code. A set of binary tables can be
+loaded into memory by an application and passed to \fBpcre2_compile()\fP in the
+same way as tables created by calling \fBpcre2_maketables()\fP. The tables are
+just a string of bytes, independent of hardware characteristics such as
+endianness. This means they can be bundled with an application that runs in
+different environments, to ensure consistent behaviour.
+.
+.
+.SH "USING EBCDIC CODE"
+.rs
+.sp
+PCRE2 assumes by default that it will run in an environment where the character
+code is ASCII or Unicode, which is a superset of ASCII. This is the case for
+most computer operating systems. PCRE2 can, however, be compiled to run in an
+8-bit EBCDIC environment by adding
+.sp
+ --enable-ebcdic --disable-unicode
+.sp
+to the \fBconfigure\fP command. You should only use it if you know that you are
+in an EBCDIC environment (for example, an IBM mainframe operating system).
+.P
+This setting implies --enable-rebuild-chartables, in order to ensure that you
+have the correct default character tables for your system's codepage. There is
+an exception when you set --enable-ebcdic-ignoring-compiler (see below), which
+allows using a default set of EBCDIC 1047 character tables rather than forcing
+use of --enable-rebuild-chartables.
+.P
+It is not supported to enable both EBCDIC input and either ASCII or UTF-8/16/32
+in the same build of the library. When PCRE2 is built with EBCDIC support, it
+always operates in EBCDIC, and consequently --enable-unicode and --enable-ebcdic
+are mutually exclusive.
+.P
+The EBCDIC character that corresponds to an ASCII LF is assumed to have the
+value 0x15 by default. However, in some EBCDIC environments, 0x25 is used. In
+such an environment you should use
+.sp
+ --enable-ebcdic-nl25
+.sp
+(which implies --enable-ebcdic). The EBCDIC character for CR has the same value
+as in ASCII, namely, 0x0d. Whichever of 0x15 and 0x25 is \fInot\fP chosen as LF
+is made to correspond to the Unicode NEL character (which, in Unicode, is 0x85).
+.P
+The options that select newline behaviour, such as --enable-newline-is-cr,
+and equivalent run-time options, refer to these character values in an EBCDIC
+environment.
+.P
+On systems requiring an EBCDIC build of PCRE2, the compiler should be set to use
+the correct codepage, so that C character literals such as 'z' use the correct
+numeric value for whichever EBCDIC codpage is in use. (PCRE2 cannot support
+multiple EBCDIC codepages dynamically.) However, if this not possible, then you
+can use
+.sp
+ --enable-ebcdic-ignoring-compiler
+.sp
+in order to disregard the compiler's codepage, and instead force PCRE2 to use
+numeric constants corresponding to the EBCDIC 1047 codepage instead. This can be
+used to build (or test) EBCDIC support on an ASCII/UTF-8 system such as Linux.
+.
+.
+.SH "PCRE2GREP SUPPORT FOR EXTERNAL SCRIPTS"
+.rs
+.sp
+By default \fBpcre2grep\fP supports the use of callouts with string arguments
+within the patterns it is matching. There are two kinds: one that generates
+output using local code, and another that calls an external program or script.
+If --disable-pcre2grep-callout-fork is added to the \fBconfigure\fP command,
+only the first kind of callout is supported; if --disable-pcre2grep-callout is
+used, all callouts are completely ignored. For more details of \fBpcre2grep\fP
+callouts, see the
+.\" HREF
+\fBpcre2grep\fP
+.\"
+documentation.
+.
+.
+.SH "PCRE2GREP OPTIONS FOR COMPRESSED FILE SUPPORT"
+.rs
+.sp
+By default, \fBpcre2grep\fP reads all files as plain text. You can build it so
+that it recognizes files whose names end in \fB.gz\fP or \fB.bz2\fP, and reads
+them with \fBlibz\fP or \fBlibbz2\fP, respectively, by adding one or both of
+.sp
+ --enable-pcre2grep-libz
+ --enable-pcre2grep-libbz2
+.sp
+to the \fBconfigure\fP command. These options naturally require that the
+relevant libraries are installed on your system. Configuration will fail if
+they are not.
+.
+.
+.SH "PCRE2GREP BUFFER SIZE"
+.rs
+.sp
+\fBpcre2grep\fP uses an internal buffer to hold a "window" on the file it is
+scanning, in order to be able to output "before" and "after" lines when it
+finds a match. The default starting size of the buffer is 20KiB. The buffer
+itself is three times this size, but because of the way it is used for holding
+"before" lines, the longest line that is guaranteed to be processable is the
+notional buffer size. If a longer line is encountered, \fBpcre2grep\fP
+automatically expands the buffer, up to a specified maximum size, whose default
+is 1MiB or the starting size, whichever is the larger. You can change the
+default parameter values by adding, for example,
+.sp
+ --with-pcre2grep-bufsize=51200
+ --with-pcre2grep-max-bufsize=2097152
+.sp
+to the \fBconfigure\fP command. The caller of \fBpcre2grep\fP can override
+these values by using --buffer-size and --max-buffer-size on the command line.
+.
+.
+.SH "PCRE2TEST OPTION FOR LIBREADLINE SUPPORT"
+.rs
+.sp
+If you add one of
+.sp
+ --enable-pcre2test-libreadline
+ --enable-pcre2test-libedit
+.sp
+to the \fBconfigure\fP command, \fBpcre2test\fP is linked with the
+\fBlibreadline\fP or\fBlibedit\fP library, respectively, and when its input is
+from a terminal, it reads it using the \fBreadline()\fP function. This provides
+line-editing and history facilities. Note that \fBlibreadline\fP is
+GPL-licensed, so if you distribute a binary of \fBpcre2test\fP linked in this
+way, there may be licensing issues. These can be avoided by linking instead
+with \fBlibedit\fP, which has a BSD licence.
+.P
+Setting --enable-pcre2test-libreadline causes the \fB-lreadline\fP option to be
+added to the \fBpcre2test\fP build. In many operating environments with a
+system-installed readline library this is sufficient. However, in some
+environments (e.g. if an unmodified distribution version of readline is in
+use), some extra configuration may be necessary. The INSTALL file for
+\fBlibreadline\fP says this:
+.sp
+ "Readline uses the termcap functions, but does not link with
+ the termcap or curses library itself, allowing applications
+ which link with readline the to choose an appropriate library."
+.sp
+If your environment has not been set up so that an appropriate library is
+automatically included, you may need to add something like
+.sp
+ LIBS="-lncurses"
+.sp
+immediately before the \fBconfigure\fP command.
+.
+.
+.SH "INCLUDING DEBUGGING CODE"
+.rs
+.sp
+If you add
+.sp
+ --enable-debug
+.sp
+to the \fBconfigure\fP command, additional debugging code is included in the
+build. This feature is intended for use by the PCRE2 maintainers.
+.
+.
+.SH "DEBUGGING WITH VALGRIND SUPPORT"
+.rs
+.sp
+If you add
+.sp
+ --enable-valgrind
+.sp
+to the \fBconfigure\fP command, PCRE2 will use valgrind annotations to mark
+certain memory regions as unaddressable. This allows it to detect invalid
+memory accesses, and is mostly useful for debugging PCRE2 itself.
+.
+.
+.SH "CODE COVERAGE REPORTING"
+.rs
+.sp
+If your C compiler is gcc, you can build a version of PCRE2 that can generate a
+code coverage report for its test suite. To enable this, you must install
+\fBlcov\fP version 1.6 or above. Then specify
+.sp
+ --enable-coverage
+.sp
+to the \fBconfigure\fP command and build PCRE2 in the usual way.
+.P
+Note that using \fBccache\fP (a caching C compiler) is incompatible with code
+coverage reporting. If you have configured \fBccache\fP to run automatically
+on your system, you must set the environment variable
+.sp
+ CCACHE_DISABLE=1
+.sp
+before running \fBmake\fP to build PCRE2, so that \fBccache\fP is not used.
+.P
+When --enable-coverage is used, the following addition targets are added to the
+\fIMakefile\fP:
+.sp
+ make coverage
+.sp
+This creates a fresh coverage report for the PCRE2 test suite. It is equivalent
+to running "make coverage-reset", "make coverage-baseline", "make check", and
+then "make coverage-report".
+.sp
+ make coverage-reset
+.sp
+This zeroes the coverage counters, but does nothing else.
+.sp
+ make coverage-baseline
+.sp
+This captures baseline coverage information.
+.sp
+ make coverage-report
+.sp
+This creates the coverage report.
+.sp
+ make coverage-clean-report
+.sp
+This removes the generated coverage report without cleaning the coverage data
+itself.
+.sp
+ make coverage-clean-data
+.sp
+This removes the captured coverage data without removing the coverage files
+created at compile time (*.gcno).
+.sp
+ make coverage-clean
+.sp
+This cleans all coverage data including the generated coverage report. For more
+information about code coverage, see the \fBgcov\fP and \fBlcov\fP
+documentation.
+.
+.
+.SH "DISABLING THE Z AND T FORMATTING MODIFIERS"
+.rs
+.sp
+The C99 standard defines formatting modifiers z and t for size_t and
+ptrdiff_t values, respectively. By default, PCRE2 uses these modifiers in
+environments other than old versions of Microsoft Visual Studio when
+__STDC_VERSION__ is defined and has a value greater than or equal to 199901L
+(indicating support for C99).
+However, there is at least one environment that claims to be C99 but does not
+support these modifiers. If
+.sp
+ --disable-percent-zt
+.sp
+is specified, no use is made of the z or t modifiers. Instead of %td or %zu,
+a suitable format is used depending in the size of long for the platform.
+.
+.
+.SH "SUPPORT FOR FUZZERS"
+.rs
+.sp
+There is a special option for use by people who want to run fuzzing tests on
+PCRE2:
+.sp
+ --enable-fuzz-support
+.sp
+At present this applies only to the 8-bit library. If set, it causes an extra
+library called libpcre2-fuzzsupport.a to be built, but not installed. This
+contains a single function called LLVMFuzzerTestOneInput() whose arguments are
+a pointer to a string and the length of the string. When called, this function
+tries to compile the string as a pattern, and if that succeeds, to match it.
+This is done both with no options and with some random options bits that are
+generated from the string.
+.P
+Setting --enable-fuzz-support also causes a binary called \fBpcre2fuzzcheck\fP
+to be created. This is normally run under valgrind or used when PCRE2 is
+compiled with address sanitizing enabled. It calls the fuzzing function and
+outputs information about what it is doing. The input strings are specified by
+arguments: if an argument starts with "=" the rest of it is a literal input
+string. Otherwise, it is assumed to be a file name, and the contents of the
+file are the test string.
+.
+.
+.SH "OBSOLETE OPTION"
+.rs
+.sp
+In versions of PCRE2 prior to 10.30, there were two ways of handling
+backtracking in the \fBpcre2_match()\fP function. The default was to use the
+system stack, but if
+.sp
+ --disable-stack-for-recursion
+.sp
+was set, memory on the heap was used. From release 10.30 onwards this has
+changed (the stack is no longer used) and this option now does nothing except
+give a warning.
+.
+.SH "SEE ALSO"
+.rs
+.sp
+\fBpcre2api\fP(3), \fBpcre2-config\fP(3).
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 17 October 2025
+Copyright (c) 1997-2024 University of Cambridge.
+.fi
diff --git a/doc/pcre2callout.3 b/doc/pcre2callout.3
new file mode 100644
index 0000000..a00ecf5
--- /dev/null
+++ b/doc/pcre2callout.3
@@ -0,0 +1,456 @@
+.TH PCRE2CALLOUT 3 "26 February 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH SYNOPSIS
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int (*pcre2_callout)(pcre2_callout_block *, void *);
+.sp
+.B int pcre2_callout_enumerate(const pcre2_code *\fIcode\fP,
+.B " int (*\fIcallback\fP)(pcre2_callout_enumerate_block *, void *),"
+.B " void *\fIuser_data\fP);"
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+PCRE2 provides a feature called "callout", which is a means of temporarily
+passing control to the caller of PCRE2 in the middle of pattern matching. The
+caller of PCRE2 provides an external function by putting its entry point in
+a match context (see \fBpcre2_set_callout()\fP in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation).
+.P
+When using the \fBpcre2_substitute()\fP function, an additional callout feature
+is available. This does a callout after each change to the subject string and
+is described in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation; the rest of this document is concerned with callouts during
+pattern matching.
+.P
+Within a regular expression, (?C) indicates a point at which the external
+function is to be called. Different callout points can be identified by putting
+a number less than 256 after the letter C. The default value is zero.
+Alternatively, the argument may be a delimited string. The starting delimiter
+must be one of ` ' " ^ % # $ { and the ending delimiter is the same as the
+start, except for {, where the ending delimiter is }. If the ending delimiter
+is needed within the string, it must be doubled. For example, this pattern has
+two callout points:
+.sp
+ (?C1)abc(?C"some ""arbitrary"" text")def
+.sp
+If the PCRE2_AUTO_CALLOUT option bit is set when a pattern is compiled, PCRE2
+automatically inserts callouts, all with number 255, before each item in the
+pattern except for immediately before or after an explicit callout. For
+example, if PCRE2_AUTO_CALLOUT is used with the pattern
+.sp
+ A(?C3)B
+.sp
+it is processed as if it were
+.sp
+ (?C255)A(?C3)B(?C255)
+.sp
+Here is a more complicated example:
+.sp
+ A(\ed{2}|--)
+.sp
+With PCRE2_AUTO_CALLOUT, this pattern is processed as if it were
+.sp
+ (?C255)A(?C255)((?C255)\ed{2}(?C255)|(?C255)-(?C255)-(?C255))(?C255)
+.sp
+Notice that there is a callout before and after each parenthesis and
+alternation bar. If the pattern contains a conditional group whose condition is
+an assertion, an automatic callout is inserted immediately before the
+condition. Such a callout may also be inserted explicitly, for example:
+.sp
+ (?(?C9)(?=a)ab|de) (?(?C%text%)(?!=d)ab|de)
+.sp
+This applies only to assertion conditions (because they are themselves
+independent groups).
+.P
+Callouts can be useful for tracking the progress of pattern matching. The
+.\" HREF
+\fBpcre2test\fP
+.\"
+program has a pattern qualifier (/auto_callout) that sets automatic callouts.
+When any callouts are present, the output from \fBpcre2test\fP indicates how
+the pattern is being matched. This is useful information when you are trying to
+optimize the performance of a particular pattern.
+.
+.
+.SH "MISSING CALLOUTS"
+.rs
+.sp
+You should be aware that, because of optimizations in the way PCRE2 compiles
+and matches patterns, callouts sometimes do not happen exactly as you might
+expect.
+.
+.
+.SS "Auto-possessification"
+.rs
+.sp
+At compile time, PCRE2 "auto-possessifies" repeated items when it knows that
+what follows cannot be part of the repeat. For example, a+[bc] is compiled as
+if it were a++[bc]. The \fBpcre2test\fP output when this pattern is compiled
+with PCRE2_ANCHORED and PCRE2_AUTO_CALLOUT and then applied to the string
+"aaaa" is:
+.sp
+ --->aaaa
+ +0 ^ a+
+ +2 ^ ^ [bc]
+ No match
+.sp
+This indicates that when matching [bc] fails, there is no backtracking into a+
+(because it is being treated as a++) and therefore the callouts that would be
+taken for the backtracks do not occur. You can disable the auto-possessify
+feature by passing PCRE2_NO_AUTO_POSSESS to \fBpcre2_compile()\fP, or starting
+the pattern with (*NO_AUTO_POSSESS). In this case, the output changes to this:
+.sp
+ --->aaaa
+ +0 ^ a+
+ +2 ^ ^ [bc]
+ +2 ^ ^ [bc]
+ +2 ^ ^ [bc]
+ +2 ^^ [bc]
+ No match
+.sp
+This time, when matching [bc] fails, the matcher backtracks into a+ and tries
+again, repeatedly, until a+ itself fails.
+.
+.
+.SS "Automatic .* anchoring"
+.rs
+.sp
+By default, an optimization is applied when .* is the first significant item in
+a pattern. If PCRE2_DOTALL is set, so that the dot can match any character, the
+pattern is automatically anchored. If PCRE2_DOTALL is not set, a match can
+start only after an internal newline or at the beginning of the subject, and
+\fBpcre2_compile()\fP remembers this. If a pattern has more than one top-level
+branch, automatic anchoring occurs if all branches are anchorable.
+.P
+This optimization is disabled, however, if .* is in an atomic group or if there
+is a backreference to the capture group in which it appears. It is also
+disabled if the pattern contains (*PRUNE) or (*SKIP). However, the presence of
+callouts does not affect it.
+.P
+For example, if the pattern .*\ed is compiled with PCRE2_AUTO_CALLOUT and
+applied to the string "aa", the \fBpcre2test\fP output is:
+.sp
+ --->aa
+ +0 ^ .*
+ +2 ^ ^ \ed
+ +2 ^^ \ed
+ +2 ^ \ed
+ No match
+.sp
+This shows that all match attempts start at the beginning of the subject. In
+other words, the pattern is anchored. You can disable this optimization by
+passing PCRE2_NO_DOTSTAR_ANCHOR to \fBpcre2_compile()\fP, or starting the
+pattern with (*NO_DOTSTAR_ANCHOR). In this case, the output changes to:
+.sp
+ --->aa
+ +0 ^ .*
+ +2 ^ ^ \ed
+ +2 ^^ \ed
+ +2 ^ \ed
+ +0 ^ .*
+ +2 ^^ \ed
+ +2 ^ \ed
+ No match
+.sp
+This shows more match attempts, starting at the second subject character.
+Another optimization, described in the next section, means that there is no
+subsequent attempt to match with an empty subject.
+.
+.
+.SS "Other optimizations"
+.rs
+.sp
+Other optimizations that provide fast "no match" results also affect callouts.
+For example, if the pattern is
+.sp
+ ab(?C4)cd
+.sp
+PCRE2 knows that any matching string must contain the letter "d". If the
+subject string is "abyz", the lack of "d" means that matching doesn't ever
+start, and the callout is never reached. However, with "abyd", though the
+result is still no match, the callout is obeyed.
+.P
+For most patterns PCRE2 also knows the minimum length of a matching string, and
+will immediately give a "no match" return without actually running a match if
+the subject is not long enough, or, for unanchored patterns, if it has been
+scanned far enough.
+.P
+You can disable these optimizations by passing the PCRE2_NO_START_OPTIMIZE
+option to \fBpcre2_compile()\fP, or by starting the pattern with
+(*NO_START_OPT). This slows down the matching process, but does ensure that
+callouts such as the example above are obeyed.
+.
+.
+.\" HTML
+.SH "THE CALLOUT INTERFACE"
+.rs
+.sp
+During matching, when PCRE2 reaches a callout point, if an external function is
+provided in the match context, it is called. This applies to both normal,
+DFA, and JIT matching. The first argument to the callout function is a pointer
+to a \fBpcre2_callout\fP block. The second argument is the void * callout data
+that was supplied when the callout was set up by calling
+\fBpcre2_set_callout()\fP (see the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation). The callout block structure contains the following fields, not
+necessarily in this order:
+.sp
+ uint32_t \fIversion\fP;
+ uint32_t \fIcallout_number\fP;
+ uint32_t \fIcapture_top\fP;
+ uint32_t \fIcapture_last\fP;
+ uint32_t \fIcallout_flags\fP;
+ PCRE2_SIZE *\fIoffset_vector\fP;
+ PCRE2_SPTR \fImark\fP;
+ PCRE2_SPTR \fIsubject\fP;
+ PCRE2_SIZE \fIsubject_length\fP;
+ PCRE2_SIZE \fIstart_match\fP;
+ PCRE2_SIZE \fIcurrent_position\fP;
+ PCRE2_SIZE \fIpattern_position\fP;
+ PCRE2_SIZE \fInext_item_length\fP;
+ PCRE2_SIZE \fIcallout_string_offset\fP;
+ PCRE2_SIZE \fIcallout_string_length\fP;
+ PCRE2_SPTR \fIcallout_string\fP;
+.sp
+The \fIversion\fP field contains the version number of the block format. The
+current version is 2; the three callout string fields were added for version 1,
+and the \fIcallout_flags\fP field for version 2. If you are writing an
+application that might use an earlier release of PCRE2, you should check the
+version number before accessing any of these fields. The version number will
+increase in future if more fields are added, but the intention is never to
+remove any of the existing fields.
+.
+.
+.SS "Fields for numerical callouts"
+.rs
+.sp
+For a numerical callout, \fIcallout_string\fP is NULL, and \fIcallout_number\fP
+contains the number of the callout, in the range 0-255. This is the number
+that follows (?C for callouts that part of the pattern; it is 255 for
+automatically generated callouts.
+.
+.
+.SS "Fields for string callouts"
+.rs
+.sp
+For callouts with string arguments, \fIcallout_number\fP is always zero, and
+\fIcallout_string\fP points to the string that is contained within the compiled
+pattern. Its length is given by \fIcallout_string_length\fP. Duplicated ending
+delimiters that were present in the original pattern string have been turned
+into single characters, but there is no other processing of the callout string
+argument. An additional code unit containing binary zero is present after the
+string, but is not included in the length. The delimiter that was used to start
+the string is also stored within the pattern, immediately before the string
+itself. You can access this delimiter as \fIcallout_string\fP[-1] if you need
+it.
+.P
+The \fIcallout_string_offset\fP field is the code unit offset to the start of
+the callout argument string within the original pattern string. This is
+provided for the benefit of applications such as script languages that might
+need to report errors in the callout string within the pattern.
+.
+.
+.SS "Fields for all callouts"
+.rs
+.sp
+The remaining fields in the callout block are the same for both kinds of
+callout.
+.P
+The \fIoffset_vector\fP field is a pointer to a vector of capturing offsets
+(the "ovector"). You may read the elements in this vector, but you must not
+change any of them.
+.P
+For calls to \fBpcre2_match()\fP, the \fIoffset_vector\fP field is not (since
+release 10.30) a pointer to the actual ovector that was passed to the matching
+function in the match data block. Instead it points to an internal ovector of a
+size large enough to hold all possible captured substrings in the pattern. Note
+that whenever a recursion or subroutine call within a pattern completes, the
+capturing state is reset to what it was before.
+.P
+The \fIcapture_last\fP field contains the number of the most recently captured
+substring, and the \fIcapture_top\fP field contains one more than the number of
+the highest numbered captured substring so far. If no substrings have yet been
+captured, the value of \fIcapture_last\fP is 0 and the value of
+\fIcapture_top\fP is 1. The values of these fields do not always differ by one;
+for example, when the callout in the pattern ((a)(b))(?C2) is taken,
+\fIcapture_last\fP is 1 but \fIcapture_top\fP is 4.
+.P
+The contents of ovector[2] to ovector[*2-1] can be inspected in
+order to extract substrings that have been matched so far, in the same way as
+extracting substrings after a match has completed. The values in ovector[0] and
+ovector[1] are always PCRE2_UNSET because the match is by definition not
+complete. Substrings that have not been captured but whose numbers are less
+than \fIcapture_top\fP also have both of their ovector slots set to
+PCRE2_UNSET.
+.P
+For DFA matching, the \fIoffset_vector\fP field points to the ovector that was
+passed to the matching function in the match data block for callouts at the top
+level, but to an internal ovector during the processing of pattern recursions,
+lookarounds, and atomic groups. However, these ovectors hold no useful
+information because \fBpcre2_dfa_match()\fP does not support substring
+capturing. The value of \fIcapture_top\fP is always 1 and the value of
+\fIcapture_last\fP is always 0 for DFA matching.
+.P
+The \fIsubject\fP and \fIsubject_length\fP fields contain copies of the values
+that were passed to the matching function.
+.P
+The \fIstart_match\fP field normally contains the offset within the subject at
+which the current match attempt started. However, if the escape sequence \eK
+has been encountered, this value is changed to reflect the modified starting
+point. If the pattern is not anchored, the callout function may be called
+several times from the same point in the pattern for different starting points
+in the subject.
+.P
+The \fIcurrent_position\fP field contains the offset within the subject of the
+current match pointer.
+.P
+The \fIpattern_position\fP field contains the offset in the pattern string to
+the next item to be matched.
+.P
+The \fInext_item_length\fP field contains the length of the next item to be
+processed in the pattern string. When the callout is at the end of the pattern,
+the length is zero. When the callout precedes an opening parenthesis, the
+length includes meta characters that follow the parenthesis. For example, in a
+callout before an assertion such as (?=ab) the length is 3. For an alternation
+bar or a closing parenthesis, the length is one, unless a closing parenthesis
+is followed by a quantifier, in which case its length is included. (This
+changed in release 10.23. In earlier releases, before an opening parenthesis
+the length was that of the entire group, and before an alternation bar or a
+closing parenthesis the length was zero.)
+.P
+The \fIpattern_position\fP and \fInext_item_length\fP fields are intended to
+help in distinguishing between different automatic callouts, which all have the
+same callout number. However, they are set for all callouts, and are used by
+\fBpcre2test\fP to show the next item to be matched when displaying callout
+information.
+.P
+In callouts from \fBpcre2_match()\fP the \fImark\fP field contains a pointer to
+the zero-terminated name of the most recently passed (*MARK), (*PRUNE), or
+(*THEN) item in the match, or NULL if no such items have been passed. Instances
+of (*PRUNE) or (*THEN) without a name do not obliterate a previous (*MARK). In
+callouts from the DFA matching function this field always contains NULL.
+.P
+The \fIcallout_flags\fP field is always zero in callouts from
+\fBpcre2_dfa_match()\fP or when JIT is being used. When \fBpcre2_match()\fP
+without JIT is used, the following bits may be set:
+.sp
+ PCRE2_CALLOUT_STARTMATCH
+.sp
+This is set for the first callout after the start of matching for each new
+starting position in the subject.
+.sp
+ PCRE2_CALLOUT_BACKTRACK
+.sp
+This is set if there has been a matching backtrack since the previous callout,
+or since the start of matching if this is the first callout from a
+\fBpcre2_match()\fP run.
+.P
+Both bits are set when a backtrack has caused a "bumpalong" to a new starting
+position in the subject. Output from \fBpcre2test\fP does not indicate the
+presence of these bits unless the \fBcallout_extra\fP modifier is set.
+.P
+The information in the \fBcallout_flags\fP field is provided so that
+applications can track and tell their users how matching with backtracking is
+done. This can be useful when trying to optimize patterns, or just to
+understand how PCRE2 works. There is no support in \fBpcre2_dfa_match()\fP
+because there is no backtracking in DFA matching, and there is no support in
+JIT because JIT is all about maximimizing matching performance. In both these
+cases the \fBcallout_flags\fP field is always zero.
+.
+.
+.SH "RETURN VALUES FROM CALLOUTS"
+.rs
+.sp
+The external callout function returns an integer to PCRE2. If the value is
+zero, matching proceeds as normal. If the value is greater than zero, matching
+fails at the current point, but the testing of other matching possibilities
+goes ahead, just as if a lookahead assertion had failed. If the value is less
+than zero, the match is abandoned, and the matching function returns the
+negative value.
+.P
+Negative values should normally be chosen from the set of PCRE2_ERROR_xxx
+values. In particular, PCRE2_ERROR_NOMATCH forces a standard "no match"
+failure. The error number PCRE2_ERROR_CALLOUT is reserved for use by callout
+functions; it will never be used by PCRE2 itself.
+.
+.
+.SH "CALLOUT ENUMERATION"
+.rs
+.sp
+.nf
+.B int pcre2_callout_enumerate(const pcre2_code *\fIcode\fP,
+.B " int (*\fIcallback\fP)(pcre2_callout_enumerate_block *, void *),"
+.B " void *\fIuser_data\fP);"
+.fi
+.sp
+A script language that supports the use of string arguments in callouts might
+like to scan all the callouts in a pattern before running the match. This can
+be done by calling \fBpcre2_callout_enumerate()\fP. The first argument is a
+pointer to a compiled pattern, the second points to a callback function, and
+the third is arbitrary user data. The callback function is called for every
+callout in the pattern in the order in which they appear. Its first argument is
+a pointer to a callout enumeration block, and its second argument is the
+\fIuser_data\fP value that was passed to \fBpcre2_callout_enumerate()\fP. The
+data block contains the following fields:
+.sp
+ \fIversion\fP Block version number
+ \fIpattern_position\fP Offset to next item in pattern
+ \fInext_item_length\fP Length of next item in pattern
+ \fIcallout_number\fP Number for numbered callouts
+ \fIcallout_string_offset\fP Offset to string within pattern
+ \fIcallout_string_length\fP Length of callout string
+ \fIcallout_string\fP Points to callout string or is NULL
+.sp
+The version number is currently 0. It will increase if new fields are ever
+added to the block. The remaining fields are the same as their namesakes in the
+\fBpcre2_callout\fP block that is used for callouts during matching, as
+described
+.\" HTML
+.\"
+above.
+.\"
+.P
+Note that the value of \fIpattern_position\fP is unique for each callout.
+However, if a callout occurs inside a group that is quantified with a non-zero
+minimum or a fixed maximum, the group is replicated inside the compiled
+pattern. For example, a pattern such as /(a){2}/ is compiled as if it were
+/(a)(a)/. This means that the callout will be enumerated more than once, but
+with the same value for \fIpattern_position\fP in each case.
+.P
+The callback function should normally return zero. If it returns a non-zero
+value, scanning the pattern stops, and that value is returned from
+\fBpcre2_callout_enumerate()\fP.
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 26 February 2025
+Copyright (c) 1997-2024 University of Cambridge.
+.fi
diff --git a/doc/pcre2compat.3 b/doc/pcre2compat.3
new file mode 100644
index 0000000..9435a9d
--- /dev/null
+++ b/doc/pcre2compat.3
@@ -0,0 +1,260 @@
+.TH PCRE2COMPAT 3 "02 June 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH "DIFFERENCES BETWEEN PCRE2 AND PERL"
+.rs
+.sp
+This document describes some of the known differences in the ways that PCRE2
+and Perl handle regular expressions. The differences described here are with
+respect to Perl version 5.38.0, but as both Perl and PCRE2 are continually
+changing, the information may at times be out of date.
+.P
+1. When PCRE2_DOTALL (equivalent to Perl's /s qualifier) is not set, the
+behaviour of the '.' metacharacter differs from Perl. In PCRE2, '.' matches the
+next character unless it is the start of a newline sequence. This means that,
+if the newline setting is CR, CRLF, or NUL, '.' will match the code point LF
+(0x0A) in ASCII/Unicode environments, and NL (either 0x15 or 0x25) when using
+EBCDIC. In Perl, '.' appears never to match LF, even when 0x0A is not a newline
+indicator.
+.P
+2. PCRE2 has only a subset of Perl's Unicode support. Details of what it does
+have are given in the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+page.
+.P
+3. Like Perl, PCRE2 allows repeat quantifiers on parenthesized assertions, but
+they do not mean what you might think. For example, (?!a){3} does not assert
+that the next three characters are not "a". It just asserts that the next
+character is not "a" three times (in principle; PCRE2 optimizes this to run the
+assertion just once). Perl allows some repeat quantifiers on other assertions,
+for example, \eb* , but these do not seem to have any use. PCRE2 does not allow
+any kind of quantifier on non-lookaround assertions.
+.P
+4. If a braced quantifier such as {1,2} appears where there is nothing to
+repeat (for example, at the start of a branch), PCRE2 raises an error whereas
+Perl treats the quantifier characters as literal. When a braced quantifier
+(...){min,max} has min > max, Perl treats it as an item which fails to match
+any portion of the subject (as no number of repetitions can meet the
+condition), and additionally issues a warning when in warning mode. PCRE2 has
+no warning features, so it gives an error in this case.
+.P
+5. Capture groups that occur inside negative lookaround assertions are counted,
+but their entries in the offsets vector are set only when a negative assertion
+is a condition that has a matching branch (that is, the condition is false).
+Perl may set such capture groups in other circumstances.
+.P
+6. The following Perl escape sequences are not supported: \eF, \el, \eL, \eu,
+\eU, and \eN when followed by a character name. \eN on its own, matching a
+non-newline character, and \eN{U+dd..}, matching a Unicode code point, are
+supported. The escapes that modify the case of following letters are
+implemented by Perl's general string-handling and are not part of its pattern
+matching engine. If any of these are encountered by PCRE2, an error is
+generated by default. However, if either of the PCRE2_ALT_BSUX or
+PCRE2_EXTRA_ALT_BSUX options is set, \eU and \eu are interpreted as ECMAScript
+interprets them.
+.P
+7. The Perl escape sequences \ep, \eP, and \eX are supported only if PCRE2 is
+built with Unicode support (the default). The properties that can be tested
+with \ep and \eP are limited to the general category properties such as Lu and
+Nd, the derived properties Any and Lc (synonym L&), script names such as Greek
+or Han, Bidi_Class, Bidi_Control, and a few binary properties. Both PCRE2 and
+Perl support the Cs (surrogate) property, but in PCRE2 its use is limited. See
+the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+documentation for details. The long synonyms for property names that Perl
+supports (such as \ep{Letter}) are not supported by PCRE2, nor is it permitted
+to prefix any of these properties with "Is".
+.P
+8. PCRE2 supports the \eQ...\eE escape for quoting substrings. Characters
+in between are treated as literals. However, this is slightly different from
+Perl in that $ and @ are also handled as literals inside the quotes. In Perl,
+they cause variable interpolation (PCRE2 does not have variables). Also, Perl
+does "double-quotish backslash interpolation" on any backslashes between \eQ
+and \eE which, its documentation says, "may lead to confusing results". PCRE2
+treats a backslash between \eQ and \eE just like any other character. Note the
+following examples:
+.sp
+ Pattern PCRE2 matches Perl matches
+.sp
+.\" JOIN
+ \eQabc$xyz\eE abc$xyz abc followed by the
+ contents of $xyz
+ \eQabc\e$xyz\eE abc\e$xyz abc\e$xyz
+ \eQabc\eE\e$\eQxyz\eE abc$xyz abc$xyz
+ \eQA\eB\eE A\eB A\eB
+ \eQ\e\eE \e \e\eE
+.sp
+The \eQ...\eE sequence is recognized both inside and outside character classes
+by both PCRE2 and Perl. Another difference from Perl is that any appearance of
+\eQ or \eE inside what might otherwise be a quantifier causes PCRE2 not to
+recognize the sequence as a quantifier. Perl recognizes a quantifier if
+(redundantly) either of the numbers is inside \eQ...\eE, but not if the
+separating comma is. When not recognized as a quantifier a sequence such as
+{\eQ1\eE,2} is treated as the literal string "{1,2}".
+.P
+9. Fairly obviously, PCRE2 does not support the (?{code}) and (??{code})
+constructions. However, PCRE2 does have a "callout" feature, which allows an
+external function to be called during pattern matching. See the
+.\" HREF
+\fBpcre2callout\fP
+.\"
+documentation for details.
+.P
+10. Subroutine calls (whether recursive or not) were treated as atomic groups
+up to PCRE2 release 10.23, but from release 10.30 this changed, and
+backtracking into subroutine calls is now supported, as in Perl.
+.P
+11. In PCRE2, if any of the backtracking control verbs are used in a group that
+is called as a subroutine (whether or not recursively), their effect is
+confined to that group; it does not extend to the surrounding pattern. This is
+not always the case in Perl. In particular, if (*THEN) is present in a group
+that is called as a subroutine, its action is limited to that group, even if
+the group does not contain any | characters. Note that such groups are
+processed as anchored at the point where they are tested. PCRE2 also confines
+all control verbs within atomic assertions, again including (*THEN) in
+assertions with only one branch.
+.P
+12. If a pattern contains more than one backtracking control verb, the first
+one that is backtracked onto acts. For example, in the pattern
+A(*COMMIT)B(*PRUNE)C a failure in B triggers (*COMMIT), but a failure in C
+triggers (*PRUNE). Perl's behaviour is more complex; in many cases it is the
+same as PCRE2, but there are cases where it differs.
+.P
+13. There are some differences that are concerned with the settings of captured
+strings when part of a pattern is repeated. For example, matching "aba" against
+the pattern /^(a(b)?)+$/ in Perl leaves $2 unset, but in PCRE2 it is set to
+"b".
+.P
+14. PCRE2's handling of duplicate capture group numbers and names is not as
+general as Perl's. This is a consequence of the fact the PCRE2 works internally
+just with numbers, using an external table to translate between numbers and
+names. In particular, a pattern such as (?|(?A)|(?B)), where the two
+capture groups have the same number but different names, is not supported, and
+causes an error at compile time. If it were allowed, it would not be possible
+to distinguish which group matched, because both names map to capture group
+number 1. To avoid this confusing situation, an error is given at compile time.
+.P
+15. Perl used to recognize comments in some places that PCRE2 does not, for
+example, between the ( and ? at the start of a group. If the /x modifier is
+set, Perl allowed white space between ( and ? though the latest Perls give an
+error (for a while it was just deprecated). There may still be some cases where
+Perl behaves differently.
+.P
+16. Perl, when in warning mode, gives warnings for character classes such as
+[A-\ed] or [a-[:digit:]]. It then treats the hyphens as literals. PCRE2 has no
+warning features, so it gives an error in these cases because they are almost
+certainly user mistakes.
+.P
+17. In PCRE2, until release 10.45, the upper/lower case character properties Lu
+and Ll were not affected when case-independent matching was specified. Perl has
+changed in this respect, and PCRE2 has now changed to match. When caseless
+matching is in force, Lu, Ll, and Lt (title case) are all treated as Lc (cased
+letter).
+.P
+18. From release 5.32.0, Perl locks out the use of \eK in lookaround
+assertions. From release 10.38 PCRE2 does the same by default. However, there
+is an option for re-enabling the previous behaviour. When this option is set,
+\eK is acted on when it occurs in positive assertions, but is ignored in
+negative assertions.
+.P
+19. PCRE2 provides some extensions to the Perl regular expression facilities.
+Perl 5.10 included new features that were not in earlier versions of Perl, some
+of which (such as named parentheses) were in PCRE2 for some time before. This
+list is with respect to Perl 5.38:
+.sp
+(a) If PCRE2_DOLLAR_ENDONLY is set and PCRE2_MULTILINE is not set, the $
+meta-character matches only at the very end of the string.
+.sp
+(b) A backslash followed by a letter with no special meaning is faulted. (Perl
+can be made to issue a warning.)
+.sp
+(c) If PCRE2_UNGREEDY is set, the greediness of the repetition quantifiers is
+inverted, that is, by default they are not greedy, but if followed by a
+question mark they are.
+.sp
+(d) PCRE2_ANCHORED can be used at matching time to force a pattern to be tried
+only at the first matching position in the subject string.
+.sp
+(e) The PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY and PCRE2_NOTEMPTY_ATSTART
+options have no Perl equivalents.
+.sp
+(f) The \eR escape sequence can be restricted to match only CR, LF, or CRLF
+by the PCRE2_BSR_ANYCRLF option.
+.sp
+(g) The callout facility is PCRE2-specific. Perl supports codeblocks and
+variable interpolation, but not general hooks on every match.
+.sp
+(h) The partial matching facility is PCRE2-specific.
+.sp
+(i) The alternative matching function (\fBpcre2_dfa_match()\fP) matches in a
+different way and is not Perl-compatible.
+.sp
+(j) PCRE2 recognizes some special sequences such as (*CR) or (*NO_JIT) at
+the start of a pattern. These set overall options that cannot be changed within
+the pattern.
+.sp
+(k) PCRE2 supports non-atomic positive lookaround assertions. This is an
+extension to the lookaround facilities. The default, Perl-compatible
+lookarounds are atomic.
+.sp
+(l) There are three syntactical items in patterns that can refer to a capturing
+group by number: back references such as \eg{2}, subroutine calls such as (?3),
+and condition references such as (?(4)...). PCRE2 supports relative group
+numbers such as +2 and -4 in all three cases. Perl supports both plus and minus
+for subroutine calls, but only minus for back references, and no relative
+numbering at all for conditions.
+.sp
+(m) The scan substring assertion (syntax (*scs:(n)...)) is a PCRE2 extension
+that is not available in Perl.
+.P
+20. Perl has different limits than PCRE2. See the
+.\" HREF
+\fBpcre2limits\fP
+.\"
+documentation for details. Perl went with 5.10 from recursion to iteration
+keeping the intermediate matches on the heap, which is ~10% slower but does not
+fall into any stack-overflow limit. PCRE2 made a similar change at release
+10.30, and also has many build-time and run-time customizable limits.
+.P
+21. Unlike Perl, PCRE2 doesn't have character set modifiers and specially no way
+to set characters by context just like Perl's "/d". A regular expression using
+PCRE2_UTF and PCRE2_UCP will use similar rules to Perl's "/u"; something closer
+to "/a" could be selected by adding other PCRE2_EXTRA_ASCII* options on top.
+.P
+22. Some recursive patterns that Perl diagnoses as infinite recursions can be
+handled by PCRE2, either by the interpreter or the JIT. An example is
+/(?:|(?0)abcd)(?(R)|\ez)/, which matches a sequence of any number of repeated
+"abcd" substrings at the end of the subject.
+.P
+23. Both PCRE2 and Perl error when \ex{ escapes are invalid, but Perl tries to
+recover and prints a warning if the problem was that an invalid hexadecimal
+digit was found. Since PCRE2 doesn't have warnings it returns an error instead.
+Additionally, Perl accepts \ex{} and generates NUL unlike PCRE2.
+.P
+24. From release 10.45, PCRE2 gives an error if \ex is not followed by a
+hexadecimal digit or a curly bracket. It used to interpret this as the NUL
+character. Perl still generates NUL, but warns when in warning mode in most
+cases.
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 02 June 2025
+Copyright (c) 1997-2024 University of Cambridge.
+.fi
diff --git a/doc/pcre2convert.3 b/doc/pcre2convert.3
new file mode 100644
index 0000000..d227f47
--- /dev/null
+++ b/doc/pcre2convert.3
@@ -0,0 +1,164 @@
+.TH PCRE2CONVERT 3 "14 November 2023" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH "EXPERIMENTAL PATTERN CONVERSION FUNCTIONS"
+.rs
+.sp
+This document describes a set of functions that can be used to convert
+"foreign" patterns into PCRE2 regular expressions. This facility is currently
+experimental, and may be changed in future releases. Two kinds of pattern,
+globs and POSIX patterns, are supported.
+.
+.
+.SH "THE CONVERT CONTEXT"
+.rs
+.sp
+.nf
+.B pcre2_convert_context *pcre2_convert_context_create(
+.B " pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B pcre2_convert_context *pcre2_convert_context_copy(
+.B " pcre2_convert_context *\fIcvcontext\fP);"
+.sp
+.B void pcre2_convert_context_free(pcre2_convert_context *\fIcvcontext\fP);
+.sp
+.B int pcre2_set_glob_escape(pcre2_convert_context *\fIcvcontext\fP,
+.B " uint32_t \fIescape_char\fP);"
+.sp
+.B int pcre2_set_glob_separator(pcre2_convert_context *\fIcvcontext\fP,
+.B " uint32_t \fIseparator_char\fP);"
+.fi
+.sp
+A convert context is used to hold parameters that affect the way that pattern
+conversion works. Like all PCRE2 contexts, you need to use a context only if
+you want to override the defaults. There are the usual create, copy, and free
+functions. If custom memory management functions are set in a general context
+that is passed to \fBpcre2_convert_context_create()\fP, they are used for all
+memory management within the conversion functions.
+.P
+There are only two parameters in the convert context at present. Both apply
+only to glob conversions. The escape character defaults to grave accent under
+Windows, otherwise backslash. It can be set to zero, meaning no escape
+character, or to any punctuation character with a code point less than 256.
+The separator character defaults to backslash under Windows, otherwise forward
+slash. It can be set to forward slash, backslash, or dot.
+.P
+The two setting functions return zero on success, or PCRE2_ERROR_BADDATA if
+their second argument is invalid.
+.
+.
+.SH "THE CONVERSION FUNCTION"
+.rs
+.sp
+.nf
+.B int pcre2_pattern_convert(PCRE2_SPTR \fIpattern\fP, PCRE2_SIZE \fIlength\fP,
+.B " uint32_t \fIoptions\fP, PCRE2_UCHAR **\fIbuffer\fP,"
+.B " PCRE2_SIZE *\fIblength\fP, pcre2_convert_context *\fIcvcontext\fP);"
+.sp
+.B void pcre2_converted_pattern_free(PCRE2_UCHAR *\fIconverted_pattern\fP);
+.fi
+.sp
+The first two arguments of \fBpcre2_pattern_convert()\fP define the foreign
+pattern that is to be converted. The length may be given as
+PCRE2_ZERO_TERMINATED. The \fBoptions\fP argument defines how the pattern is to
+be processed. If the input is UTF, the PCRE2_CONVERT_UTF option should be set.
+PCRE2_CONVERT_NO_UTF_CHECK may also be set if you are sure the input is valid.
+One or more of the glob options, or one of the following POSIX options must be
+set to define the type of conversion that is required:
+.sp
+ PCRE2_CONVERT_GLOB
+ PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR
+ PCRE2_CONVERT_GLOB_NO_STARSTAR
+ PCRE2_CONVERT_POSIX_BASIC
+ PCRE2_CONVERT_POSIX_EXTENDED
+.sp
+Details of the conversions are given below. The \fBbuffer\fP and \fBblength\fP
+arguments define how the output is handled:
+.P
+If \fBbuffer\fP is NULL, the function just returns the length of the converted
+pattern via \fBblength\fP. This is one less than the length of buffer needed,
+because a terminating zero is always added to the output.
+.P
+If \fBbuffer\fP points to a NULL pointer, an output buffer is obtained using
+the allocator in the context or \fBmalloc()\fP if no context is supplied. A
+pointer to this buffer is placed in the variable to which \fBbuffer\fP points.
+When no longer needed the output buffer must be freed by calling
+\fBpcre2_converted_pattern_free()\fP. If this function is called with a NULL
+argument, it returns immediately without doing anything.
+.P
+If \fBbuffer\fP points to a non-NULL pointer, \fBblength\fP must be set to the
+actual length of the buffer provided (in code units).
+.P
+In all cases, after successful conversion, the variable pointed to by
+\fBblength\fP is updated to the length actually used (in code units), excluding
+the terminating zero that is always added.
+.P
+If an error occurs, the length (via \fBblength\fP) is set to the offset
+within the input pattern where the error was detected. Only gross syntax errors
+are caught; there are plenty of errors that will get passed on for
+\fBpcre2_compile()\fP to discover.
+.P
+The return from \fBpcre2_pattern_convert()\fP is zero on success or a non-zero
+PCRE2 error code. Note that PCRE2 error codes may be positive or negative:
+\fBpcre2_compile()\fP uses mostly positive codes and \fBpcre2_match()\fP
+negative ones; \fBpcre2_convert()\fP uses existing codes of both kinds. A
+textual error message can be obtained by calling
+\fBpcre2_get_error_message()\fP.
+.
+.
+.SH "CONVERTING GLOBS"
+.rs
+.sp
+Globs are used to match file names, and consequently have the concept of a
+"path separator", which defaults to backslash under Windows and forward slash
+otherwise. If PCRE2_CONVERT_GLOB is set, the wildcards * and ? are not
+permitted to match separator characters, but the double-star (**) feature
+(which does match separators) is supported.
+.P
+PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR matches globs with wildcards allowed to
+match separator characters. PCRE2_CONVERT_GLOB_NO_STARSTAR matches globs with
+the double-star feature disabled. These options may be given together.
+.
+.
+.SH "CONVERTING POSIX PATTERNS"
+.rs
+.sp
+POSIX defines two kinds of regular expression pattern: basic and extended.
+These can be processed by setting PCRE2_CONVERT_POSIX_BASIC or
+PCRE2_CONVERT_POSIX_EXTENDED, respectively.
+.P
+In POSIX patterns, backslash is not special in a character class. Unmatched
+closing parentheses are treated as literals.
+.P
+In basic patterns, ? + | {} and () must be escaped to be recognized
+as metacharacters outside a character class. If the first character in the
+pattern is * it is treated as a literal. ^ is a metacharacter only at the start
+of a branch.
+.P
+In extended patterns, a backslash not in a character class always
+makes the next character literal, whatever it is. There are no backreferences.
+.P
+Note: POSIX mandates that the longest possible match at the first matching
+position must be found. This is not what \fBpcre2_match()\fP does; it yields
+the first match that is found. An application can use \fBpcre2_dfa_match()\fP
+to find the longest match, but that does not support backreferences (but then
+neither do POSIX extended patterns).
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 14 November 2023
+Copyright (c) 1997-2018 University of Cambridge.
+.fi
diff --git a/doc/pcre2demo.3 b/doc/pcre2demo.3
new file mode 100644
index 0000000..b4a360f
--- /dev/null
+++ b/doc/pcre2demo.3
@@ -0,0 +1,475 @@
+.TH PCRE2DEMO 3 "24 March 2025" "PCRE2 10.48"
+.\"AUTOMATICALLY GENERATED BY UpdateAlways - do not EDIT!
+.SH NAME
+PCRE2DEMO - A demonstration C program for PCRE2
+.SH "SOURCE CODE"
+.rs
+.sp
+.\" Start example.
+.de EX
+. do ds mF \\n[.fam]
+. nr mE \\n(.f
+. nf
+. nh
+. do fam C
+. ft CW
+..
+.
+.
+.\" End example.
+.de EE
+. do fam \\*(mF
+. ft \\n(mE
+. fi
+. hy \\n(HY
+..
+.
+.RS -7
+.EX
+/*************************************************
+* PCRE2 DEMONSTRATION PROGRAM *
+*************************************************/
+
+/* This is a demonstration program to illustrate a straightforward way of
+using the PCRE2 regular expression library from a C program. See the
+pcre2sample documentation for a short discussion ("man pcre2sample" if you have
+the PCRE2 man pages installed). PCRE2 is a revised API for the library, and is
+incompatible with the original PCRE API.
+
+There are actually three libraries, each supporting a different code unit
+width. This demonstration program uses the 8-bit library. The default is to
+process each code unit as a separate character, but if the pattern begins with
+"(*UTF)", both it and the subject are treated as UTF-8 strings, where
+characters may occupy multiple code units.
+
+In Unix-like environments, if PCRE2 is installed in your standard system
+libraries, you should be able to compile this program using this command:
+
+cc -Wall pcre2demo.c -lpcre2-8 -o pcre2demo
+
+If PCRE2 is not installed in a standard place, it is likely to be installed
+with support for the pkg-config mechanism. If you have pkg-config, you can
+compile this program using this command:
+
+cc -Wall pcre2demo.c `pkg-config --cflags --libs libpcre2-8` -o pcre2demo
+
+If you do not have pkg-config, you may have to use something like this:
+
+cc -Wall pcre2demo.c -I/usr/local/include -L/usr/local/lib \e
+ -R/usr/local/lib -lpcre2-8 -o pcre2demo
+
+Replace "/usr/local/include" and "/usr/local/lib" with wherever the include and
+library files for PCRE2 are installed on your system. Only some operating
+systems (Solaris is one) use the -R option.
+
+Building under Windows:
+
+If you want to statically link this program against a non-dll .a file, you must
+define PCRE2_STATIC before including pcre2.h, so in this environment, uncomment
+the following line. */
+
+/* #define PCRE2_STATIC */
+
+/* The PCRE2_CODE_UNIT_WIDTH macro must be defined before including pcre2.h.
+For a program that uses only one code unit width, setting it to 8, 16, or 32
+makes it possible to use generic function names such as pcre2_compile(). Note
+that just changing 8 to 16 (for example) is not sufficient to convert this
+program to process 16-bit characters. Even in a fully 16-bit environment, where
+string-handling functions such as strcmp() and printf() work with 16-bit
+characters, the code for handling the table of named substrings will still need
+to be modified. */
+
+#define PCRE2_CODE_UNIT_WIDTH 8
+
+#include
+#include
+#include
+
+
+/**************************************************************************
+* Here is the program. The API includes the concept of "contexts" for *
+* setting up unusual interface requirements for compiling and matching, *
+* such as custom memory managers and non-standard newline definitions. *
+* This program does not do any of this, so it makes no use of contexts, *
+* always passing NULL where a context could be given. *
+**************************************************************************/
+
+int main(int argc, char **argv)
+{
+pcre2_code *re;
+PCRE2_SPTR pattern; /* PCRE2_SPTR is a pointer to unsigned code units of */
+PCRE2_SPTR subject; /* the appropriate width (in this case, 8 bits). */
+PCRE2_SPTR name_table;
+
+int errornumber;
+int find_all, caseless_match;
+int i;
+int rc;
+
+uint32_t namecount;
+uint32_t name_entry_size;
+
+PCRE2_SIZE erroroffset;
+PCRE2_SIZE *ovector;
+PCRE2_SIZE ovector_last[2];
+PCRE2_SIZE subject_length;
+
+pcre2_match_data *match_data;
+
+
+/**************************************************************************
+* First, sort out the command line. Options: *
+* - "-g" to request repeated matching to find all occurrences, *
+* like Perl's /g option. We set the variable find_all to a non-zero *
+* value if the -g option is present. *
+* - "-i" to request caseless matching, like Perl's /i option. We set the *
+* variable caseless_match to PCRE2_CASELESS if the -i option is *
+* present. *
+**************************************************************************/
+
+find_all = 0;
+caseless_match = 0;
+for (i = 1; i < argc; i++)
+ {
+ if (strcmp(argv[i], "-g") == 0) find_all = 1;
+ else if (strcmp(argv[i], "-i") == 0) caseless_match = PCRE2_CASELESS;
+ else if (argv[i][0] == '-')
+ {
+ printf("Unrecognised option %s\en", argv[i]);
+ return 1;
+ }
+ else break;
+ }
+
+/* After the options, we require exactly two arguments, which are the pattern,
+and the subject string. */
+
+if (argc - i != 2)
+ {
+ printf("Exactly two arguments required: a regex and a subject string\en");
+ return 1;
+ }
+
+/* Pattern and subject are char arguments, so they can be straightforwardly
+cast to PCRE2_SPTR because we are working in 8-bit code units. The subject
+length is cast to PCRE2_SIZE for completeness, though PCRE2_SIZE is in fact
+defined to be size_t. */
+
+pattern = (PCRE2_SPTR)argv[i];
+subject = (PCRE2_SPTR)argv[i+1];
+subject_length = (PCRE2_SIZE)strlen((char *)subject);
+
+
+/*************************************************************************
+* Now we are going to compile the regular expression pattern, and handle *
+* any errors that are detected. *
+*************************************************************************/
+
+re = pcre2_compile(
+ pattern, /* the pattern */
+ PCRE2_ZERO_TERMINATED, /* indicates pattern is zero-terminated */
+ caseless_match, /* possibly enable caseless */
+ &errornumber, /* for error number */
+ &erroroffset, /* for error offset */
+ NULL); /* use default compile context */
+
+/* Compilation failed: print the error message and exit. */
+
+if (re == NULL)
+ {
+ PCRE2_UCHAR buffer[256];
+ pcre2_get_error_message(errornumber, buffer, sizeof(buffer));
+ printf("PCRE2 compilation failed at offset %d: %s\en", (int)erroroffset,
+ buffer);
+ return 1;
+ }
+
+
+/*************************************************************************
+* If the compilation succeeded, we call PCRE2 again, in order to do a *
+* pattern match against the subject string. This does just ONE match. If *
+* further matching is needed, it will be done below. Before running the *
+* match we must set up a match_data block for holding the result. Using *
+* pcre2_match_data_create_from_pattern() ensures that the block is *
+* exactly the right size for the number of capturing parentheses in the *
+* pattern. If you need to know the actual size of a match_data block as *
+* a number of bytes, you can find it like this: *
+* *
+* PCRE2_SIZE match_data_size = pcre2_get_match_data_size(match_data); *
+*************************************************************************/
+
+match_data = pcre2_match_data_create_from_pattern(re, NULL);
+
+/* Now run the match. */
+
+rc = pcre2_match(
+ re, /* the compiled pattern */
+ subject, /* the subject string */
+ subject_length, /* the length of the subject */
+ 0, /* start at offset 0 in the subject */
+ 0, /* default options */
+ match_data, /* block for storing the result */
+ NULL); /* use default match context */
+
+/* Matching failed: handle error cases */
+
+if (rc < 0)
+ {
+ switch(rc)
+ {
+ case PCRE2_ERROR_NOMATCH: printf("No match\en"); break;
+ /*
+ Handle other special cases if you like
+ */
+ default: printf("Matching error %d\en", rc); break;
+ }
+ pcre2_match_data_free(match_data); /* Release memory used for the match */
+ pcre2_code_free(re); /* data and the compiled pattern. */
+ return 1;
+ }
+
+/* Match succeeded. Get a pointer to the output vector, where string offsets
+are stored. */
+
+ovector = pcre2_get_ovector_pointer(match_data);
+printf("Match succeeded at offset %d\en", (int)ovector[0]);
+
+
+/*************************************************************************
+* We have found the first match within the subject string. If the output *
+* vector wasn't big enough, say so. Then output any substrings that were *
+* captured. *
+*************************************************************************/
+
+/* The output vector wasn't big enough. This should not happen, because we used
+pcre2_match_data_create_from_pattern() above. */
+
+if (rc == 0)
+ printf("ovector was not big enough for all the captured substrings\en");
+
+/* Since release 10.38 PCRE2 has locked out the use of \eK in lookaround
+assertions. This is the recommended behaviour. However, the option
+PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK allows applications to re-enable the old
+behaviour. If that is set, it is possible to run patterns such as /(?=.\eK)/ that
+use \eK in an assertion to set the start of a match later than its end. In this
+demonstration program, we show how to detect this case, although it cannot arise
+because the option is never set. */
+
+if (ovector[0] > ovector[1])
+ {
+ printf("\e\eK was used in an assertion to set the match start after its end.\en"
+ "From end to start the match was: %.*s\en", (int)(ovector[0] - ovector[1]),
+ (char *)(subject + ovector[1]));
+ printf("Run abandoned\en");
+ pcre2_match_data_free(match_data);
+ pcre2_code_free(re);
+ return 1;
+ }
+
+/* Show substrings stored in the output vector by number. Obviously, in a real
+application you might want to do things other than print them. */
+
+for (i = 0; i < rc; i++)
+ {
+ PCRE2_SPTR substring_start = subject + ovector[2*i];
+ PCRE2_SIZE substring_length = ovector[2*i+1] - ovector[2*i];
+ printf("%2d: %.*s\en", i, (int)substring_length, (char *)substring_start);
+ }
+
+
+/**************************************************************************
+* That concludes the basic part of this demonstration program. We have *
+* compiled a pattern, and performed a single match. The code that follows *
+* shows first how to access named substrings, and then how to code for *
+* repeated matches on the same subject. *
+**************************************************************************/
+
+/* See if there are any named substrings, and if so, show them by name. First
+we have to extract the count of named parentheses from the pattern. */
+
+(void)pcre2_pattern_info(
+ re, /* the compiled pattern */
+ PCRE2_INFO_NAMECOUNT, /* get the number of named substrings */
+ &namecount); /* where to put the answer */
+
+if (namecount == 0)
+ printf("No named substrings\en");
+else
+ {
+ PCRE2_SPTR tabptr;
+ printf("Named substrings\en");
+
+ /* Before we can access the substrings, we must extract the table for
+ translating names to numbers, and the size of each entry in the table. */
+
+ (void)pcre2_pattern_info(
+ re, /* the compiled pattern */
+ PCRE2_INFO_NAMETABLE, /* address of the table */
+ &name_table); /* where to put the answer */
+
+ (void)pcre2_pattern_info(
+ re, /* the compiled pattern */
+ PCRE2_INFO_NAMEENTRYSIZE, /* size of each entry in the table */
+ &name_entry_size); /* where to put the answer */
+
+ /* Now we can scan the table and, for each entry, print the number, the name,
+ and the substring itself. In the 8-bit library the number is held in two
+ bytes, most significant first. */
+
+ tabptr = name_table;
+ for (i = 0; i < namecount; i++)
+ {
+ int n = (tabptr[0] << 8) | tabptr[1];
+ printf("(%d) %*s: %.*s\en", n, name_entry_size - 3, tabptr + 2,
+ (int)(ovector[2*n+1] - ovector[2*n]), subject + ovector[2*n]);
+ tabptr += name_entry_size;
+ }
+ }
+
+
+/*************************************************************************
+* If the "-g" option was given on the command line, we want to continue *
+* to search for additional matches in the subject string, in a similar *
+* way to the /g option in Perl. This turns out to be trickier than you *
+* might think because of the possibility of matching an empty string. *
+* *
+* To help with this task, PCRE2 provides the pcre2_next_match() helper. *
+*************************************************************************/
+
+if (!find_all) /* Check for -g */
+ {
+ pcre2_match_data_free(match_data); /* Release the memory that was used */
+ pcre2_code_free(re); /* for the match data and the pattern. */
+ return 0; /* Exit the program. */
+ }
+
+/* Loop for second and subsequent matches */
+
+ovector_last[0] = ovector[0];
+ovector_last[1] = ovector[1];
+
+for (;;)
+ {
+ PCRE2_SIZE start_offset;
+ uint32_t options;
+
+ /* After each successful match, we use pcre2_next_match() to obtain the match
+ parameters for subsequent match attempts. */
+
+ if (!pcre2_next_match(match_data, &start_offset, &options))
+ break;
+
+ /* Run the next matching operation */
+
+ rc = pcre2_match(
+ re, /* the compiled pattern */
+ subject, /* the subject string */
+ subject_length, /* the length of the subject */
+ start_offset, /* starting offset in the subject */
+ options, /* options */
+ match_data, /* block for storing the result */
+ NULL); /* use default match context */
+
+ /* If this match attempt fails, exit the loop for subsequent matches. */
+
+ if (rc == PCRE2_ERROR_NOMATCH)
+ break;
+
+ /* Other matching errors are not recoverable. */
+
+ if (rc < 0)
+ {
+ printf("Matching error %d\en", rc);
+ pcre2_match_data_free(match_data);
+ pcre2_code_free(re);
+ return 1;
+ }
+
+ /* This demonstration program depends on pcre2_next_match() to ensure that the
+ loop for second and subsequent matches does not run forever. However, it would
+ be robust practice for a production application to verify this. The following
+ block of code shows how to do this. This error case is not reachable unless
+ there is a bug in PCRE2.
+
+ Because this program does not set the PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK option,
+ the logic is simple. We verify that either ovector[1] has advanced, or that we
+ have an empty match touching the end of a previous non-empty match. See the
+ API documentation for guidance if your application uses
+ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK and searches for multiple matches. */
+
+ if (!(ovector[1] > ovector_last[1] ||
+ (ovector[1] == ovector[0] && ovector_last[1] > ovector_last[0] &&
+ ovector[1] == ovector_last[1])))
+ {
+ printf("\e\eK was used in an assertion to yield non-advancing matches.\en");
+ printf("Run abandoned\en");
+ pcre2_match_data_free(match_data);
+ pcre2_code_free(re);
+ return 1;
+ }
+
+ ovector_last[0] = ovector[0];
+ ovector_last[1] = ovector[1];
+
+ /* Match succeeded. */
+
+ printf("\enMatch succeeded again at offset %d\en", (int)ovector[0]);
+
+ /* The match succeeded, but the output vector wasn't big enough. This
+ should not happen. */
+
+ if (rc == 0)
+ printf("ovector was not big enough for all the captured substrings\en");
+
+ /* We guard against patterns such as /(?=.\eK)/ that use \eK in an assertion to
+ set the start of a match later than its end. As explained above, this case
+ should not occur because this demonstration program does not set the
+ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK option, however, we do include code showing
+ how to detect it. */
+
+ if (ovector[0] > ovector[1])
+ {
+ printf("\e\eK was used in an assertion to set the match start after its end.\en"
+ "From end to start the match was: %.*s\en", (int)(ovector[0] - ovector[1]),
+ (char *)(subject + ovector[1]));
+ printf("Run abandoned\en");
+ pcre2_match_data_free(match_data);
+ pcre2_code_free(re);
+ return 1;
+ }
+
+ /* As before, show substrings stored in the output vector by number, and then
+ also any named substrings. */
+
+ for (i = 0; i < rc; i++)
+ {
+ PCRE2_SPTR substring_start = subject + ovector[2*i];
+ size_t substring_length = ovector[2*i+1] - ovector[2*i];
+ printf("%2d: %.*s\en", i, (int)substring_length, (char *)substring_start);
+ }
+
+ if (namecount == 0)
+ printf("No named substrings\en");
+ else
+ {
+ PCRE2_SPTR tabptr = name_table;
+ printf("Named substrings\en");
+ for (i = 0; i < namecount; i++)
+ {
+ int n = (tabptr[0] << 8) | tabptr[1];
+ printf("(%d) %*s: %.*s\en", n, name_entry_size - 3, tabptr + 2,
+ (int)(ovector[2*n+1] - ovector[2*n]), subject + ovector[2*n]);
+ tabptr += name_entry_size;
+ }
+ }
+ } /* End of loop to find second and subsequent matches */
+
+printf("\en");
+
+pcre2_match_data_free(match_data);
+pcre2_code_free(re);
+return 0;
+}
+
+/* End of pcre2demo.c */
+.EE
diff --git a/doc/pcre2grep.1 b/doc/pcre2grep.1
new file mode 100644
index 0000000..ab57cad
--- /dev/null
+++ b/doc/pcre2grep.1
@@ -0,0 +1,1027 @@
+.TH PCRE2GREP 1 "24 January 2025" "PCRE2 10.48"
+.SH NAME
+pcre2grep - a grep with Perl-compatible regular expressions.
+.SH SYNOPSIS
+.B pcre2grep [options] [long options] [pattern] [path1 path2 ...]
+.
+.SH DESCRIPTION
+.rs
+.sp
+\fBpcre2grep\fP searches files for character patterns, in the same way as other
+grep commands do, but it uses the PCRE2 regular expression library to support
+patterns that are compatible with the regular expressions of Perl 5. See
+.\" HREF
+\fBpcre2syntax\fP(3)
+.\"
+for a quick-reference summary of pattern syntax, or
+.\" HREF
+\fBpcre2pattern\fP(3)
+.\"
+for a full description of the syntax and semantics of the regular expressions
+that PCRE2 supports.
+.P
+Patterns, whether supplied on the command line or in a separate file, are given
+without delimiters. For example:
+.sp
+ pcre2grep Thursday /etc/motd
+.sp
+If you attempt to use delimiters (for example, by surrounding a pattern with
+slashes, as is common in Perl scripts), they are interpreted as part of the
+pattern. Quotes can of course be used to delimit patterns on the command line
+because they are interpreted by the shell, and indeed quotes are required if a
+pattern contains white space or shell metacharacters.
+.P
+The first argument that follows any option settings is treated as the single
+pattern to be matched when neither \fB-e\fP nor \fB-f\fP is present.
+Conversely, when one or both of these options are used to specify patterns, all
+arguments are treated as path names. At least one of \fB-e\fP, \fB-f\fP, or an
+argument pattern must be provided.
+.P
+If no files are specified, \fBpcre2grep\fP reads the standard input. The
+standard input can also be referenced by a name consisting of a single hyphen.
+For example:
+.sp
+ pcre2grep some-pattern file1 - file3
+.sp
+By default, input files are searched line by line, so pattern assertions about
+the beginning and end of a subject string (^, $, \eA, \eZ, and \ez) match at
+the beginning and end of each line. When a line matches a pattern, it is copied
+to the standard output, and if there is more than one file, the file name is
+output at the start of each line, followed by a colon. However, there are
+options that can change how \fBpcre2grep\fP behaves. For example, the \fB-M\fP
+option makes it possible to search for strings that span line boundaries. What
+defines a line boundary is controlled by the \fB-N\fP (\fB--newline\fP) option.
+The \fB-h\fP and \fB-H\fP options control whether or not file names are shown,
+and the \fB-Z\fP option changes the file name terminator to a zero byte.
+.P
+The amount of memory used for buffering files that are being scanned is
+controlled by parameters that can be set by the \fB--buffer-size\fP and
+\fB--max-buffer-size\fP options. The first of these sets the size of buffer
+that is obtained at the start of processing. If an input file contains very
+long lines, a larger buffer may be needed; this is handled by automatically
+extending the buffer, up to the limit specified by \fB--max-buffer-size\fP. The
+default values for these parameters can be set when \fBpcre2grep\fP is
+built; if nothing is specified, the defaults are set to 20KiB and 1MiB
+respectively. An error occurs if a line is too long and the buffer can no
+longer be expanded.
+.P
+The block of memory that is actually used is three times the "buffer size", to
+allow for buffering "before" and "after" lines. If the buffer size is too
+small, fewer than requested "before" and "after" lines may be output.
+.P
+When matching with a multiline pattern, the size of the buffer must be at least
+half of the maximum match expected or the pattern might fail to match.
+.P
+Patterns can be no longer than 8KiB or BUFSIZ bytes, whichever is the greater.
+BUFSIZ is defined in \fB\fP. When there is more than one pattern
+(specified by the use of \fB-e\fP and/or \fB-f\fP), each pattern is applied to
+each line in the order in which they are defined, except that all the \fB-e\fP
+patterns are tried before the \fB-f\fP patterns.
+.P
+By default, as soon as one pattern matches a line, no further patterns are
+considered. However, if \fB--colour\fP (or \fB--color\fP) is used to colour the
+matching substrings, or if \fB--only-matching\fP, \fB--file-offsets\fP,
+\fB--line-offsets\fP, or \fB--output\fP is used to output only the part of the
+line that matched (either shown literally, or as an offset), the behaviour is
+different. In this situation, all the patterns are applied to the line. If
+there is more than one match, the one that begins nearest to the start of the
+subject is processed; if there is more than one match at that position, the one
+with the longest matching substring is processed; if the matching substrings
+are equal, the first match found is processed.
+.P
+Scanning with all the patterns resumes immediately following the match, so that
+later matches on the same line can be found. Note, however, that an overlapping
+match that starts in the middle of another match will not be processed.
+.P
+The above behaviour was changed at release 10.41 to be more compatible with GNU
+grep. In earlier releases, \fBpcre2grep\fP did not recognize matches from
+later patterns that were earlier in the subject.
+.P
+Patterns that can match an empty string are accepted, but empty string
+matches are never recognized. An example is the pattern "(super)?(man)?", in
+which all components are optional. This pattern finds all occurrences of both
+"super" and "man"; the output differs from matching with "super|man" when only
+the matching substrings are being shown.
+.P
+If the \fBLC_ALL\fP or \fBLC_CTYPE\fP environment variable is set,
+\fBpcre2grep\fP uses the value to set a locale when calling the PCRE2 library.
+The \fB--locale\fP option can be used to override this.
+.
+.
+.SH "SUPPORT FOR COMPRESSED FILES"
+.rs
+.sp
+Compile-time options for \fBpcre2grep\fP can set it up to use \fBlibz\fP or
+\fBlibbz2\fP for reading compressed files whose names end in \fB.gz\fP or
+\fB.bz2\fP, respectively. You can find out whether your \fBpcre2grep\fP binary
+has support for one or both of these file types by running it with the
+\fB--help\fP option. If the appropriate support is not present, all files are
+treated as plain text. The standard input is always so treated. If a file with
+a \fB.gz\fP or \fB.bz2\fP extension is not in fact compressed, it is read as a
+plain text file. When input is from a compressed .gz or .bz2 file, the
+\fB--line-buffered\fP option is ignored.
+.
+.
+.SH "BINARY FILES"
+.rs
+.sp
+By default, a file that contains a binary zero byte within the first 1024 bytes
+is identified as a binary file, and is processed specially. However, if the
+newline type is specified as NUL, that is, the line terminator is a binary
+zero, the test for a binary file is not applied. See the \fB--binary-files\fP
+option for a means of changing the way binary files are handled.
+.
+.
+.SH "BINARY ZEROS IN PATTERNS"
+.rs
+.sp
+Patterns passed from the command line are strings that are terminated by a
+binary zero, so cannot contain internal zeros. However, patterns that are read
+from a file via the \fB-f\fP option may contain binary zeros.
+.
+.
+.SH OPTIONS
+.rs
+.sp
+The order in which some of the options appear can affect the output. For
+example, both the \fB-H\fP and \fB-l\fP options affect the printing of file
+names. Whichever comes later in the command line will be the one that takes
+effect. Similarly, except where noted below, if an option is given twice, the
+later setting is used. Numerical values for options may be followed by K or M,
+to signify multiplication by 1024 or 1024*1024 respectively.
+.TP 10
+\fB--\fP
+This terminates the list of options. It is useful if the next item on the
+command line starts with a hyphen but is not an option. This allows for the
+processing of patterns and file names that start with hyphens.
+.TP
+\fB-A\fP \fInumber\fP, \fB--after-context=\fP\fInumber\fP
+Output up to \fInumber\fP lines of context after each matching line. Fewer
+lines are output if the next match or the end of the file is reached, or if the
+processing buffer size has been set too small. If file names and/or line
+numbers are being output, a hyphen separator is used instead of a colon for the
+context lines (the \fB-Z\fP option can be used to change the file name
+terminator to a zero byte). A line containing "--" is output between each group
+of lines, unless they are in fact contiguous in the input file. The value of
+\fInumber\fP is expected to be relatively small. When \fB-c\fP is used,
+\fB-A\fP is ignored.
+.TP
+\fB-a\fP, \fB--text\fP
+Treat binary files as text. This is equivalent to
+\fB--binary-files\fP=\fItext\fP.
+.TP
+\fB--allow-lookaround-bsk\fP
+PCRE2 now forbids the use of \eK in lookarounds by default, in line with Perl.
+This option causes \fBpcre2grep\fP to set the PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK
+option, which enables this somewhat dangerous usage.
+.TP
+\fB-B\fP \fInumber\fP, \fB--before-context=\fP\fInumber\fP
+Output up to \fInumber\fP lines of context before each matching line. Fewer
+lines are output if the previous match or the start of the file is within
+\fInumber\fP lines, or if the processing buffer size has been set too small. If
+file names and/or line numbers are being output, a hyphen separator is used
+instead of a colon for the context lines (the \fB-Z\fP option can be used to
+change the file name terminator to a zero byte). A line containing "--" is
+output between each group of lines, unless they are in fact contiguous in the
+input file. The value of \fInumber\fP is expected to be relatively small. When
+\fB-c\fP is used, \fB-B\fP is ignored.
+.TP
+\fB--binary-files=\fP\fIword\fP
+Specify how binary files are to be processed. If the word is "binary" (the
+default), pattern matching is performed on binary files, but the only output is
+"Binary file matches" when a match succeeds. If the word is "text",
+which is equivalent to the \fB-a\fP or \fB--text\fP option, binary files are
+processed in the same way as any other file. In this case, when a match
+succeeds, the output may be binary garbage, which can have nasty effects if
+sent to a terminal. If the word is "without-match", which is equivalent to the
+\fB-I\fP option, binary files are not processed at all; they are assumed not to
+be of interest and are skipped without causing any output or affecting the
+return code.
+.TP
+\fB--buffer-size=\fP\fInumber\fP
+Set the parameter that controls how much memory is obtained at the start of
+processing for buffering files that are being scanned. See also
+\fB--max-buffer-size\fP below.
+.TP
+\fB-C\fP \fInumber\fP, \fB--context=\fP\fInumber\fP
+Output \fInumber\fP lines of context both before and after each matching line.
+This is equivalent to setting both \fB-A\fP and \fB-B\fP to the same value.
+.TP
+\fB-c\fP, \fB--count\fP
+Do not output lines from the files that are being scanned; instead output the
+number of lines that would have been shown, either because they matched, or, if
+\fB-v\fP is set, because they failed to match. By default, this count is
+exactly the same as the number of lines that would have been output, but if the
+\fB-M\fP (multiline) option is used (without \fB-v\fP), there may be more
+suppressed lines than the count (that is, the number of matches).
+.sp
+If no lines are selected, the number zero is output. If several files are
+being scanned, a count is output for each of them and the \fB-t\fP option can
+be used to cause a total to be output at the end. However, if the
+\fB--files-with-matches\fP option is also used, only those files whose counts
+are greater than zero are listed. When \fB-c\fP is used, the \fB-A\fP,
+\fB-B\fP, and \fB-C\fP options are ignored.
+.TP
+\fB--colour\fP, \fB--color\fP
+If this option is given without any data, it is equivalent to "--colour=auto".
+If data is required, it must be given in the same shell item, separated by an
+equals sign.
+.TP
+\fB--colour=\fP\fIvalue\fP, \fB--color=\fP\fIvalue\fP
+This option specifies under what circumstances the parts of a line that matched
+a pattern should be coloured in the output. It is ignored if
+\fB--file-offsets\fP, \fB--line-offsets\fP, or \fB--output\fP is set. By
+default, output is not coloured. The value for the \fB--colour\fP option (which
+is optional, see above) may be "never", "always", or "auto". In the latter
+case, colouring happens only if the standard output is connected to a terminal.
+More resources are used when colouring is enabled, because \fBpcre2grep\fP has
+to search for all possible matches in a line, not just one, in order to colour
+them all.
+.sp
+The colour that is used can be specified by setting one of the environment
+variables PCRE2GREP_COLOUR, PCRE2GREP_COLOR, PCREGREP_COLOUR, or
+PCREGREP_COLOR, which are checked in that order. If none of these are set,
+\fBpcre2grep\fP looks for GREP_COLORS or GREP_COLOR (in that order). The value
+of the variable should be a string of two numbers, separated by a semicolon,
+except in the case of GREP_COLORS, which must start with "ms=" or "mt="
+followed by two semicolon-separated colours, terminated by the end of the
+string or by a colon. If GREP_COLORS does not start with "ms=" or "mt=" it is
+ignored, and GREP_COLOR is checked.
+.sp
+If the string obtained from one of the above variables contains any characters
+other than semicolon or digits, the setting is ignored and the default colour
+is used. The string is copied directly into the control string for setting
+colour on a terminal, so it is your responsibility to ensure that the values
+make sense. If no relevant environment variable is set, the default is "1;31",
+which gives red.
+.TP
+\fB-D\fP \fIaction\fP, \fB--devices=\fP\fIaction\fP
+If an input path is not a regular file or a directory, "action" specifies how
+it is to be processed. Valid values are "read" (the default) or "skip"
+(silently skip the path).
+.TP
+\fB-d\fP \fIaction\fP, \fB--directories=\fP\fIaction\fP
+If an input path is a directory, "action" specifies how it is to be processed.
+Valid values are "read" (the default in non-Windows environments, for
+compatibility with GNU grep), "recurse" (equivalent to the \fB-r\fP option), or
+"skip" (silently skip the path, the default in Windows environments). In the
+"read" case, directories are read as if they were ordinary files. In some
+operating systems the effect of reading a directory like this is an immediate
+end-of-file; in others it may provoke an error.
+.TP
+\fB--depth-limit\fP=\fInumber\fP
+See \fB--match-limit\fP below.
+.TP
+\fB-E\fP, \fB--case-restrict\fP
+When case distinctions are being ignored in Unicode mode, two ASCII letters (K
+and S) will by default match Unicode characters U+212A (Kelvin sign) and U+017F
+(long S) respectively, as well as their lower case ASCII counterparts. When
+this option is set, case equivalences are restricted such that no ASCII
+character matches a non-ASCII character, and vice versa.
+.TP
+\fB-e\fP \fIpattern\fP, \fB--regex=\fP\fIpattern\fP, \fB--regexp=\fP\fIpattern\fP
+Specify a pattern to be matched. This option can be used multiple times in
+order to specify several patterns. It can also be used as a way of specifying a
+single pattern that starts with a hyphen. When \fB-e\fP is used, no argument
+pattern is taken from the command line; all arguments are treated as file
+names. There is no limit to the number of patterns. They are applied to each
+line in the order in which they are defined.
+.sp
+If \fB-f\fP is used with \fB-e\fP, the command line patterns are matched first,
+followed by the patterns from the file(s), independent of the order in which
+these options are specified.
+.TP
+\fB--exclude\fP=\fIpattern\fP
+Files (but not directories) whose names match the pattern are skipped without
+being processed. This applies to all files, whether listed on the command line,
+obtained from \fB--file-list\fP, or by scanning a directory. The pattern is a
+PCRE2 regular expression, and is matched against the final component of the
+file name, not the entire path. The \fB-F\fP, \fB-w\fP, and \fB-x\fP options do
+not apply to this pattern. The option may be given any number of times in order
+to specify multiple patterns. If a file name matches both an \fB--include\fP
+and an \fB--exclude\fP pattern, it is excluded. There is no short form for this
+option.
+.TP
+\fB--exclude-from=\fP\fIfilename\fP
+Treat each non-empty line of the file as the data for an \fB--exclude\fP
+option. What constitutes a newline when reading the file is the operating
+system's default. The \fB--newline\fP option has no effect on this option. This
+option may be given more than once in order to specify a number of files to
+read.
+.TP
+\fB--exclude-dir\fP=\fIpattern\fP
+Directories whose names match the pattern are skipped without being processed,
+whatever the setting of the \fB--recursive\fP option. This applies to all
+directories, whether listed on the command line, obtained from
+\fB--file-list\fP, or by scanning a parent directory. The pattern is a PCRE2
+regular expression, and is matched against the final component of the directory
+name, not the entire path. The \fB-F\fP, \fB-w\fP, and \fB-x\fP options do not
+apply to this pattern. The option may be given any number of times in order to
+specify more than one pattern. If a directory matches both \fB--include-dir\fP
+and \fB--exclude-dir\fP, it is excluded. There is no short form for this
+option.
+.TP
+\fB-F\fP, \fB--fixed-strings\fP
+Interpret each data-matching pattern as a list of fixed strings, separated by
+newlines, instead of as a regular expression. What constitutes a newline for
+this purpose is controlled by the \fB--newline\fP option. The \fB-w\fP (match
+as a word) and \fB-x\fP (match whole line) options can be used with \fB-F\fP.
+They apply to each of the fixed strings. A line is selected if any of the fixed
+strings are found in it (subject to \fB-w\fP or \fB-x\fP, if present). This
+option applies only to the patterns that are matched against the contents of
+files; it does not apply to patterns specified by any of the \fB--include\fP or
+\fB--exclude\fP options.
+.TP
+\fB-f\fP \fIfilename\fP, \fB--file=\fP\fIfilename\fP
+Read patterns from the file, one per line. As is the case with patterns on the
+command line, no delimiters should be used. What constitutes a newline when
+reading the file is the operating system's default interpretation of \en. The
+\fB--newline\fP option has no effect on this option. Trailing white space is
+removed from each line, and blank lines are ignored unless the
+\fB--posix-pattern-file\fP option is also provided. An empty file contains no
+patterns and therefore matches nothing. Patterns read from a file in this way
+may contain binary zeros, which are treated as ordinary character literals.
+.sp
+If this option is given more than once, all the specified files are read. A
+data line is output if any of the patterns match it. A file name can be given
+as "-" to refer to the standard input. When \fB-f\fP is used, patterns
+specified on the command line using \fB-e\fP may also be present; they are
+matched before the file's patterns. However, no pattern is taken from the
+command line; all arguments are treated as the names of paths to be searched.
+.TP
+\fB--file-list\fP=\fIfilename\fP
+Read a list of files and/or directories that are to be scanned from the given
+file, one per line. What constitutes a newline when reading the file is the
+operating system's default. Trailing white space is removed from each line, and
+blank lines are ignored. These paths are processed before any that are listed
+on the command line. The file name can be given as "-" to refer to the standard
+input. If \fB--file\fP and \fB--file-list\fP are both specified as "-",
+patterns are read first. This is useful only when the standard input is a
+terminal, from which further lines (the list of files) can be read after an
+end-of-file indication. If this option is given more than once, all the
+specified files are read.
+.TP
+\fB--file-offsets\fP
+Instead of showing lines or parts of lines that match, show each match as an
+offset from the start of the file and a length, separated by a comma. In this
+mode, \fB--colour\fP has no effect, and no context is shown. That is, the
+\fB-A\fP, \fB-B\fP, and \fB-C\fP options are ignored. If there is more than one
+match in a line, each of them is shown separately. This option is mutually
+exclusive with \fB--output\fP, \fB--line-offsets\fP, and \fB--only-matching\fP.
+.TP
+\fB--group-separator\fP=\fItext\fP
+Output this text string instead of two hyphens between groups of lines when
+\fB-A\fP, \fB-B\fP, or \fB-C\fP is in use. See also \fB--no-group-separator\fP.
+.TP
+\fB-H\fP, \fB--with-filename\fP
+Force the inclusion of the file name at the start of output lines when
+searching a single file. The file name is not normally shown in this case.
+By default, for matching lines, the file name is followed by a colon; for
+context lines, a hyphen separator is used. The \fB-Z\fP option can be used to
+change the terminator to a zero byte. If a line number is also being output,
+it follows the file name. When the \fB-M\fP option causes a pattern to match
+more than one line, only the first is preceded by the file name. This option
+overrides any previous \fB-h\fP, \fB-l\fP, or \fB-L\fP options.
+.TP
+\fB-h\fP, \fB--no-filename\fP
+Suppress the output file names when searching multiple files. File names are
+normally shown when multiple files are searched. By default, for matching
+lines, the file name is followed by a colon; for context lines, a hyphen
+separator is used. The \fB-Z\fP option can be used to change the terminator to
+a zero byte. If a line number is also being output, it follows the file name.
+This option overrides any previous \fB-H\fP, \fB-L\fP, or \fB-l\fP options.
+.TP
+\fB--heap-limit\fP=\fInumber\fP
+See \fB--match-limit\fP below.
+.TP
+\fB--help\fP
+Output a help message, giving brief details of the command options and file
+type support, and then exit. Anything else on the command line is
+ignored.
+.TP
+\fB-I\fP
+Ignore binary files. This is equivalent to
+\fB--binary-files\fP=\fIwithout-match\fP.
+.TP
+\fB-i\fP, \fB--ignore-case\fP
+Ignore upper/lower case distinctions when pattern matching. This applies when
+matching path names for inclusion or exclusion as well as when matching lines
+in files.
+.TP
+\fB--include\fP=\fIpattern\fP
+If any \fB--include\fP patterns are specified, the only files that are
+processed are those whose names match one of the patterns and do not match an
+\fB--exclude\fP pattern. This option does not affect directories, but it
+applies to all files, whether listed on the command line, obtained from
+\fB--file-list\fP, or by scanning a directory. The pattern is a PCRE2 regular
+expression, and is matched against the final component of the file name, not
+the entire path. The \fB-F\fP, \fB-w\fP, and \fB-x\fP options do not apply to
+this pattern. The option may be given any number of times. If a file name
+matches both an \fB--include\fP and an \fB--exclude\fP pattern, it is excluded.
+There is no short form for this option.
+.TP
+\fB--include-from=\fP\fIfilename\fP
+Treat each non-empty line of the file as the data for an \fB--include\fP
+option. What constitutes a newline for this purpose is the operating system's
+default. The \fB--newline\fP option has no effect on this option. This option
+may be given any number of times; all the files are read.
+.TP
+\fB--include-dir\fP=\fIpattern\fP
+If any \fB--include-dir\fP patterns are specified, the only directories that
+are processed are those whose names match one of the patterns and do not match
+an \fB--exclude-dir\fP pattern. This applies to all directories, whether listed
+on the command line, obtained from \fB--file-list\fP, or by scanning a parent
+directory. The pattern is a PCRE2 regular expression, and is matched against
+the final component of the directory name, not the entire path. The \fB-F\fP,
+\fB-w\fP, and \fB-x\fP options do not apply to this pattern. The option may be
+given any number of times. If a directory matches both \fB--include-dir\fP and
+\fB--exclude-dir\fP, it is excluded. There is no short form for this option.
+.TP
+\fB-L\fP, \fB--files-without-match\fP
+Instead of outputting lines from the files, just output the names of the files
+that do not contain any lines that would have been output. Each file name is
+output once, on a separate line by default, but if the \fB-Z\fP option is set,
+they are separated by zero bytes instead of newlines. This option overrides any
+previous \fB-H\fP, \fB-h\fP, or \fB-l\fP options.
+.TP
+\fB-l\fP, \fB--files-with-matches\fP
+Instead of outputting lines from the files, just output the names of the files
+containing lines that would have been output. Each file name is output once, on
+a separate line, but if the \fB-Z\fP option is set, they are separated by zero
+bytes instead of newlines. Searching normally stops as soon as a matching line
+is found in a file. However, if the \fB-c\fP (count) option is also used,
+matching continues in order to obtain the correct count, and those files that
+have at least one match are listed along with their counts. Using this option
+with \fB-c\fP is a way of suppressing the listing of files with no matches that
+occurs with \fB-c\fP on its own. This option overrides any previous \fB-H\fP,
+\fB-h\fP, or \fB-L\fP options.
+.TP
+\fB--label\fP=\fIname\fP
+This option supplies a name to be used for the standard input when file names
+are being output. If not supplied, "(standard input)" is used. There is no
+short form for this option.
+.TP
+\fB--line-buffered\fP
+When this option is given, non-compressed input is read and processed line by
+line, and the output is flushed after each write. By default, input is read in
+large chunks, unless \fBpcre2grep\fP can determine that it is reading from a
+terminal, which is currently possible only in Unix-like environments or
+Windows. Output to terminal is normally automatically flushed by the operating
+system. This option can be useful when the input or output is attached to a
+pipe and you do not want \fBpcre2grep\fP to buffer up large amounts of data.
+However, its use will affect performance, and the \fB-M\fP (multiline) option
+ceases to work. When input is from a compressed .gz or .bz2 file,
+\fB--line-buffered\fP is ignored.
+.TP
+\fB--line-offsets\fP
+Instead of showing lines or parts of lines that match, show each match as a
+line number, the offset from the start of the line, and a length. The line
+number is terminated by a colon (as usual; see the \fB-n\fP option), and the
+offset and length are separated by a comma. In this mode, \fB--colour\fP has no
+effect, and no context is shown. That is, the \fB-A\fP, \fB-B\fP, and \fB-C\fP
+options are ignored. If there is more than one match in a line, each of them is
+shown separately. This option is mutually exclusive with \fB--output\fP,
+\fB--file-offsets\fP, and \fB--only-matching\fP.
+.TP
+\fB--locale\fP=\fIlocale-name\fP
+This option specifies a locale to be used for pattern matching. It overrides
+the value in the \fBLC_ALL\fP or \fBLC_CTYPE\fP environment variables. If no
+locale is specified, the PCRE2 library's default (usually the "C" locale) is
+used. There is no short form for this option.
+.TP
+\fB-M\fP, \fB--multiline\fP
+Allow patterns to match more than one line. When this option is set, the PCRE2
+library is called in "multiline" mode, and a match is allowed to continue past
+the end of the initial line and onto one or more subsequent lines.
+.sp
+Patterns used with \fB-M\fP may usefully contain literal newline characters and
+internal occurrences of ^ and $ characters, because in multiline mode these can
+match at internal newlines. Because \fBpcre2grep\fP is scanning multiple lines,
+the \eZ and \ez assertions match only at the end of the last line in the file.
+The \eA assertion matches at the start of the first line of a match. This can
+be any line in the file; it is not anchored to the first line.
+.sp
+The output for a successful match may consist of more than one line. The first
+line is the line in which the match started, and the last line is the line in
+which the match ended. If the matched string ends with a newline sequence, the
+output ends at the end of that line. If \fB-v\fP is set, none of the lines in a
+multi-line match are output. Once a match has been handled, scanning restarts
+at the beginning of the line after the one in which the match ended.
+.sp
+The newline sequence that separates multiple lines must be matched as part of
+the pattern. For example, to find the phrase "regular expression" in a file
+where "regular" might be at the end of a line and "expression" at the start of
+the next line, you could use this command:
+.sp
+ pcre2grep -M 'regular\es+expression'
+.sp
+The \es escape sequence matches any white space character, including newlines,
+and is followed by + so as to match trailing white space on the first line as
+well as possibly handling a two-character newline sequence.
+.sp
+There is a limit to the number of lines that can be matched, imposed by the way
+that \fBpcre2grep\fP buffers the input file as it scans it. With a sufficiently
+large processing buffer, this should not be a problem.
+.sp
+The \fB-M\fP option does not work when input is read line by line (see
+\fB--line-buffered\fP.)
+.TP
+\fB-m\fP \fInumber\fP, \fB--max-count\fP=\fInumber\fP
+Stop processing after finding \fInumber\fP matching lines, or non-matching
+lines if \fB-v\fP is also set. Any trailing context lines are output after the
+final match. In multiline mode, each multiline match counts as just one line
+for this purpose. If this limit is reached when reading the standard input from
+a regular file, the file is left positioned just after the last matching line.
+If \fB-c\fP is also set, the count that is output is never greater than
+\fInumber\fP. This option has no effect if used with \fB-L\fP, \fB-l\fP, or
+\fB-q\fP, or when just checking for a match in a binary file.
+.TP
+\fB--match-limit\fP=\fInumber\fP
+Processing some regular expression patterns may take a very long time to search
+for all possible matching strings. Others may require a very large amount of
+memory. There are three options that set resource limits for matching.
+.sp
+The \fB--match-limit\fP option provides a means of limiting computing resource
+usage when processing patterns that are not going to match, but which have a
+very large number of possibilities in their search trees. The classic example
+is a pattern that uses nested unlimited repeats. Internally, PCRE2 has a
+counter that is incremented each time around its main processing loop. If the
+value set by \fB--match-limit\fP is reached, an error occurs.
+.sp
+The \fB--heap-limit\fP option specifies, as a number of kibibytes (units of
+1024 bytes), the maximum amount of heap memory that may be used for matching.
+.sp
+The \fB--depth-limit\fP option limits the depth of nested backtracking points,
+which indirectly limits the amount of memory that is used. The amount of memory
+needed for each backtracking point depends on the number of capturing
+parentheses in the pattern, so the amount of memory that is used before this
+limit acts varies from pattern to pattern. This limit is of use only if it is
+set smaller than \fB--match-limit\fP.
+.sp
+There are no short forms for these options. The default limits can be set
+when the PCRE2 library is compiled; if they are not specified, the defaults
+are very large and so effectively unlimited.
+.TP
+\fB--max-buffer-size\fP=\fInumber\fP
+This limits the expansion of the processing buffer, whose initial size can be
+set by \fB--buffer-size\fP. The maximum buffer size is silently forced to be no
+smaller than the starting buffer size.
+.TP
+\fB-N\fP \fInewline-type\fP, \fB--newline\fP=\fInewline-type\fP
+Six different conventions for indicating the ends of lines in scanned files are
+supported. For example:
+.sp
+ pcre2grep -N CRLF 'some pattern'
+.sp
+The newline type may be specified in upper, lower, or mixed case. If the
+newline type is NUL, lines are separated by binary zero characters. The other
+types are the single-character sequences CR (carriage return) and LF
+(linefeed), the two-character sequence CRLF, an "anycrlf" type, which
+recognizes any of the preceding three types, and an "any" type, for which any
+Unicode line ending sequence is assumed to end a line. The Unicode sequences
+are the three just mentioned, plus VT (vertical tab, U+000B), FF (form feed,
+U+000C), NEL (next line, U+0085), LS (line separator, U+2028), and PS
+(paragraph separator, U+2029).
+.sp
+When the PCRE2 library is built, a default line-ending sequence is specified.
+This is normally the standard sequence for the operating system. Unless
+otherwise specified by this option, \fBpcre2grep\fP uses the library's default.
+.sp
+This option makes it possible to use \fBpcre2grep\fP to scan files that have
+come from other environments without having to modify their line endings. If
+the data that is being scanned does not agree with the convention set by this
+option, \fBpcre2grep\fP may behave in strange ways. Note that this option does
+not apply to files specified by the \fB-f\fP, \fB--exclude-from\fP, or
+\fB--include-from\fP options, which are expected to use the operating system's
+standard newline sequence.
+.TP
+\fB-n\fP, \fB--line-number\fP
+Precede each output line by its line number in the file, followed by a colon
+for matching lines or a hyphen for context lines. If the file name is also
+being output, it precedes the line number. When the \fB-M\fP option causes a
+pattern to match more than one line, only the first is preceded by its line
+number. This option is forced if \fB--line-offsets\fP is used.
+.TP
+\fB--no-group-separator\fP
+Do not output a separator between groups of lines when \fB-A\fP, \fB-B\fP, or
+\fB-C\fP is in use. The default is to output a line containing two hyphens. See
+also \fB--group-separator\fP.
+.TP
+\fB--no-jit\fP
+If the PCRE2 library is built with support for just-in-time compiling (which
+speeds up matching), \fBpcre2grep\fP automatically makes use of this, unless it
+was explicitly disabled at build time. This option can be used to disable the
+use of JIT at run time. It is provided for testing and working around problems.
+It should never be needed in normal use.
+.TP
+\fB-O\fP \fItext\fP, \fB--output\fP=\fItext\fP
+When there is a match, instead of outputting the line that matched, output just
+the text specified in this option, followed by an operating-system standard
+newline. In this mode, \fB--colour\fP has no effect, and no context is shown.
+That is, the \fB-A\fP, \fB-B\fP, and \fB-C\fP options are ignored. The
+\fB--newline\fP option has no effect on this option, which is mutually
+exclusive with \fB--only-matching\fP, \fB--file-offsets\fP, and
+\fB--line-offsets\fP. However, like \fB--only-matching\fP, if there is more
+than one match in a line, each of them causes a line of output.
+.sp
+Escape sequences starting with a dollar character may be used to insert the
+contents of the matched part of the line and/or captured substrings into the
+text.
+.sp
+$ or ${} is replaced by the captured substring of the given
+decimal number; $& (or the legacy $0) substitutes the whole match. If the
+number is greater than the number of capturing substrings, or if the capture
+is unset, the replacement is empty.
+.sp
+$a is replaced by bell; $b by backspace; $e by escape; $f by form feed; $n by
+newline; $r by carriage return; $t by tab; $v by vertical tab.
+.sp
+$o or $o{} is replaced by the character whose code point is the
+given octal number. In the first form, up to three octal digits are processed.
+When more digits are needed in Unicode mode to specify a wide character, the
+second form must be used.
+.sp
+$x or $x{} is replaced by the character represented by the
+given hexadecimal number. In the first form, up to two hexadecimal digits are
+processed. When more digits are needed in Unicode mode to specify a wide
+character, the second form must be used.
+.sp
+Any other character is substituted by itself. In particular, $$ is replaced by
+a single dollar.
+.TP
+\fB-o\fP, \fB--only-matching\fP
+Show only the part of the line that matched a pattern instead of the whole
+line. In this mode, no context is shown. That is, the \fB-A\fP, \fB-B\fP, and
+\fB-C\fP options are ignored. If there is more than one match in a line, each
+of them is shown separately, on a separate line of output. If \fB-o\fP is
+combined with \fB-v\fP (invert the sense of the match to find non-matching
+lines), no output is generated, but the return code is set appropriately. If
+the matched portion of the line is empty, nothing is output unless the file
+name or line number are being printed, in which case they are shown on an
+otherwise empty line. This option is mutually exclusive with \fB--output\fP,
+\fB--file-offsets\fP and \fB--line-offsets\fP.
+.TP
+\fB-o\fP\fInumber\fP, \fB--only-matching\fP=\fInumber\fP
+Show only the part of the line that matched the capturing parentheses of the
+given number. Up to 50 capturing parentheses are supported by default. This
+limit can be changed via the \fB--om-capture\fP option. A pattern may contain
+any number of capturing parentheses, but only those whose number is within the
+limit can be accessed by \fB-o\fP. An error occurs if the number specified by
+\fB-o\fP is greater than the limit.
+.sp
+-o0 is the same as \fB-o\fP without a number. Because these options can be
+given without an argument (see above), if an argument is present, it must be
+given in the same shell item, for example, -o3 or --only-matching=2. The
+comments given for the non-argument case above also apply to this option. If
+the specified capturing parentheses do not exist in the pattern, or were not
+set in the match, nothing is output unless the file name or line number are
+being output.
+.sp
+If this option is given multiple times, multiple substrings are output for each
+match, in the order the options are given, and all on one line. For example,
+-o3 -o1 -o3 causes the substrings matched by capturing parentheses 3 and 1 and
+then 3 again to be output. By default, there is no separator (but see the next
+but one option).
+.TP
+\fB--om-capture\fP=\fInumber\fP
+Set the number of capturing parentheses that can be accessed by \fB-o\fP. The
+default is 50.
+.TP
+\fB--om-separator\fP=\fItext\fP
+Specify a separating string for multiple occurrences of \fB-o\fP. The default
+is an empty string. Separating strings are never coloured.
+.TP
+\fB-P\fP, \fB--no-ucp\fP
+Starting from release 10.43, when UTF/Unicode mode is specified with \fB-u\fP
+or \fB-U\fP, the PCRE2_UCP option is used by default. This means that the
+POSIX classes in patterns match more than just ASCII characters. For example,
+[:digit:] matches any Unicode decimal digit. The \fB--no-ucp\fP option
+suppresses PCRE2_UCP, thus restricting the POSIX classes to ASCII characters,
+as was the case in earlier releases. Note that there are now more fine-grained
+option settings within patterns that affect individual classes. For example,
+when in UCP mode, the sequence (?aP) restricts [:word:] to ASCII letters, while
+allowing \ew to match Unicode letters and digits.
+.TP
+\fB--posix-pattern-file\fP
+When patterns are provided with the \fB-f\fP option, do not trim trailing
+spaces or ignore empty lines in a similar way than other grep tools. To keep
+the behaviour consistent with older versions, if the pattern read was
+terminated with CRLF (as character literals) then both characters won't be
+included as part of it, so if you really need to have pattern ending in '\er',
+use a escape sequence or provide it by a different method.
+.TP
+\fB-q\fP, \fB--quiet\fP
+Work quietly, that is, display nothing except error messages. The exit
+status indicates whether or not any matches were found.
+.TP
+\fB-r\fP, \fB--recursive\fP
+If any given path is a directory, recursively scan the files it contains,
+taking note of any \fB--include\fP and \fB--exclude\fP settings. By default, a
+directory is read as a normal file; in some operating systems this gives an
+immediate end-of-file. This option is a shorthand for setting the \fB-d\fP
+option to "recurse".
+.TP
+\fB--recursion-limit\fP=\fInumber\fP
+This is an obsolete synonym for \fB--depth-limit\fP. See \fB--match-limit\fP
+above for details.
+.TP
+\fB-s\fP, \fB--no-messages\fP
+Suppress error messages about non-existent or unreadable files. Such files are
+quietly skipped. However, the return code is still 2, even if matches were
+found in other files.
+.TP
+\fB-t\fP, \fB--total-count\fP
+This option is useful when scanning more than one file. If used on its own,
+\fB-t\fP suppresses all output except for a grand total number of matching
+lines (or non-matching lines if \fB-v\fP is used) in all the files. If \fB-t\fP
+is used with \fB-c\fP, a grand total is output except when the previous output
+is just one line. In other words, it is not output when just one file's count
+is listed. If file names are being output, the grand total is preceded by
+"TOTAL:". Otherwise, it appears as just another number. The \fB-t\fP option is
+ignored when used with \fB-L\fP (list files without matches), because the grand
+total would always be zero.
+.TP
+\fB-u\fP, \fB--utf\fP
+Operate in UTF/Unicode mode. This option is available only if PCRE2 has been
+compiled with UTF-8 support. All patterns (including those for any
+\fB--exclude\fP and \fB--include\fP options) and all lines that are scanned
+must be valid strings of UTF-8 characters. If an invalid UTF-8 string is
+encountered, an error occurs.
+.TP
+\fB-U\fP, \fB--utf-allow-invalid\fP
+As \fB--utf\fP, but in addition subject lines may contain invalid UTF-8 code
+unit sequences. These can never form part of any pattern match. Patterns
+themselves, however, must still be valid UTF-8 strings. This facility allows
+valid UTF-8 strings to be sought within arbitrary byte sequences in executable
+or other binary files. For more details about matching in non-valid UTF-8
+strings, see the
+.\" HREF
+\fBpcre2unicode\fP(3)
+.\"
+documentation.
+.TP
+\fB-V\fP, \fB--version\fP
+Write the version numbers of \fBpcre2grep\fP and the PCRE2 library to the
+standard output and then exit. Anything else on the command line is
+ignored.
+.TP
+\fB-v\fP, \fB--invert-match\fP
+Invert the sense of the match, so that lines which do \fInot\fP match any of
+the patterns are the ones that are found. When this option is set, options such
+as \fB--only-matching\fP and \fB--output\fP, which specify parts of a match
+that are to be output, are ignored.
+.TP
+\fB-w\fP, \fB--word-regex\fP, \fB--word-regexp\fP
+Force the patterns only to match "words". That is, there must be a word
+boundary at the start and end of each matched string. This is equivalent to
+having "\eb(?:" at the start of each pattern, and ")\eb" at the end. This
+option applies only to the patterns that are matched against the contents of
+files; it does not apply to patterns specified by any of the \fB--include\fP or
+\fB--exclude\fP options.
+.TP
+\fB-x\fP, \fB--line-regex\fP, \fB--line-regexp\fP
+Force the patterns to start matching only at the beginnings of lines, and in
+addition, require them to match entire lines. In multiline mode the match may
+be more than one line. This is equivalent to having "^(?:" at the start of each
+pattern and ")$" at the end. This option applies only to the patterns that are
+matched against the contents of files; it does not apply to patterns specified
+by any of the \fB--include\fP or \fB--exclude\fP options.
+.TP
+\fB-Z\fP, \fB--null\fP
+Terminate files names in the regular output with a zero byte (the NUL
+character) instead of what would normally appear. This is useful when file
+names contain unusual characters such as colons, hyphens, or even newlines. The
+option does not apply to file names in error messages.
+.
+.
+.SH "ENVIRONMENT VARIABLES"
+.rs
+.sp
+The environment variables \fBLC_ALL\fP and \fBLC_CTYPE\fP are examined, in that
+order, for a locale. The first one that is set is used. This can be overridden
+by the \fB--locale\fP option. If no locale is set, the PCRE2 library's default
+(usually the "C" locale) is used.
+.
+.
+.SH "NEWLINES"
+.rs
+.sp
+The \fB-N\fP (\fB--newline\fP) option allows \fBpcre2grep\fP to scan files with
+newline conventions that differ from the default. This option affects only the
+way scanned files are processed. It does not affect the interpretation of files
+specified by the \fB-f\fP, \fB--file-list\fP, \fB--exclude-from\fP, or
+\fB--include-from\fP options.
+.P
+Any parts of the scanned input files that are written to the standard output
+are copied with whatever newline sequences they have in the input. However, if
+the final line of a file is output, and it does not end with a newline
+sequence, a newline sequence is added. If the newline setting is CR, LF, CRLF
+or NUL, that line ending is output; for the other settings (ANYCRLF or ANY) a
+single NL is used.
+.P
+The newline setting does not affect the way in which \fBpcre2grep\fP writes
+newlines in informational messages to the standard output and error streams.
+Under Windows, the standard output is set to be binary, so that "\er\en" at the
+ends of output lines that are copied from the input is not converted to
+"\er\er\en" by the C I/O library. This means that any messages written to the
+standard output must end with "\er\en". For all other operating systems, and
+for all messages to the standard error stream, "\en" is used.
+.
+.
+.SH "OPTIONS COMPATIBILITY WITH GNU GREP"
+.rs
+.sp
+Many of the short and long forms of \fBpcre2grep\fP's options are the same as
+in the GNU \fBgrep\fP program. Any long option of the form \fB--xxx-regexp\fP
+(GNU terminology) is also available as \fB--xxx-regex\fP (PCRE2 terminology).
+However, the \fB--case-restrict\fP, \fB--depth-limit\fP, \fB-E\fP,
+\fB--file-list\fP, \fB--file-offsets\fP, \fB--heap-limit\fP,
+\fB--include-dir\fP, \fB--line-offsets\fP, \fB--locale\fP, \fB--match-limit\fP,
+\fB-M\fP, \fB--multiline\fP, \fB-N\fP, \fB--newline\fP, \fB--no-ucp\fP,
+\fB--om-separator\fP, \fB--output\fP, \fB-P\fP, \fB-u\fP, \fB--utf\fP,
+\fB-U\fP, and \fB--utf-allow-invalid\fP options are specific to
+\fBpcre2grep\fP, as is the use of the \fB--only-matching\fP option with a
+capturing parentheses number.
+.P
+Although most of the common options work the same way, a few are different in
+\fBpcre2grep\fP. For example, the \fB--include\fP option's argument is a glob
+for GNU \fBgrep\fP, but in \fBpcre2grep\fP it is a regular expression to which
+the \fB-i\fP option applies. If both the \fB-c\fP and \fB-l\fP options are
+given, GNU grep lists only file names, without counts, but \fBpcre2grep\fP
+gives the counts as well.
+.
+.
+.SH "OPTIONS WITH DATA"
+.rs
+.sp
+There are four different ways in which an option with data can be specified.
+If a short form option is used, the data may follow immediately, or (with one
+exception) in the next command line item. For example:
+.sp
+ -f/some/file
+ -f /some/file
+.sp
+The exception is the \fB-o\fP option, which may appear with or without data.
+Because of this, if data is present, it must follow immediately in the same
+item, for example -o3.
+.P
+If a long form option is used, the data may appear in the same command line
+item, separated by an equals character, or (with two exceptions) it may appear
+in the next command line item. For example:
+.sp
+ --file=/some/file
+ --file /some/file
+.sp
+Note, however, that if you want to supply a file name beginning with ~ as data
+in a shell command, and have the shell expand ~ to a home directory, you must
+separate the file name from the option, because the shell does not treat ~
+specially unless it is at the start of an item.
+.P
+The exceptions to the above are the \fB--colour\fP (or \fB--color\fP) and
+\fB--only-matching\fP options, for which the data is optional. If one of these
+options does have data, it must be given in the first form, using an equals
+character. Otherwise \fBpcre2grep\fP will assume that it has no data.
+.
+.
+.SH "USING PCRE2'S CALLOUT FACILITY"
+.rs
+.sp
+\fBpcre2grep\fP has, by default, support for calling external programs or
+scripts or echoing specific strings during matching by making use of PCRE2's
+callout facility. However, this support can be completely or partially disabled
+when \fBpcre2grep\fP is built. You can find out whether your binary has support
+for callouts by running it with the \fB--help\fP option. If callout support is
+completely disabled, callouts in patterns are forbidden by \fBpcre2grep\fP.
+If the facility is partially disabled, calling external programs is not
+supported, and callouts that request it are ignored.
+.P
+A callout in a PCRE2 pattern is of the form (?C) where the argument is
+either a number or a quoted string (see the
+.\" HREF
+\fBpcre2callout\fP
+.\"
+documentation for details). Numbered callouts are ignored by \fBpcre2grep\fP;
+only callouts with string arguments are useful.
+.
+.
+.SS "Echoing a specific string"
+.rs
+.sp
+Starting the callout string with a pipe character invokes an echoing facility
+that avoids calling an external program or script. This facility is always
+available, provided that callouts were not completely disabled when
+\fBpcre2grep\fP was built. The rest of the callout string is processed as a
+zero-terminated string, which means it should not contain any internal binary
+zeros. It is written to the output, having first been passed through the same
+escape processing as text from the \fB--output\fP (\fB-O\fP) option (see
+above). However, $0 or $& cannot be used to insert a matched substring because
+the match is still in progress. Instead, the single character '0' is inserted.
+Any syntax errors in the string (for example, a dollar not followed by another
+character) causes the callout to be ignored. No terminator is added to the
+output string, so if you want a newline, you must include it explicitly using
+the escape $n. For example:
+.sp
+ pcre2grep '(.)(..(.))(?C"|[$1] [$2] [$3]$n")'
+.sp
+Matching continues normally after the string is output. If you want to see only
+the callout output but not any output from an actual match, you should end the
+pattern with (*FAIL).
+.
+.
+.SS "Calling external programs or scripts"
+.rs
+.sp
+This facility can be independently disabled when \fBpcre2grep\fP is built. It
+is supported for Windows, where a call to \fB_spawnvp()\fP is used, for VMS,
+where \fBlib$spawn()\fP is used, and for any Unix-like environment where
+\fBfork()\fP and \fBexecv()\fP are available.
+.P
+If the callout string does not start with a pipe (vertical bar) character, it
+is parsed into a list of substrings separated by pipe characters. The first
+substring must be an executable name, with the following substrings specifying
+arguments:
+.sp
+ executable_name|arg1|arg2|...
+.sp
+Any substring (including the executable name) may contain escape sequences
+started by a dollar character. These are the same as for the \fB--output\fP
+(\fB-O\fP) option documented above, except that $0 or $& cannot insert the
+matched string because the match is still in progress. Instead, the character
+\&'0' is inserted. If you need a literal dollar or pipe character in any
+substring, use $$ or $| respectively. Here is an example:
+.sp
+ echo -e "abcde\en12345" | pcre2grep \e
+ '(?x)(.)(..(.))
+ (?C"/bin/echo|Arg1: [$1] [$2] [$3]|Arg2: $|${1}$| ($4)")()' -
+.sp
+ Output:
+.sp
+ Arg1: [a] [bcd] [d] Arg2: |a| ()
+ abcde
+ Arg1: [1] [234] [4] Arg2: |1| ()
+ 12345
+.sp
+The parameters for the system call that is used to run the program or script
+are zero-terminated strings. This means that binary zero characters in the
+callout argument will cause premature termination of their substrings, and
+therefore should not be present. Any syntax errors in the string (for example,
+a dollar not followed by another character) causes the callout to be ignored.
+If running the program fails for any reason (including the non-existence of the
+executable), a local matching failure occurs and the matcher backtracks in the
+normal way.
+.
+.
+.SH "MATCHING ERRORS"
+.rs
+.sp
+It is possible to supply a regular expression that takes a very long time to
+fail to match certain lines. Such patterns normally involve nested indefinite
+repeats, for example: (a+)*\ed when matched against a line of a's with no final
+digit. The PCRE2 matching function has a resource limit that causes it to abort
+in these circumstances. If this happens, \fBpcre2grep\fP outputs an error
+message and the line that caused the problem to the standard error stream. If
+there are more than 20 such errors, \fBpcre2grep\fP gives up.
+.P
+The \fB--match-limit\fP option of \fBpcre2grep\fP can be used to set the
+overall resource limit. There are also other limits that affect the amount of
+memory used during matching; see the discussion of \fB--heap-limit\fP and
+\fB--depth-limit\fP above.
+.
+.
+.SH DIAGNOSTICS
+.rs
+.sp
+Exit status is 0 if any matches were found, 1 if no matches were found, and 2
+for syntax errors, overlong lines, non-existent or inaccessible files (even if
+matches were found in other files) or too many matching errors. Using the
+\fB-s\fP option to suppress error messages about inaccessible files does not
+affect the return code.
+.P
+When run under VMS, the return code is placed in the symbol PCRE2GREP_RC
+because VMS does not distinguish between exit(0) and exit(1).
+.
+.
+.SH "SEE ALSO"
+.rs
+.sp
+\fBpcre2pattern\fP(3), \fBpcre2syntax\fP(3), \fBpcre2callout\fP(3),
+\fBpcre2unicode\fP(3).
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 24 January 2025
+Copyright (c) 1997-2023 University of Cambridge.
+.fi
diff --git a/doc/pcre2grep.txt b/doc/pcre2grep.txt
new file mode 100644
index 0000000..99f14ab
--- /dev/null
+++ b/doc/pcre2grep.txt
@@ -0,0 +1,1106 @@
+PCRE2GREP(1) General Commands Manual PCRE2GREP(1)
+
+
+NAME
+ pcre2grep - a grep with Perl-compatible regular expressions.
+
+
+SYNOPSIS
+ pcre2grep [options] [long options] [pattern] [path1 path2 ...]
+
+
+DESCRIPTION
+
+ pcre2grep searches files for character patterns, in the same way as
+ other grep commands do, but it uses the PCRE2 regular expression li-
+ brary to support patterns that are compatible with the regular expres-
+ sions of Perl 5. See pcre2syntax(3) for a quick-reference summary of
+ pattern syntax, or pcre2pattern(3) for a full description of the syntax
+ and semantics of the regular expressions that PCRE2 supports.
+
+ Patterns, whether supplied on the command line or in a separate file,
+ are given without delimiters. For example:
+
+ pcre2grep Thursday /etc/motd
+
+ If you attempt to use delimiters (for example, by surrounding a pattern
+ with slashes, as is common in Perl scripts), they are interpreted as
+ part of the pattern. Quotes can of course be used to delimit patterns
+ on the command line because they are interpreted by the shell, and in-
+ deed quotes are required if a pattern contains white space or shell
+ metacharacters.
+
+ The first argument that follows any option settings is treated as the
+ single pattern to be matched when neither -e nor -f is present. Con-
+ versely, when one or both of these options are used to specify pat-
+ terns, all arguments are treated as path names. At least one of -e, -f,
+ or an argument pattern must be provided.
+
+ If no files are specified, pcre2grep reads the standard input. The
+ standard input can also be referenced by a name consisting of a single
+ hyphen. For example:
+
+ pcre2grep some-pattern file1 - file3
+
+ By default, input files are searched line by line, so pattern asser-
+ tions about the beginning and end of a subject string (^, $, \A, \Z,
+ and \z) match at the beginning and end of each line. When a line
+ matches a pattern, it is copied to the standard output, and if there is
+ more than one file, the file name is output at the start of each line,
+ followed by a colon. However, there are options that can change how
+ pcre2grep behaves. For example, the -M option makes it possible to
+ search for strings that span line boundaries. What defines a line
+ boundary is controlled by the -N (--newline) option. The -h and -H op-
+ tions control whether or not file names are shown, and the -Z option
+ changes the file name terminator to a zero byte.
+
+ The amount of memory used for buffering files that are being scanned is
+ controlled by parameters that can be set by the --buffer-size and
+ --max-buffer-size options. The first of these sets the size of buffer
+ that is obtained at the start of processing. If an input file contains
+ very long lines, a larger buffer may be needed; this is handled by au-
+ tomatically extending the buffer, up to the limit specified by --max-
+ buffer-size. The default values for these parameters can be set when
+ pcre2grep is built; if nothing is specified, the defaults are set to
+ 20KiB and 1MiB respectively. An error occurs if a line is too long and
+ the buffer can no longer be expanded.
+
+ The block of memory that is actually used is three times the "buffer
+ size", to allow for buffering "before" and "after" lines. If the buffer
+ size is too small, fewer than requested "before" and "after" lines may
+ be output.
+
+ When matching with a multiline pattern, the size of the buffer must be
+ at least half of the maximum match expected or the pattern might fail
+ to match.
+
+ Patterns can be no longer than 8KiB or BUFSIZ bytes, whichever is the
+ greater. BUFSIZ is defined in . When there is more than one
+ pattern (specified by the use of -e and/or -f), each pattern is applied
+ to each line in the order in which they are defined, except that all
+ the -e patterns are tried before the -f patterns.
+
+ By default, as soon as one pattern matches a line, no further patterns
+ are considered. However, if --colour (or --color) is used to colour the
+ matching substrings, or if --only-matching, --file-offsets, --line-off-
+ sets, or --output is used to output only the part of the line that
+ matched (either shown literally, or as an offset), the behaviour is
+ different. In this situation, all the patterns are applied to the line.
+ If there is more than one match, the one that begins nearest to the
+ start of the subject is processed; if there is more than one match at
+ that position, the one with the longest matching substring is
+ processed; if the matching substrings are equal, the first match found
+ is processed.
+
+ Scanning with all the patterns resumes immediately following the match,
+ so that later matches on the same line can be found. Note, however,
+ that an overlapping match that starts in the middle of another match
+ will not be processed.
+
+ The above behaviour was changed at release 10.41 to be more compatible
+ with GNU grep. In earlier releases, pcre2grep did not recognize matches
+ from later patterns that were earlier in the subject.
+
+ Patterns that can match an empty string are accepted, but empty string
+ matches are never recognized. An example is the pattern "(su-
+ per)?(man)?", in which all components are optional. This pattern finds
+ all occurrences of both "super" and "man"; the output differs from
+ matching with "super|man" when only the matching substrings are being
+ shown.
+
+ If the LC_ALL or LC_CTYPE environment variable is set, pcre2grep uses
+ the value to set a locale when calling the PCRE2 library. The --locale
+ option can be used to override this.
+
+
+SUPPORT FOR COMPRESSED FILES
+
+ Compile-time options for pcre2grep can set it up to use libz or libbz2
+ for reading compressed files whose names end in .gz or .bz2, respec-
+ tively. You can find out whether your pcre2grep binary has support for
+ one or both of these file types by running it with the --help option.
+ If the appropriate support is not present, all files are treated as
+ plain text. The standard input is always so treated. If a file with a
+ .gz or .bz2 extension is not in fact compressed, it is read as a plain
+ text file. When input is from a compressed .gz or .bz2 file, the
+ --line-buffered option is ignored.
+
+
+BINARY FILES
+
+ By default, a file that contains a binary zero byte within the first
+ 1024 bytes is identified as a binary file, and is processed specially.
+ However, if the newline type is specified as NUL, that is, the line
+ terminator is a binary zero, the test for a binary file is not applied.
+ See the --binary-files option for a means of changing the way binary
+ files are handled.
+
+
+BINARY ZEROS IN PATTERNS
+
+ Patterns passed from the command line are strings that are terminated
+ by a binary zero, so cannot contain internal zeros. However, patterns
+ that are read from a file via the -f option may contain binary zeros.
+
+
+OPTIONS
+
+ The order in which some of the options appear can affect the output.
+ For example, both the -H and -l options affect the printing of file
+ names. Whichever comes later in the command line will be the one that
+ takes effect. Similarly, except where noted below, if an option is
+ given twice, the later setting is used. Numerical values for options
+ may be followed by K or M, to signify multiplication by 1024 or
+ 1024*1024 respectively.
+
+ -- This terminates the list of options. It is useful if the next
+ item on the command line starts with a hyphen but is not an
+ option. This allows for the processing of patterns and file
+ names that start with hyphens.
+
+ -A number, --after-context=number
+ Output up to number lines of context after each matching
+ line. Fewer lines are output if the next match or the end of
+ the file is reached, or if the processing buffer size has
+ been set too small. If file names and/or line numbers are be-
+ ing output, a hyphen separator is used instead of a colon for
+ the context lines (the -Z option can be used to change the
+ file name terminator to a zero byte). A line containing "--"
+ is output between each group of lines, unless they are in
+ fact contiguous in the input file. The value of number is ex-
+ pected to be relatively small. When -c is used, -A is ig-
+ nored.
+
+ -a, --text
+ Treat binary files as text. This is equivalent to --binary-
+ files=text.
+
+ --allow-lookaround-bsk
+ PCRE2 now forbids the use of \K in lookarounds by default, in
+ line with Perl. This option causes pcre2grep to set the
+ PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK option, which enables this
+ somewhat dangerous usage.
+
+ -B number, --before-context=number
+ Output up to number lines of context before each matching
+ line. Fewer lines are output if the previous match or the
+ start of the file is within number lines, or if the process-
+ ing buffer size has been set too small. If file names and/or
+ line numbers are being output, a hyphen separator is used in-
+ stead of a colon for the context lines (the -Z option can be
+ used to change the file name terminator to a zero byte). A
+ line containing "--" is output between each group of lines,
+ unless they are in fact contiguous in the input file. The
+ value of number is expected to be relatively small. When -c
+ is used, -B is ignored.
+
+ --binary-files=word
+ Specify how binary files are to be processed. If the word is
+ "binary" (the default), pattern matching is performed on bi-
+ nary files, but the only output is "Binary file
+ matches" when a match succeeds. If the word is "text", which
+ is equivalent to the -a or --text option, binary files are
+ processed in the same way as any other file. In this case,
+ when a match succeeds, the output may be binary garbage,
+ which can have nasty effects if sent to a terminal. If the
+ word is "without-match", which is equivalent to the -I op-
+ tion, binary files are not processed at all; they are assumed
+ not to be of interest and are skipped without causing any
+ output or affecting the return code.
+
+ --buffer-size=number
+ Set the parameter that controls how much memory is obtained
+ at the start of processing for buffering files that are being
+ scanned. See also --max-buffer-size below.
+
+ -C number, --context=number
+ Output number lines of context both before and after each
+ matching line. This is equivalent to setting both -A and -B
+ to the same value.
+
+ -c, --count
+ Do not output lines from the files that are being scanned;
+ instead output the number of lines that would have been
+ shown, either because they matched, or, if -v is set, because
+ they failed to match. By default, this count is exactly the
+ same as the number of lines that would have been output, but
+ if the -M (multiline) option is used (without -v), there may
+ be more suppressed lines than the count (that is, the number
+ of matches).
+
+ If no lines are selected, the number zero is output. If sev-
+ eral files are being scanned, a count is output for each of
+ them and the -t option can be used to cause a total to be
+ output at the end. However, if the --files-with-matches op-
+ tion is also used, only those files whose counts are greater
+ than zero are listed. When -c is used, the -A, -B, and -C op-
+ tions are ignored.
+
+ --colour, --color
+ If this option is given without any data, it is equivalent to
+ "--colour=auto". If data is required, it must be given in
+ the same shell item, separated by an equals sign.
+
+ --colour=value, --color=value
+ This option specifies under what circumstances the parts of a
+ line that matched a pattern should be coloured in the output.
+ It is ignored if --file-offsets, --line-offsets, or --output
+ is set. By default, output is not coloured. The value for the
+ --colour option (which is optional, see above) may be
+ "never", "always", or "auto". In the latter case, colouring
+ happens only if the standard output is connected to a termi-
+ nal. More resources are used when colouring is enabled, be-
+ cause pcre2grep has to search for all possible matches in a
+ line, not just one, in order to colour them all.
+
+ The colour that is used can be specified by setting one of
+ the environment variables PCRE2GREP_COLOUR, PCRE2GREP_COLOR,
+ PCREGREP_COLOUR, or PCREGREP_COLOR, which are checked in that
+ order. If none of these are set, pcre2grep looks for
+ GREP_COLORS or GREP_COLOR (in that order). The value of the
+ variable should be a string of two numbers, separated by a
+ semicolon, except in the case of GREP_COLORS, which must
+ start with "ms=" or "mt=" followed by two semicolon-separated
+ colours, terminated by the end of the string or by a colon.
+ If GREP_COLORS does not start with "ms=" or "mt=" it is ig-
+ nored, and GREP_COLOR is checked.
+
+ If the string obtained from one of the above variables con-
+ tains any characters other than semicolon or digits, the set-
+ ting is ignored and the default colour is used. The string is
+ copied directly into the control string for setting colour on
+ a terminal, so it is your responsibility to ensure that the
+ values make sense. If no relevant environment variable is
+ set, the default is "1;31", which gives red.
+
+ -D action, --devices=action
+ If an input path is not a regular file or a directory, "ac-
+ tion" specifies how it is to be processed. Valid values are
+ "read" (the default) or "skip" (silently skip the path).
+
+ -d action, --directories=action
+ If an input path is a directory, "action" specifies how it is
+ to be processed. Valid values are "read" (the default in
+ non-Windows environments, for compatibility with GNU grep),
+ "recurse" (equivalent to the -r option), or "skip" (silently
+ skip the path, the default in Windows environments). In the
+ "read" case, directories are read as if they were ordinary
+ files. In some operating systems the effect of reading a di-
+ rectory like this is an immediate end-of-file; in others it
+ may provoke an error.
+
+ --depth-limit=number
+ See --match-limit below.
+
+ -E, --case-restrict
+ When case distinctions are being ignored in Unicode mode, two
+ ASCII letters (K and S) will by default match Unicode charac-
+ ters U+212A (Kelvin sign) and U+017F (long S) respectively,
+ as well as their lower case ASCII counterparts. When this op-
+ tion is set, case equivalences are restricted such that no
+ ASCII character matches a non-ASCII character, and vice
+ versa.
+
+ -e pattern, --regex=pattern, --regexp=pattern
+ Specify a pattern to be matched. This option can be used mul-
+ tiple times in order to specify several patterns. It can also
+ be used as a way of specifying a single pattern that starts
+ with a hyphen. When -e is used, no argument pattern is taken
+ from the command line; all arguments are treated as file
+ names. There is no limit to the number of patterns. They are
+ applied to each line in the order in which they are defined.
+
+ If -f is used with -e, the command line patterns are matched
+ first, followed by the patterns from the file(s), independent
+ of the order in which these options are specified.
+
+ --exclude=pattern
+ Files (but not directories) whose names match the pattern are
+ skipped without being processed. This applies to all files,
+ whether listed on the command line, obtained from --file-
+ list, or by scanning a directory. The pattern is a PCRE2 reg-
+ ular expression, and is matched against the final component
+ of the file name, not the entire path. The -F, -w, and -x op-
+ tions do not apply to this pattern. The option may be given
+ any number of times in order to specify multiple patterns. If
+ a file name matches both an --include and an --exclude pat-
+ tern, it is excluded. There is no short form for this option.
+
+ --exclude-from=filename
+ Treat each non-empty line of the file as the data for an
+ --exclude option. What constitutes a newline when reading the
+ file is the operating system's default. The --newline option
+ has no effect on this option. This option may be given more
+ than once in order to specify a number of files to read.
+
+ --exclude-dir=pattern
+ Directories whose names match the pattern are skipped without
+ being processed, whatever the setting of the --recursive op-
+ tion. This applies to all directories, whether listed on the
+ command line, obtained from --file-list, or by scanning a
+ parent directory. The pattern is a PCRE2 regular expression,
+ and is matched against the final component of the directory
+ name, not the entire path. The -F, -w, and -x options do not
+ apply to this pattern. The option may be given any number of
+ times in order to specify more than one pattern. If a direc-
+ tory matches both --include-dir and --exclude-dir, it is ex-
+ cluded. There is no short form for this option.
+
+ -F, --fixed-strings
+ Interpret each data-matching pattern as a list of fixed
+ strings, separated by newlines, instead of as a regular ex-
+ pression. What constitutes a newline for this purpose is con-
+ trolled by the --newline option. The -w (match as a word) and
+ -x (match whole line) options can be used with -F. They ap-
+ ply to each of the fixed strings. A line is selected if any
+ of the fixed strings are found in it (subject to -w or -x, if
+ present). This option applies only to the patterns that are
+ matched against the contents of files; it does not apply to
+ patterns specified by any of the --include or --exclude op-
+ tions.
+
+ -f filename, --file=filename
+ Read patterns from the file, one per line. As is the case
+ with patterns on the command line, no delimiters should be
+ used. What constitutes a newline when reading the file is the
+ operating system's default interpretation of \n. The --new-
+ line option has no effect on this option. Trailing white
+ space is removed from each line, and blank lines are ignored
+ unless the --posix-pattern-file option is also provided. An
+ empty file contains no patterns and therefore matches noth-
+ ing. Patterns read from a file in this way may contain binary
+ zeros, which are treated as ordinary character literals.
+
+ If this option is given more than once, all the specified
+ files are read. A data line is output if any of the patterns
+ match it. A file name can be given as "-" to refer to the
+ standard input. When -f is used, patterns specified on the
+ command line using -e may also be present; they are matched
+ before the file's patterns. However, no pattern is taken from
+ the command line; all arguments are treated as the names of
+ paths to be searched.
+
+ --file-list=filename
+ Read a list of files and/or directories that are to be
+ scanned from the given file, one per line. What constitutes a
+ newline when reading the file is the operating system's de-
+ fault. Trailing white space is removed from each line, and
+ blank lines are ignored. These paths are processed before any
+ that are listed on the command line. The file name can be
+ given as "-" to refer to the standard input. If --file and
+ --file-list are both specified as "-", patterns are read
+ first. This is useful only when the standard input is a ter-
+ minal, from which further lines (the list of files) can be
+ read after an end-of-file indication. If this option is given
+ more than once, all the specified files are read.
+
+ --file-offsets
+ Instead of showing lines or parts of lines that match, show
+ each match as an offset from the start of the file and a
+ length, separated by a comma. In this mode, --colour has no
+ effect, and no context is shown. That is, the -A, -B, and -C
+ options are ignored. If there is more than one match in a
+ line, each of them is shown separately. This option is mutu-
+ ally exclusive with --output, --line-offsets, and --only-
+ matching.
+
+ --group-separator=text
+ Output this text string instead of two hyphens between groups
+ of lines when -A, -B, or -C is in use. See also --no-group-
+ separator.
+
+ -H, --with-filename
+ Force the inclusion of the file name at the start of output
+ lines when searching a single file. The file name is not nor-
+ mally shown in this case. By default, for matching lines,
+ the file name is followed by a colon; for context lines, a
+ hyphen separator is used. The -Z option can be used to change
+ the terminator to a zero byte. If a line number is also being
+ output, it follows the file name. When the -M option causes a
+ pattern to match more than one line, only the first is pre-
+ ceded by the file name. This option overrides any previous
+ -h, -l, or -L options.
+
+ -h, --no-filename
+ Suppress the output file names when searching multiple files.
+ File names are normally shown when multiple files are
+ searched. By default, for matching lines, the file name is
+ followed by a colon; for context lines, a hyphen separator is
+ used. The -Z option can be used to change the terminator to a
+ zero byte. If a line number is also being output, it follows
+ the file name. This option overrides any previous -H, -L, or
+ -l options.
+
+ --heap-limit=number
+ See --match-limit below.
+
+ --help Output a help message, giving brief details of the command
+ options and file type support, and then exit. Anything else
+ on the command line is ignored.
+
+ -I Ignore binary files. This is equivalent to --binary-
+ files=without-match.
+
+ -i, --ignore-case
+ Ignore upper/lower case distinctions when pattern matching.
+ This applies when matching path names for inclusion or exclu-
+ sion as well as when matching lines in files.
+
+ --include=pattern
+ If any --include patterns are specified, the only files that
+ are processed are those whose names match one of the patterns
+ and do not match an --exclude pattern. This option does not
+ affect directories, but it applies to all files, whether
+ listed on the command line, obtained from --file-list, or by
+ scanning a directory. The pattern is a PCRE2 regular expres-
+ sion, and is matched against the final component of the file
+ name, not the entire path. The -F, -w, and -x options do not
+ apply to this pattern. The option may be given any number of
+ times. If a file name matches both an --include and an --ex-
+ clude pattern, it is excluded. There is no short form for
+ this option.
+
+ --include-from=filename
+ Treat each non-empty line of the file as the data for an
+ --include option. What constitutes a newline for this purpose
+ is the operating system's default. The --newline option has
+ no effect on this option. This option may be given any number
+ of times; all the files are read.
+
+ --include-dir=pattern
+ If any --include-dir patterns are specified, the only direc-
+ tories that are processed are those whose names match one of
+ the patterns and do not match an --exclude-dir pattern. This
+ applies to all directories, whether listed on the command
+ line, obtained from --file-list, or by scanning a parent di-
+ rectory. The pattern is a PCRE2 regular expression, and is
+ matched against the final component of the directory name,
+ not the entire path. The -F, -w, and -x options do not apply
+ to this pattern. The option may be given any number of times.
+ If a directory matches both --include-dir and --exclude-dir,
+ it is excluded. There is no short form for this option.
+
+ -L, --files-without-match
+ Instead of outputting lines from the files, just output the
+ names of the files that do not contain any lines that would
+ have been output. Each file name is output once, on a sepa-
+ rate line by default, but if the -Z option is set, they are
+ separated by zero bytes instead of newlines. This option
+ overrides any previous -H, -h, or -l options.
+
+ -l, --files-with-matches
+ Instead of outputting lines from the files, just output the
+ names of the files containing lines that would have been out-
+ put. Each file name is output once, on a separate line, but
+ if the -Z option is set, they are separated by zero bytes in-
+ stead of newlines. Searching normally stops as soon as a
+ matching line is found in a file. However, if the -c (count)
+ option is also used, matching continues in order to obtain
+ the correct count, and those files that have at least one
+ match are listed along with their counts. Using this option
+ with -c is a way of suppressing the listing of files with no
+ matches that occurs with -c on its own. This option overrides
+ any previous -H, -h, or -L options.
+
+ --label=name
+ This option supplies a name to be used for the standard input
+ when file names are being output. If not supplied, "(standard
+ input)" is used. There is no short form for this option.
+
+ --line-buffered
+ When this option is given, non-compressed input is read and
+ processed line by line, and the output is flushed after each
+ write. By default, input is read in large chunks, unless
+ pcre2grep can determine that it is reading from a terminal,
+ which is currently possible only in Unix-like environments or
+ Windows. Output to terminal is normally automatically flushed
+ by the operating system. This option can be useful when the
+ input or output is attached to a pipe and you do not want
+ pcre2grep to buffer up large amounts of data. However, its
+ use will affect performance, and the -M (multiline) option
+ ceases to work. When input is from a compressed .gz or .bz2
+ file, --line-buffered is ignored.
+
+ --line-offsets
+ Instead of showing lines or parts of lines that match, show
+ each match as a line number, the offset from the start of the
+ line, and a length. The line number is terminated by a colon
+ (as usual; see the -n option), and the offset and length are
+ separated by a comma. In this mode, --colour has no effect,
+ and no context is shown. That is, the -A, -B, and -C options
+ are ignored. If there is more than one match in a line, each
+ of them is shown separately. This option is mutually exclu-
+ sive with --output, --file-offsets, and --only-matching.
+
+ --locale=locale-name
+ This option specifies a locale to be used for pattern match-
+ ing. It overrides the value in the LC_ALL or LC_CTYPE envi-
+ ronment variables. If no locale is specified, the PCRE2 li-
+ brary's default (usually the "C" locale) is used. There is no
+ short form for this option.
+
+ -M, --multiline
+ Allow patterns to match more than one line. When this option
+ is set, the PCRE2 library is called in "multiline" mode, and
+ a match is allowed to continue past the end of the initial
+ line and onto one or more subsequent lines.
+
+ Patterns used with -M may usefully contain literal newline
+ characters and internal occurrences of ^ and $ characters,
+ because in multiline mode these can match at internal new-
+ lines. Because pcre2grep is scanning multiple lines, the \Z
+ and \z assertions match only at the end of the last line in
+ the file. The \A assertion matches at the start of the first
+ line of a match. This can be any line in the file; it is not
+ anchored to the first line.
+
+ The output for a successful match may consist of more than
+ one line. The first line is the line in which the match
+ started, and the last line is the line in which the match
+ ended. If the matched string ends with a newline sequence,
+ the output ends at the end of that line. If -v is set, none
+ of the lines in a multi-line match are output. Once a match
+ has been handled, scanning restarts at the beginning of the
+ line after the one in which the match ended.
+
+ The newline sequence that separates multiple lines must be
+ matched as part of the pattern. For example, to find the
+ phrase "regular expression" in a file where "regular" might
+ be at the end of a line and "expression" at the start of the
+ next line, you could use this command:
+
+ pcre2grep -M 'regular\s+expression'
+
+ The \s escape sequence matches any white space character, in-
+ cluding newlines, and is followed by + so as to match trail-
+ ing white space on the first line as well as possibly han-
+ dling a two-character newline sequence.
+
+ There is a limit to the number of lines that can be matched,
+ imposed by the way that pcre2grep buffers the input file as
+ it scans it. With a sufficiently large processing buffer,
+ this should not be a problem.
+
+ The -M option does not work when input is read line by line
+ (see --line-buffered.)
+
+ -m number, --max-count=number
+ Stop processing after finding number matching lines, or non-
+ matching lines if -v is also set. Any trailing context lines
+ are output after the final match. In multiline mode, each
+ multiline match counts as just one line for this purpose. If
+ this limit is reached when reading the standard input from a
+ regular file, the file is left positioned just after the last
+ matching line. If -c is also set, the count that is output
+ is never greater than number. This option has no effect if
+ used with -L, -l, or -q, or when just checking for a match in
+ a binary file.
+
+ --match-limit=number
+ Processing some regular expression patterns may take a very
+ long time to search for all possible matching strings. Others
+ may require a very large amount of memory. There are three
+ options that set resource limits for matching.
+
+ The --match-limit option provides a means of limiting comput-
+ ing resource usage when processing patterns that are not go-
+ ing to match, but which have a very large number of possibil-
+ ities in their search trees. The classic example is a pattern
+ that uses nested unlimited repeats. Internally, PCRE2 has a
+ counter that is incremented each time around its main pro-
+ cessing loop. If the value set by --match-limit is reached,
+ an error occurs.
+
+ The --heap-limit option specifies, as a number of kibibytes
+ (units of 1024 bytes), the maximum amount of heap memory that
+ may be used for matching.
+
+ The --depth-limit option limits the depth of nested back-
+ tracking points, which indirectly limits the amount of memory
+ that is used. The amount of memory needed for each backtrack-
+ ing point depends on the number of capturing parentheses in
+ the pattern, so the amount of memory that is used before this
+ limit acts varies from pattern to pattern. This limit is of
+ use only if it is set smaller than --match-limit.
+
+ There are no short forms for these options. The default lim-
+ its can be set when the PCRE2 library is compiled; if they
+ are not specified, the defaults are very large and so effec-
+ tively unlimited.
+
+ --max-buffer-size=number
+ This limits the expansion of the processing buffer, whose
+ initial size can be set by --buffer-size. The maximum buffer
+ size is silently forced to be no smaller than the starting
+ buffer size.
+
+ -N newline-type, --newline=newline-type
+ Six different conventions for indicating the ends of lines in
+ scanned files are supported. For example:
+
+ pcre2grep -N CRLF 'some pattern'
+
+ The newline type may be specified in upper, lower, or mixed
+ case. If the newline type is NUL, lines are separated by bi-
+ nary zero characters. The other types are the single-charac-
+ ter sequences CR (carriage return) and LF (linefeed), the
+ two-character sequence CRLF, an "anycrlf" type, which recog-
+ nizes any of the preceding three types, and an "any" type,
+ for which any Unicode line ending sequence is assumed to end
+ a line. The Unicode sequences are the three just mentioned,
+ plus VT (vertical tab, U+000B), FF (form feed, U+000C), NEL
+ (next line, U+0085), LS (line separator, U+2028), and PS
+ (paragraph separator, U+2029).
+
+ When the PCRE2 library is built, a default line-ending se-
+ quence is specified. This is normally the standard sequence
+ for the operating system. Unless otherwise specified by this
+ option, pcre2grep uses the library's default.
+
+ This option makes it possible to use pcre2grep to scan files
+ that have come from other environments without having to mod-
+ ify their line endings. If the data that is being scanned
+ does not agree with the convention set by this option,
+ pcre2grep may behave in strange ways. Note that this option
+ does not apply to files specified by the -f, --exclude-from,
+ or --include-from options, which are expected to use the op-
+ erating system's standard newline sequence.
+
+ -n, --line-number
+ Precede each output line by its line number in the file, fol-
+ lowed by a colon for matching lines or a hyphen for context
+ lines. If the file name is also being output, it precedes the
+ line number. When the -M option causes a pattern to match
+ more than one line, only the first is preceded by its line
+ number. This option is forced if --line-offsets is used.
+
+ --no-group-separator
+ Do not output a separator between groups of lines when -A,
+ -B, or -C is in use. The default is to output a line contain-
+ ing two hyphens. See also --group-separator.
+
+ --no-jit If the PCRE2 library is built with support for just-in-time
+ compiling (which speeds up matching), pcre2grep automatically
+ makes use of this, unless it was explicitly disabled at build
+ time. This option can be used to disable the use of JIT at
+ run time. It is provided for testing and working around prob-
+ lems. It should never be needed in normal use.
+
+ -O text, --output=text
+ When there is a match, instead of outputting the line that
+ matched, output just the text specified in this option, fol-
+ lowed by an operating-system standard newline. In this mode,
+ --colour has no effect, and no context is shown. That is,
+ the -A, -B, and -C options are ignored. The --newline option
+ has no effect on this option, which is mutually exclusive
+ with --only-matching, --file-offsets, and --line-offsets.
+ However, like --only-matching, if there is more than one
+ match in a line, each of them causes a line of output.
+
+ Escape sequences starting with a dollar character may be used
+ to insert the contents of the matched part of the line and/or
+ captured substrings into the text.
+
+ $ or ${} is replaced by the captured sub-
+ string of the given decimal number; $& (or the legacy $0)
+ substitutes the whole match. If the number is greater than
+ the number of capturing substrings, or if the capture is un-
+ set, the replacement is empty.
+
+ $a is replaced by bell; $b by backspace; $e by escape; $f by
+ form feed; $n by newline; $r by carriage return; $t by tab;
+ $v by vertical tab.
+
+ $o or $o{} is replaced by the character whose
+ code point is the given octal number. In the first form, up
+ to three octal digits are processed. When more digits are
+ needed in Unicode mode to specify a wide character, the sec-
+ ond form must be used.
+
+ $x or $x{} is replaced by the character rep-
+ resented by the given hexadecimal number. In the first form,
+ up to two hexadecimal digits are processed. When more digits
+ are needed in Unicode mode to specify a wide character, the
+ second form must be used.
+
+ Any other character is substituted by itself. In particular,
+ $$ is replaced by a single dollar.
+
+ -o, --only-matching
+ Show only the part of the line that matched a pattern instead
+ of the whole line. In this mode, no context is shown. That
+ is, the -A, -B, and -C options are ignored. If there is more
+ than one match in a line, each of them is shown separately,
+ on a separate line of output. If -o is combined with -v (in-
+ vert the sense of the match to find non-matching lines), no
+ output is generated, but the return code is set appropri-
+ ately. If the matched portion of the line is empty, nothing
+ is output unless the file name or line number are being
+ printed, in which case they are shown on an otherwise empty
+ line. This option is mutually exclusive with --output,
+ --file-offsets and --line-offsets.
+
+ -onumber, --only-matching=number
+ Show only the part of the line that matched the capturing
+ parentheses of the given number. Up to 50 capturing parenthe-
+ ses are supported by default. This limit can be changed via
+ the --om-capture option. A pattern may contain any number of
+ capturing parentheses, but only those whose number is within
+ the limit can be accessed by -o. An error occurs if the num-
+ ber specified by -o is greater than the limit.
+
+ -o0 is the same as -o without a number. Because these options
+ can be given without an argument (see above), if an argument
+ is present, it must be given in the same shell item, for ex-
+ ample, -o3 or --only-matching=2. The comments given for the
+ non-argument case above also apply to this option. If the
+ specified capturing parentheses do not exist in the pattern,
+ or were not set in the match, nothing is output unless the
+ file name or line number are being output.
+
+ If this option is given multiple times, multiple substrings
+ are output for each match, in the order the options are
+ given, and all on one line. For example, -o3 -o1 -o3 causes
+ the substrings matched by capturing parentheses 3 and 1 and
+ then 3 again to be output. By default, there is no separator
+ (but see the next but one option).
+
+ --om-capture=number
+ Set the number of capturing parentheses that can be accessed
+ by -o. The default is 50.
+
+ --om-separator=text
+ Specify a separating string for multiple occurrences of -o.
+ The default is an empty string. Separating strings are never
+ coloured.
+
+ -P, --no-ucp
+ Starting from release 10.43, when UTF/Unicode mode is speci-
+ fied with -u or -U, the PCRE2_UCP option is used by default.
+ This means that the POSIX classes in patterns match more than
+ just ASCII characters. For example, [:digit:] matches any
+ Unicode decimal digit. The --no-ucp option suppresses
+ PCRE2_UCP, thus restricting the POSIX classes to ASCII char-
+ acters, as was the case in earlier releases. Note that there
+ are now more fine-grained option settings within patterns
+ that affect individual classes. For example, when in UCP
+ mode, the sequence (?aP) restricts [:word:] to ASCII letters,
+ while allowing \w to match Unicode letters and digits.
+
+ --posix-pattern-file
+ When patterns are provided with the -f option, do not trim
+ trailing spaces or ignore empty lines in a similar way than
+ other grep tools. To keep the behaviour consistent with older
+ versions, if the pattern read was terminated with CRLF (as
+ character literals) then both characters won't be included as
+ part of it, so if you really need to have pattern ending in
+ '\r', use a escape sequence or provide it by a different
+ method.
+
+ -q, --quiet
+ Work quietly, that is, display nothing except error messages.
+ The exit status indicates whether or not any matches were
+ found.
+
+ -r, --recursive
+ If any given path is a directory, recursively scan the files
+ it contains, taking note of any --include and --exclude set-
+ tings. By default, a directory is read as a normal file; in
+ some operating systems this gives an immediate end-of-file.
+ This option is a shorthand for setting the -d option to "re-
+ curse".
+
+ --recursion-limit=number
+ This is an obsolete synonym for --depth-limit. See --match-
+ limit above for details.
+
+ -s, --no-messages
+ Suppress error messages about non-existent or unreadable
+ files. Such files are quietly skipped. However, the return
+ code is still 2, even if matches were found in other files.
+
+ -t, --total-count
+ This option is useful when scanning more than one file. If
+ used on its own, -t suppresses all output except for a grand
+ total number of matching lines (or non-matching lines if -v
+ is used) in all the files. If -t is used with -c, a grand to-
+ tal is output except when the previous output is just one
+ line. In other words, it is not output when just one file's
+ count is listed. If file names are being output, the grand
+ total is preceded by "TOTAL:". Otherwise, it appears as just
+ another number. The -t option is ignored when used with -L
+ (list files without matches), because the grand total would
+ always be zero.
+
+ -u, --utf Operate in UTF/Unicode mode. This option is available only if
+ PCRE2 has been compiled with UTF-8 support. All patterns (in-
+ cluding those for any --exclude and --include options) and
+ all lines that are scanned must be valid strings of UTF-8
+ characters. If an invalid UTF-8 string is encountered, an er-
+ ror occurs.
+
+ -U, --utf-allow-invalid
+ As --utf, but in addition subject lines may contain invalid
+ UTF-8 code unit sequences. These can never form part of any
+ pattern match. Patterns themselves, however, must still be
+ valid UTF-8 strings. This facility allows valid UTF-8 strings
+ to be sought within arbitrary byte sequences in executable or
+ other binary files. For more details about matching in non-
+ valid UTF-8 strings, see the pcre2unicode(3) documentation.
+
+ -V, --version
+ Write the version numbers of pcre2grep and the PCRE2 library
+ to the standard output and then exit. Anything else on the
+ command line is ignored.
+
+ -v, --invert-match
+ Invert the sense of the match, so that lines which do not
+ match any of the patterns are the ones that are found. When
+ this option is set, options such as --only-matching and
+ --output, which specify parts of a match that are to be out-
+ put, are ignored.
+
+ -w, --word-regex, --word-regexp
+ Force the patterns only to match "words". That is, there must
+ be a word boundary at the start and end of each matched
+ string. This is equivalent to having "\b(?:" at the start of
+ each pattern, and ")\b" at the end. This option applies only
+ to the patterns that are matched against the contents of
+ files; it does not apply to patterns specified by any of the
+ --include or --exclude options.
+
+ -x, --line-regex, --line-regexp
+ Force the patterns to start matching only at the beginnings
+ of lines, and in addition, require them to match entire
+ lines. In multiline mode the match may be more than one line.
+ This is equivalent to having "^(?:" at the start of each pat-
+ tern and ")$" at the end. This option applies only to the
+ patterns that are matched against the contents of files; it
+ does not apply to patterns specified by any of the --include
+ or --exclude options.
+
+ -Z, --null
+ Terminate files names in the regular output with a zero byte
+ (the NUL character) instead of what would normally appear.
+ This is useful when file names contain unusual characters
+ such as colons, hyphens, or even newlines. The option does
+ not apply to file names in error messages.
+
+
+ENVIRONMENT VARIABLES
+
+ The environment variables LC_ALL and LC_CTYPE are examined, in that or-
+ der, for a locale. The first one that is set is used. This can be over-
+ ridden by the --locale option. If no locale is set, the PCRE2 library's
+ default (usually the "C" locale) is used.
+
+
+NEWLINES
+
+ The -N (--newline) option allows pcre2grep to scan files with newline
+ conventions that differ from the default. This option affects only the
+ way scanned files are processed. It does not affect the interpretation
+ of files specified by the -f, --file-list, --exclude-from, or --in-
+ clude-from options.
+
+ Any parts of the scanned input files that are written to the standard
+ output are copied with whatever newline sequences they have in the in-
+ put. However, if the final line of a file is output, and it does not
+ end with a newline sequence, a newline sequence is added. If the new-
+ line setting is CR, LF, CRLF or NUL, that line ending is output; for
+ the other settings (ANYCRLF or ANY) a single NL is used.
+
+ The newline setting does not affect the way in which pcre2grep writes
+ newlines in informational messages to the standard output and error
+ streams. Under Windows, the standard output is set to be binary, so
+ that "\r\n" at the ends of output lines that are copied from the input
+ is not converted to "\r\r\n" by the C I/O library. This means that any
+ messages written to the standard output must end with "\r\n". For all
+ other operating systems, and for all messages to the standard error
+ stream, "\n" is used.
+
+
+OPTIONS COMPATIBILITY WITH GNU GREP
+
+ Many of the short and long forms of pcre2grep's options are the same as
+ in the GNU grep program. Any long option of the form --xxx-regexp (GNU
+ terminology) is also available as --xxx-regex (PCRE2 terminology).
+ However, the --case-restrict, --depth-limit, -E, --file-list, --file-
+ offsets, --heap-limit, --include-dir, --line-offsets, --locale,
+ --match-limit, -M, --multiline, -N, --newline, --no-ucp, --om-separa-
+ tor, --output, -P, -u, --utf, -U, and --utf-allow-invalid options are
+ specific to pcre2grep, as is the use of the --only-matching option with
+ a capturing parentheses number.
+
+ Although most of the common options work the same way, a few are dif-
+ ferent in pcre2grep. For example, the --include option's argument is a
+ glob for GNU grep, but in pcre2grep it is a regular expression to which
+ the -i option applies. If both the -c and -l options are given, GNU
+ grep lists only file names, without counts, but pcre2grep gives the
+ counts as well.
+
+
+OPTIONS WITH DATA
+
+ There are four different ways in which an option with data can be spec-
+ ified. If a short form option is used, the data may follow immedi-
+ ately, or (with one exception) in the next command line item. For exam-
+ ple:
+
+ -f/some/file
+ -f /some/file
+
+ The exception is the -o option, which may appear with or without data.
+ Because of this, if data is present, it must follow immediately in the
+ same item, for example -o3.
+
+ If a long form option is used, the data may appear in the same command
+ line item, separated by an equals character, or (with two exceptions)
+ it may appear in the next command line item. For example:
+
+ --file=/some/file
+ --file /some/file
+
+ Note, however, that if you want to supply a file name beginning with ~
+ as data in a shell command, and have the shell expand ~ to a home di-
+ rectory, you must separate the file name from the option, because the
+ shell does not treat ~ specially unless it is at the start of an item.
+
+ The exceptions to the above are the --colour (or --color) and --only-
+ matching options, for which the data is optional. If one of these op-
+ tions does have data, it must be given in the first form, using an
+ equals character. Otherwise pcre2grep will assume that it has no data.
+
+
+USING PCRE2'S CALLOUT FACILITY
+
+ pcre2grep has, by default, support for calling external programs or
+ scripts or echoing specific strings during matching by making use of
+ PCRE2's callout facility. However, this support can be completely or
+ partially disabled when pcre2grep is built. You can find out whether
+ your binary has support for callouts by running it with the --help op-
+ tion. If callout support is completely disabled, callouts in patterns
+ are forbidden by pcre2grep. If the facility is partially disabled,
+ calling external programs is not supported, and callouts that request
+ it are ignored.
+
+ A callout in a PCRE2 pattern is of the form (?C) where the argu-
+ ment is either a number or a quoted string (see the pcre2callout docu-
+ mentation for details). Numbered callouts are ignored by pcre2grep;
+ only callouts with string arguments are useful.
+
+ Echoing a specific string
+
+ Starting the callout string with a pipe character invokes an echoing
+ facility that avoids calling an external program or script. This facil-
+ ity is always available, provided that callouts were not completely
+ disabled when pcre2grep was built. The rest of the callout string is
+ processed as a zero-terminated string, which means it should not con-
+ tain any internal binary zeros. It is written to the output, having
+ first been passed through the same escape processing as text from the
+ --output (-O) option (see above). However, $0 or $& cannot be used to
+ insert a matched substring because the match is still in progress. In-
+ stead, the single character '0' is inserted. Any syntax errors in the
+ string (for example, a dollar not followed by another character) causes
+ the callout to be ignored. No terminator is added to the output string,
+ so if you want a newline, you must include it explicitly using the es-
+ cape $n. For example:
+
+ pcre2grep '(.)(..(.))(?C"|[$1] [$2] [$3]$n")'
+
+ Matching continues normally after the string is output. If you want to
+ see only the callout output but not any output from an actual match,
+ you should end the pattern with (*FAIL).
+
+ Calling external programs or scripts
+
+ This facility can be independently disabled when pcre2grep is built. It
+ is supported for Windows, where a call to _spawnvp() is used, for VMS,
+ where lib$spawn() is used, and for any Unix-like environment where
+ fork() and execv() are available.
+
+ If the callout string does not start with a pipe (vertical bar) charac-
+ ter, it is parsed into a list of substrings separated by pipe charac-
+ ters. The first substring must be an executable name, with the follow-
+ ing substrings specifying arguments:
+
+ executable_name|arg1|arg2|...
+
+ Any substring (including the executable name) may contain escape se-
+ quences started by a dollar character. These are the same as for the
+ --output (-O) option documented above, except that $0 or $& cannot in-
+ sert the matched string because the match is still in progress. In-
+ stead, the character '0' is inserted. If you need a literal dollar or
+ pipe character in any substring, use $$ or $| respectively. Here is an
+ example:
+
+ echo -e "abcde\n12345" | pcre2grep \
+ '(?x)(.)(..(.))
+ (?C"/bin/echo|Arg1: [$1] [$2] [$3]|Arg2: $|${1}$| ($4)")()' -
+
+ Output:
+
+ Arg1: [a] [bcd] [d] Arg2: |a| ()
+ abcde
+ Arg1: [1] [234] [4] Arg2: |1| ()
+ 12345
+
+ The parameters for the system call that is used to run the program or
+ script are zero-terminated strings. This means that binary zero charac-
+ ters in the callout argument will cause premature termination of their
+ substrings, and therefore should not be present. Any syntax errors in
+ the string (for example, a dollar not followed by another character)
+ causes the callout to be ignored. If running the program fails for any
+ reason (including the non-existence of the executable), a local match-
+ ing failure occurs and the matcher backtracks in the normal way.
+
+
+MATCHING ERRORS
+
+ It is possible to supply a regular expression that takes a very long
+ time to fail to match certain lines. Such patterns normally involve
+ nested indefinite repeats, for example: (a+)*\d when matched against a
+ line of a's with no final digit. The PCRE2 matching function has a re-
+ source limit that causes it to abort in these circumstances. If this
+ happens, pcre2grep outputs an error message and the line that caused
+ the problem to the standard error stream. If there are more than 20
+ such errors, pcre2grep gives up.
+
+ The --match-limit option of pcre2grep can be used to set the overall
+ resource limit. There are also other limits that affect the amount of
+ memory used during matching; see the discussion of --heap-limit and
+ --depth-limit above.
+
+
+DIAGNOSTICS
+
+ Exit status is 0 if any matches were found, 1 if no matches were found,
+ and 2 for syntax errors, overlong lines, non-existent or inaccessible
+ files (even if matches were found in other files) or too many matching
+ errors. Using the -s option to suppress error messages about inaccessi-
+ ble files does not affect the return code.
+
+ When run under VMS, the return code is placed in the symbol
+ PCRE2GREP_RC because VMS does not distinguish between exit(0) and
+ exit(1).
+
+
+SEE ALSO
+
+ pcre2pattern(3), pcre2syntax(3), pcre2callout(3), pcre2unicode(3).
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 24 January 2025
+ Copyright (c) 1997-2023 University of Cambridge.
+
+
+PCRE2 10.48 24 January 2025 PCRE2GREP(1)
diff --git a/doc/pcre2jit.3 b/doc/pcre2jit.3
new file mode 100644
index 0000000..947cd41
--- /dev/null
+++ b/doc/pcre2jit.3
@@ -0,0 +1,490 @@
+.TH PCRE2JIT 3 "08 August 2026" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH "PCRE2 JUST-IN-TIME COMPILER SUPPORT"
+.rs
+.sp
+Just-in-time compiling is a heavyweight optimization that can greatly speed up
+pattern matching. However, it comes at the cost of extra processing before the
+match is performed, so it is of most benefit when the same pattern is going to
+be matched many times. This does not necessarily mean many calls of a matching
+function; if the pattern is not anchored, matching attempts may take place many
+times at various positions in the subject, even for a single call. Therefore,
+if the subject string is very long, it may still pay to use JIT even for
+one-off matches. JIT support is available for all of the 8-bit, 16-bit and
+32-bit PCRE2 libraries.
+.P
+JIT support applies only to the traditional Perl-compatible matching function.
+It does not apply when the DFA matching function is being used. The code for
+JIT support was written by Zoltan Herczeg.
+.
+.
+.SH "AVAILABILITY OF JIT SUPPORT"
+.rs
+.sp
+JIT support is an optional feature of PCRE2. The "configure" option
+--enable-jit (or equivalent CMake option) must be set when PCRE2 is built if
+you want to use JIT. The support is limited to the following hardware
+platforms:
+.sp
+ ARM 32-bit (v7, and Thumb2)
+ ARM 64-bit
+ IBM s390x 64 bit
+ Intel x86 32-bit and 64-bit
+ LoongArch 64 bit
+ MIPS 32-bit and 64-bit
+ Power PC 32-bit and 64-bit
+ RISC-V 32-bit and 64-bit
+.sp
+If --enable-jit is set on an unsupported platform, compilation fails.
+.P
+A client program can tell if JIT support has been compiled by calling
+\fBpcre2_config()\fP with the PCRE2_CONFIG_JIT option. The result is one if
+PCRE2 was built with JIT support, and zero otherwise. However, having the JIT
+code available does not guarantee that it will be used for any particular
+match. One reason for this is that there are a number of options and pattern
+items that are
+.\" HTML
+.\"
+not supported by JIT
+.\"
+(see below). Another reason is that in some environments JIT is unable to get
+executable memory in which to build its compiled code. The only guarantee from
+\fBpcre2_config()\fP is that if it returns zero, JIT will definitely \fInot\fP
+be used.
+.P
+As of release 10.45 there is a more informative way to test for JIT support. If
+\fBpcre2_compile_jit()\fP is called with the single option PCRE2_JIT_TEST_ALLOC
+it returns zero if JIT is available and has a working allocator. Otherwise it
+returns PCRE2_ERROR_NOMEMORY if JIT is available but cannot allocate executable
+memory, or PCRE2_ERROR_JIT_UNSUPPORTED if JIT support is not compiled. The
+code argument is ignored, so it can be a NULL value.
+.P
+A simple program does not need to check availability in order to use JIT when
+possible. The API is implemented in a way that falls back to the interpretive
+code if JIT is not available or cannot be used for a given match. For programs
+that need the best possible performance, there is a
+.\" HTML
+.\"
+"fast path"
+.\"
+API that is JIT-specific.
+.
+.
+.SH "SIMPLE USE OF JIT"
+.rs
+.sp
+To make use of the JIT support in the simplest way, all you have to do is to
+call \fBpcre2_jit_compile()\fP after successfully compiling a pattern with
+\fBpcre2_compile()\fP. This function has two arguments: the first is the
+compiled pattern pointer that was returned by \fBpcre2_compile()\fP, and the
+second is zero or more of the following option bits: PCRE2_JIT_COMPLETE,
+PCRE2_JIT_PARTIAL_HARD, or PCRE2_JIT_PARTIAL_SOFT.
+.P
+If JIT support is not available, a call to \fBpcre2_jit_compile()\fP does
+nothing and returns PCRE2_ERROR_JIT_BADOPTION. Otherwise, the compiled pattern
+is passed to the JIT compiler, which turns it into machine code that executes
+much faster than the normal interpretive code, but yields exactly the same
+results. The returned value from \fBpcre2_jit_compile()\fP is zero on success,
+or a negative error code.
+.P
+There is a limit to the size of pattern that JIT supports, imposed by the size
+of machine stack that it uses. The exact rules are not documented because they
+may change at any time, in particular, when new optimizations are introduced.
+If a pattern is too big, a call to \fBpcre2_jit_compile()\fP returns
+PCRE2_ERROR_NOMEMORY.
+.P
+PCRE2_JIT_COMPLETE requests the JIT compiler to generate code for complete
+matches. If you want to run partial matches using the PCRE2_PARTIAL_HARD or
+PCRE2_PARTIAL_SOFT options of \fBpcre2_match()\fP, you should set one or both
+of the other options as well as, or instead of PCRE2_JIT_COMPLETE. The JIT
+compiler generates different optimized code for each of the three modes
+(normal, soft partial, hard partial). When \fBpcre2_match()\fP is called, the
+appropriate code is run if it is available. Otherwise, the pattern is matched
+using interpretive code.
+.P
+You can call \fBpcre2_jit_compile()\fP multiple times for the same compiled
+pattern. It does nothing if it has previously compiled code for any of the
+option bits. For example, you can call it once with PCRE2_JIT_COMPLETE and
+(perhaps later, when you find you need partial matching) again with
+PCRE2_JIT_COMPLETE and PCRE2_JIT_PARTIAL_HARD. This time it will ignore
+PCRE2_JIT_COMPLETE and just compile code for partial matching. If
+\fBpcre2_jit_compile()\fP is called with no option bits set, it immediately
+returns zero. This is an alternative way of testing whether JIT support has
+been compiled.
+.P
+At present, it is not possible to free JIT compiled code except when the entire
+compiled pattern is freed by calling \fBpcre2_code_free()\fP.
+.P
+In some circumstances you may need to call additional functions. These are
+described in the section entitled
+.\" HTML
+.\"
+"Controlling the JIT stack"
+.\"
+below.
+.P
+There are some \fBpcre2_match()\fP options that are not supported by JIT, and
+there are also some pattern items that JIT cannot handle. Details are given
+.\" HTML
+.\"
+below.
+.\"
+In both cases, matching automatically falls back to the interpretive code. If
+you want to know whether JIT was actually used for a particular match, you
+should arrange for a JIT callback function to be set up as described in the
+section entitled
+.\" HTML
+.\"
+"Controlling the JIT stack"
+.\"
+below, even if you do not need to supply a non-default JIT stack. Such a
+callback function is called whenever JIT code is about to be obeyed. If the
+match-time options are not right for JIT execution, the callback function is
+not obeyed.
+.P
+If the JIT compiler finds an unsupported item, no JIT data is generated. You
+can find out if JIT compilation was successful for a compiled pattern by
+calling \fBpcre2_pattern_info()\fP with the PCRE2_INFO_JITSIZE option. A
+non-zero result means that JIT compilation was successful. A result of 0 means
+that JIT support is not available, or the pattern was not processed by
+\fBpcre2_jit_compile()\fP, or the JIT compiler was not able to handle the
+pattern. Successful JIT compilation does not, however, guarantee the use of JIT
+at match time because there are some match time options that are not supported
+by JIT.
+.
+.
+.SH "MATCHING SUBJECTS CONTAINING INVALID UTF"
+.rs
+.sp
+When a pattern is compiled with the PCRE2_UTF option, subject strings are
+normally expected to be a valid sequence of UTF code units. By default, this is
+checked at the start of matching and an error is generated if invalid UTF is
+detected. The PCRE2_NO_UTF_CHECK option can be passed to \fBpcre2_match()\fP to
+skip the check (for improved performance) if you are sure that a subject string
+is valid. If this option is used with an invalid string, the result is
+undefined. The calling program may crash or loop or otherwise misbehave.
+.P
+However, a way of running matches on strings that may contain invalid UTF
+sequences is available. Calling \fBpcre2_compile()\fP with the
+PCRE2_MATCH_INVALID_UTF option has two effects: it tells the interpreter in
+\fBpcre2_match()\fP to support invalid UTF, and, if \fBpcre2_jit_compile()\fP
+is subsequently called, the compiled JIT code also supports invalid UTF.
+Details of how this support works, in both the JIT and the interpretive cases,
+is given in the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+documentation.
+.P
+There is also an obsolete option for \fBpcre2_jit_compile()\fP called
+PCRE2_JIT_INVALID_UTF, which currently exists only for backward compatibility.
+It is superseded by the \fBpcre2_compile()\fP option PCRE2_MATCH_INVALID_UTF
+and should no longer be used. It may be removed in future.
+.
+.
+.\" HTML
+.SH "UNSUPPORTED OPTIONS AND PATTERN ITEMS"
+.rs
+.sp
+The \fBpcre2_match()\fP options that are supported for JIT matching are
+PCRE2_COPY_MATCHED_SUBJECT, PCRE2_NOTBOL, PCRE2_NOTEOL, PCRE2_NOTEMPTY,
+PCRE2_NOTEMPTY_ATSTART, PCRE2_NO_UTF_CHECK, PCRE2_PARTIAL_HARD, and
+PCRE2_PARTIAL_SOFT. The PCRE2_ANCHORED and PCRE2_ENDANCHORED options are not
+supported at match time.
+.P
+If the PCRE2_NO_JIT option is passed to \fBpcre2_match()\fP it disables the
+use of JIT, forcing matching by the interpreter code.
+.P
+The only unsupported pattern items are \eC (match a single data unit) when
+running in a UTF mode, and a callout immediately before an assertion condition
+in a conditional group.
+.
+.
+.SH "RETURN VALUES FROM JIT MATCHING"
+.rs
+.sp
+When a pattern is matched using JIT, the return values are the same as those
+given by the interpretive \fBpcre2_match()\fP code, with the addition of one
+new error code: PCRE2_ERROR_JIT_STACKLIMIT. This means that the memory used for
+the JIT stack was insufficient. See
+.\" HTML
+.\"
+"Controlling the JIT stack"
+.\"
+below for a discussion of JIT stack usage.
+.P
+The error code PCRE2_ERROR_MATCHLIMIT is returned by the JIT code if searching
+a very large pattern tree goes on for too long, as it is in the same
+circumstance when JIT is not used, but the details of exactly what is counted
+are not the same. The PCRE2_ERROR_DEPTHLIMIT error code is never returned
+when JIT matching is used.
+.
+.
+.\" HTML
+.SH "CONTROLLING THE JIT STACK"
+.rs
+.sp
+When the compiled JIT code runs, it needs a block of memory to use as a stack.
+By default, it uses 32KiB on the machine stack. However, some large or
+complicated patterns need more than this. The error PCRE2_ERROR_JIT_STACKLIMIT
+is given when there is not enough stack. Three functions are provided for
+managing blocks of memory for use as JIT stacks. There is further discussion
+about the use of JIT stacks in the section entitled
+.\" HTML
+.\"
+"JIT stack FAQ"
+.\"
+below.
+.P
+The \fBpcre2_jit_stack_create()\fP function creates a JIT stack. Its arguments
+are a starting size, a maximum size, and a general context (for memory
+allocation functions, or NULL for standard memory allocation). It returns a
+pointer to an opaque structure of type \fBpcre2_jit_stack\fP, or NULL if there
+is an error. The \fBpcre2_jit_stack_free()\fP function is used to free a stack
+that is no longer needed. If its argument is NULL, this function returns
+immediately, without doing anything. (For the technically minded: the address
+space is allocated by mmap or VirtualAlloc.) A maximum stack size of 512KiB to
+1MiB should be more than enough for any pattern.
+.P
+The \fBpcre2_jit_stack_assign()\fP function specifies which stack JIT code
+should use. Its arguments are as follows:
+.sp
+ pcre2_match_context *mcontext
+ pcre2_jit_callback callback
+ void *data
+.sp
+The first argument is a pointer to a match context. When this is subsequently
+passed to a matching function, its information determines which JIT stack is
+used. If this argument is NULL, the function returns immediately, without doing
+anything. There are three cases for the values of the other two options:
+.sp
+ (1) If \fIcallback\fP is NULL and \fIdata\fP is NULL, an internal 32KiB block
+ on the machine stack is used. This is the default when a match
+ context is created.
+.sp
+ (2) If \fIcallback\fP is NULL and \fIdata\fP is not NULL, \fIdata\fP must be
+ a pointer to a valid JIT stack, the result of calling
+ \fBpcre2_jit_stack_create()\fP.
+.sp
+ (3) If \fIcallback\fP is not NULL, it must point to a function that is
+ called with \fIdata\fP as an argument at the start of matching, in
+ order to set up a JIT stack. If the return from the callback
+ function is NULL, the internal 32KiB stack is used; otherwise the
+ return value must be a valid JIT stack, the result of calling
+ \fBpcre2_jit_stack_create()\fP.
+.sp
+A callback function is obeyed whenever JIT code is about to be run; it is not
+obeyed when \fBpcre2_match()\fP is called with options that are incompatible
+for JIT matching. A callback function can therefore be used to determine
+whether a match operation was executed by JIT or by the interpreter.
+.P
+You may safely use the same JIT stack for more than one pattern (either by
+assigning directly or by callback), as long as the patterns are matched
+sequentially in the same thread. Currently, the only way to set up
+non-sequential matches in one thread is to use callouts: if a callout function
+starts another match, that match must use a different JIT stack to the one used
+for currently suspended match(es).
+.P
+In a multithread application, if you do not specify a JIT stack, or if you
+assign or pass back NULL from a callback, that is thread-safe, because each
+thread has its own machine stack. However, if you assign or pass back a
+non-NULL JIT stack, this must be a different stack for each thread so that the
+application is thread-safe.
+.P
+Strictly speaking, even more is allowed. You can assign the same non-NULL stack
+to a match context that is used by any number of patterns, as long as they are
+not used for matching by multiple threads at the same time. For example, you
+could use the same stack in all compiled patterns, with a global mutex in the
+callback to wait until the stack is available for use. However, this is an
+inefficient solution, and not recommended.
+.P
+This is a suggestion for how a multithreaded program that needs to set up
+non-default JIT stacks might operate:
+.sp
+ During thread initialization
+ thread_local_var = pcre2_jit_stack_create(...)
+.sp
+ During thread exit
+ pcre2_jit_stack_free(thread_local_var)
+.sp
+ Use a one-line callback function
+ return thread_local_var
+.sp
+All the functions described in this section do nothing if JIT is not available.
+.
+.
+.\" HTML
+.SH "JIT STACK FAQ"
+.rs
+.sp
+(1) Why do we need JIT stacks?
+.sp
+PCRE2 (and JIT) is a recursive, depth-first engine, so it needs a stack where
+the local data of the current node is pushed before checking its child nodes.
+Allocating real machine stack on some platforms is difficult. For example, the
+stack chain needs to be updated every time if we extend the stack on PowerPC.
+Although it is possible, its updating time overhead decreases performance. So
+we do the recursion in memory.
+.P
+(2) Why don't we simply allocate blocks of memory with \fBmalloc()\fP?
+.sp
+Modern operating systems have a nice feature: they can reserve an address space
+instead of allocating memory. We can safely allocate memory pages inside this
+address space, so the stack could grow without moving memory data (this is
+important because of pointers). Thus we can allocate 1MiB address space, and
+use only a single memory page (usually 4KiB) if that is enough. However, we can
+still grow up to 1MiB anytime if needed.
+.P
+(3) Who "owns" a JIT stack?
+.sp
+The owner of the stack is the user program, not the JIT studied pattern or
+anything else. The user program must ensure that if a stack is being used by
+\fBpcre2_match()\fP, (that is, it is assigned to a match context that is passed
+to the pattern currently running), that stack must not be used by any other
+threads (to avoid overwriting the same memory area). The best practice for
+multithreaded programs is to allocate a stack for each thread, and return this
+stack through the JIT callback function.
+.P
+(4) When should a JIT stack be freed?
+.sp
+You can free a JIT stack at any time, as long as it will not be used by
+\fBpcre2_match()\fP again. When you assign the stack to a match context, only a
+pointer is set. There is no reference counting or any other magic. You can free
+compiled patterns, contexts, and stacks in any order, anytime.
+Just \fIdo not\fP call \fBpcre2_match()\fP with a match context pointing to an
+already freed stack, as that will cause SEGFAULT. (Also, do not free a stack
+currently used by \fBpcre2_match()\fP in another thread). You can also replace
+the stack in a context at any time when it is not in use. You should free the
+previous stack before assigning a replacement.
+.P
+(5) Should I allocate/free a stack every time before/after calling
+\fBpcre2_match()\fP?
+.sp
+No, because this is too costly in terms of resources. However, you could
+implement some clever idea which release the stack if it is not used in let's
+say two minutes. The JIT callback can help to achieve this without keeping a
+list of patterns.
+.P
+(6) OK, the stack is for long term memory allocation. But what happens if a
+pattern causes stack overflow with a stack of 1MiB? Is that 1MiB kept until the
+stack is freed?
+.sp
+Especially on embedded systems, it might be a good idea to release memory
+sometimes without freeing the stack. There is no API for this at the moment.
+Probably a function call which returns with the currently allocated memory for
+any stack and another which allows releasing memory (shrinking the stack) would
+be a good idea if someone needs this.
+.P
+(7) This is too much of a headache. Isn't there any better solution for JIT
+stack handling?
+.sp
+No, thanks to Windows. If POSIX threads were used everywhere, we could throw
+out this complicated API.
+.
+.
+.SH "FREEING JIT SPECULATIVE MEMORY"
+.rs
+.sp
+.nf
+.B void pcre2_jit_free_unused_memory(pcre2_general_context *\fIgcontext\fP);
+.fi
+.P
+The JIT executable allocator does not free all memory when it is possible. It
+expects new allocations, and keeps some free memory around to improve
+allocation speed. However, in low memory conditions, it might be better to free
+all possible memory. You can cause this to happen by calling
+pcre2_jit_free_unused_memory(). Its argument is a general context, for custom
+memory management, or NULL for standard memory management.
+.
+.
+.SH "EXAMPLE CODE"
+.rs
+.sp
+This is a single-threaded example that specifies a JIT stack without using a
+callback. A real program should include error checking after all the function
+calls.
+.sp
+ int rc;
+ pcre2_code *re;
+ pcre2_match_data *match_data;
+ pcre2_match_context *mcontext;
+ pcre2_jit_stack *jit_stack;
+.sp
+ re = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED, 0,
+ &errornumber, &erroffset, NULL);
+ rc = pcre2_jit_compile(re, PCRE2_JIT_COMPLETE);
+ mcontext = pcre2_match_context_create(NULL);
+ jit_stack = pcre2_jit_stack_create(32*1024, 512*1024, NULL);
+ pcre2_jit_stack_assign(mcontext, NULL, jit_stack);
+ match_data = pcre2_match_data_create(re, 10);
+ rc = pcre2_match(re, subject, length, 0, 0, match_data, mcontext);
+ /* Process result */
+.sp
+ pcre2_code_free(re);
+ pcre2_match_data_free(match_data);
+ pcre2_match_context_free(mcontext);
+ pcre2_jit_stack_free(jit_stack);
+.sp
+.
+.
+.\" HTML
+.SH "JIT FAST PATH API"
+.rs
+.sp
+Because the API described above falls back to interpreted matching when JIT is
+not available, it is convenient for programs that are written for general use
+in many environments. However, calling JIT via \fBpcre2_match()\fP does have a
+performance impact. Programs that are written for use where JIT is known to be
+available, and which need the best possible performance, can instead use a
+"fast path" API to call JIT matching directly instead of calling
+\fBpcre2_match()\fP (obviously only for patterns that have been successfully
+processed by \fBpcre2_jit_compile()\fP).
+.P
+The fast path function is called \fBpcre2_jit_match()\fP, and it takes exactly
+the same arguments as \fBpcre2_match()\fP. However, the subject string must be
+specified with a length; PCRE2_ZERO_TERMINATED is not supported. Unsupported
+option bits (for example, PCRE2_ANCHORED, PCRE2_ENDANCHORED, and
+PCRE2_COPY_MATCHED_SUBJECT) are ignored, as is the PCRE2_NO_JIT option. The
+return values are also the same as for \fBpcre2_match()\fP, plus
+PCRE2_ERROR_JIT_BADOPTION if a matching mode (partial or complete) is requested
+that was not compiled.
+.P
+When you call \fBpcre2_match()\fP, as well as testing for invalid options, a
+number of other sanity checks are performed on the arguments. For example, if
+the subject pointer is NULL but the length is non-zero, an immediate error is
+given. Also, unless PCRE2_NO_UTF_CHECK is set, a UTF subject string is tested
+for validity. In the interests of speed, these checks do not happen on the JIT
+fast path. If invalid UTF data is passed when PCRE2_MATCH_INVALID_UTF was not
+set for \fBpcre2_compile()\fP, the result is undefined. The program may crash
+or loop or give wrong results. In the absence of PCRE2_MATCH_INVALID_UTF you
+should call \fBpcre2_jit_match()\fP in UTF mode only if you are sure the
+subject is valid.
+.P
+Bypassing the sanity checks and the \fBpcre2_match()\fP wrapping can give
+speedups of more than 10%.
+.
+.
+.SH "SEE ALSO"
+.rs
+.sp
+\fBpcre2api\fP(3), \fBpcre2unicode\fP(3)
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel (FAQ by Zoltan Herczeg)
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 08 August 2026
+Copyright (c) 1997-2024 University of Cambridge.
+.fi
diff --git a/doc/pcre2limits.3 b/doc/pcre2limits.3
new file mode 100644
index 0000000..03c1ee9
--- /dev/null
+++ b/doc/pcre2limits.3
@@ -0,0 +1,86 @@
+.TH PCRE2LIMITS 3 "03 September 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH "SIZE AND OTHER LIMITATIONS"
+.rs
+.sp
+There are some size limitations in PCRE2 but it is hoped that they will never
+in practice be relevant.
+.P
+The maximum size of a compiled pattern is approximately 64 thousand code units
+for the 8-bit and 16-bit libraries if PCRE2 is compiled with the default
+internal linkage size, which is 2 bytes for these libraries. If you want to
+process regular expressions that are truly enormous, you can compile PCRE2 with
+an internal linkage size of 3 or 4 (when building the 16-bit library, 3 is
+rounded up to 4). See the \fBREADME\fP file in the source distribution and the
+.\" HREF
+\fBpcre2build\fP
+.\"
+documentation for details. In these cases the limit is substantially larger.
+However, the speed of execution is slower. In the 32-bit library, the internal
+linkage size is always 4.
+.P
+The maximum length of a source pattern string is essentially unlimited; it is
+the largest number a PCRE2_SIZE variable can hold. However, the program that
+calls \fBpcre2_compile()\fP can specify a smaller limit.
+.P
+The maximum length (in code units) of a subject string is one less than the
+largest number a PCRE2_SIZE variable can hold. PCRE2_SIZE is an unsigned
+integer type, usually defined as size_t. Its maximum value (that is
+~(PCRE2_SIZE)0) is reserved as a special indicator for zero-terminated strings
+and unset offsets.
+.P
+All values in repeating quantifiers must be less than 65536.
+.P
+There are two different limits that apply to branches of lookbehind assertions.
+If every branch in such an assertion matches a fixed number of characters,
+the maximum length of any branch is 65535 characters. If any branch matches a
+variable number of characters, then the maximum matching length for every
+branch is limited. The default limit is set at compile time, defaulting to 255,
+but can be changed by the calling program.
+.P
+There is no limit to the number of parenthesized groups, but there can be no
+more than 65535 capture groups, and there is a limit to the depth of nesting of
+parenthesized subpatterns of all kinds. This is imposed in order to limit the
+amount of system stack used at compile time. The default limit can be specified
+when PCRE2 is built; if not, the default is set to 250. An application can
+change this limit by calling pcre2_set_parens_nest_limit() to set the limit in
+a compile context.
+.P
+The maximum length of the name for a named capture group as well as the number
+of such groups is configurable at build time. The maximum length for the name
+defaults to
+.\" DEFINE MAX_NAME_SIZE
+128 code units, and the maximum number of such groups to
+.\" DEFINE MAX_NAME_COUNT
+10000.
+.P
+The maximum length of a name in a (*MARK), (*PRUNE), (*SKIP), or (*THEN) verb
+is 255 code units for the 8-bit library and 65535 code units for the 16-bit and
+32-bit libraries.
+.P
+The maximum length of a string argument to a callout is the largest number a
+32-bit unsigned integer can hold.
+.P
+The maximum amount of heap memory used for matching is controlled by the heap
+limit, which can be set in a pattern or in a match context. The default is a
+very large number, effectively unlimited.
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 03 September 2025
+Copyright (c) 1997-2023 University of Cambridge.
+.fi
diff --git a/doc/pcre2matching.3 b/doc/pcre2matching.3
new file mode 100644
index 0000000..7d5b04b
--- /dev/null
+++ b/doc/pcre2matching.3
@@ -0,0 +1,228 @@
+.TH PCRE2MATCHING 3 "22 February 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH "PCRE2 MATCHING ALGORITHMS"
+.rs
+.sp
+This document describes the two different algorithms that are available in
+PCRE2 for matching a compiled regular expression against a given subject
+string. The "standard" algorithm is the one provided by the \fBpcre2_match()\fP
+function. This works in the same way as Perl's matching function, and provides a
+Perl-compatible matching operation. The just-in-time (JIT) optimization that is
+described in the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+documentation is compatible with this function.
+.P
+An alternative algorithm is provided by the \fBpcre2_dfa_match()\fP function;
+it operates in a different way, and is not Perl-compatible. This alternative
+has advantages and disadvantages compared with the standard algorithm, and
+these are described below.
+.P
+When there is only one possible way in which a given subject string can match a
+pattern, the two algorithms give the same answer. A difference arises, however,
+when there are multiple possibilities. For example, if the anchored pattern
+.sp
+ ^<.*>
+.sp
+is matched against the string
+.sp
+
+.sp
+there are three possible answers. The standard algorithm finds only one of
+them, whereas the alternative algorithm finds all three.
+.
+.
+.SH "REGULAR EXPRESSIONS AS TREES"
+.rs
+.sp
+The set of strings that are matched by a regular expression can be represented
+as a tree structure. An unlimited repetition in the pattern makes the tree of
+infinite size, but it is still a tree. Matching the pattern to a given subject
+string (from a given starting point) can be thought of as a search of the tree.
+There are two ways to search a tree: depth-first and breadth-first, and these
+correspond to the two matching algorithms provided by PCRE2.
+.
+.
+.SH "THE STANDARD MATCHING ALGORITHM"
+.rs
+.sp
+In the terminology of Jeffrey Friedl's book "Mastering Regular Expressions",
+the standard algorithm is an "NFA algorithm". It conducts a depth-first search
+of the pattern tree. That is, it proceeds along a single path through the tree,
+checking that the subject matches what is required. When there is a mismatch,
+the algorithm tries any alternatives at the current point, and if they all
+fail, it backs up to the previous branch point in the tree, and tries the next
+alternative branch at that level. This often involves backing up (moving to the
+left) in the subject string as well. The order in which repetition branches are
+tried is controlled by the greedy or ungreedy nature of the quantifier.
+.P
+If a leaf node is reached, a matching string has been found, and at that point
+the algorithm stops. Thus, if there is more than one possible match, this
+algorithm returns the first one that it finds. Whether this is the shortest,
+the longest, or some intermediate length depends on the way the alternations
+and the greedy or ungreedy repetition quantifiers are specified in the
+pattern.
+.P
+Because it ends up with a single path through the tree, it is relatively
+straightforward for this algorithm to keep track of the substrings that are
+matched by portions of the pattern in parentheses. This provides support for
+capturing parentheses and backreferences.
+.
+.
+.SH "THE ALTERNATIVE MATCHING ALGORITHM"
+.rs
+.sp
+This algorithm conducts a breadth-first search of the tree. Starting from the
+first matching point in the subject, it scans the subject string from left to
+right, once, character by character, and as it does this, it remembers all the
+paths through the tree that represent valid matches. In Friedl's terminology,
+this is a kind of "DFA algorithm", though it is not implemented as a
+traditional finite state machine (it keeps multiple states active
+simultaneously).
+.P
+Although the general principle of this matching algorithm is that it scans the
+subject string only once, without backtracking, there is one exception: when a
+lookaround assertion is encountered, the characters following or preceding the
+current point have to be independently inspected.
+.P
+The scan continues until either the end of the subject is reached, or there are
+no more unterminated paths. At this point, terminated paths represent the
+different matching possibilities (if there are none, the match has failed).
+Thus, if there is more than one possible match, this algorithm finds all of
+them, and in particular, it finds the longest. The matches are returned in
+the output vector in decreasing order of length. There is an option to stop the
+algorithm after the first match (which is necessarily the shortest) is found.
+.P
+Note that the size of vector needed to contain all the results depends on the
+number of simultaneous matches, not on the number of capturing parentheses in
+the pattern. Using \fBpcre2_match_data_create_from_pattern()\fP to create the
+match data block is therefore not advisable when doing DFA matching.
+.P
+Note also that all the matches that are found start at the same point in the
+subject. If the pattern
+.sp
+ cat(er(pillar)?)?
+.sp
+is matched against the string "the caterpillar catchment", the result is the
+three strings "caterpillar", "cater", and "cat" that start at the fifth
+character of the subject. The algorithm does not automatically move on to find
+matches that start at later positions.
+.P
+PCRE2's "auto-possessification" optimization usually applies to character
+repeats at the end of a pattern (as well as internally). For example, the
+pattern "a\ed+" is compiled as if it were "a\ed++" because there is no point
+even considering the possibility of backtracking into the repeated digits. For
+DFA matching, this means that only one possible match is found. If you really
+do want multiple matches in such cases, either use an ungreedy repeat
+("a\ed+?") or set the PCRE2_NO_AUTO_POSSESS option when compiling.
+.P
+There are a number of features of PCRE2 regular expressions that are not
+supported or behave differently in the alternative matching function. Those
+that are not supported cause an error if encountered.
+.P
+1. Because the algorithm finds all possible matches, the greedy or ungreedy
+nature of repetition quantifiers is not relevant (though it may affect
+auto-possessification, as just described). During matching, greedy and ungreedy
+quantifiers are treated in exactly the same way. However, possessive
+quantifiers can make a difference when what follows could also match what is
+quantified, for example in a pattern like this:
+.sp
+ ^a++\ew!
+.sp
+This pattern matches "aaab!" but not "aaa!", which would be matched by a
+non-possessive quantifier. Similarly, if an atomic group is present, it is
+matched as if it were a standalone pattern at the current point, and the
+longest match is then "locked in" for the rest of the overall pattern.
+.P
+2. When dealing with multiple paths through the tree simultaneously, it is not
+straightforward to keep track of captured substrings for the different matching
+possibilities, and PCRE2's implementation of this algorithm does not attempt to
+do this. This means that no captured substrings are available.
+.P
+3. Because no substrings are captured, a number of related features are not
+available:
+.sp
+(a) Backreferences;
+.sp
+(b) Conditional expressions that use a backreference as the condition or test
+for a specific group recursion;
+.sp
+(c) Script runs;
+.sp
+(d) Scan substring assertions.
+.P
+4. Because many paths through the tree may be active, the \eK escape sequence,
+which resets the start of the match when encountered (but may be on some paths
+and not on others), is not supported.
+.P
+5. Callouts are supported, but the value of the \fIcapture_top\fP field is
+always 1, and the value of the \fIcapture_last\fP field is always 0.
+.P
+6. The \eC escape sequence, which (in the standard algorithm) always matches a
+single code unit, even in a UTF mode, is not supported in UTF modes because
+the alternative algorithm moves through the subject string one character (not
+code unit) at a time, for all active paths through the tree.
+.P
+7. Except for (*FAIL), the backtracking control verbs such as (*PRUNE) are not
+supported. (*FAIL) is supported, and behaves like a failing negative assertion.
+.P
+8. The PCRE2_MATCH_INVALID_UTF option for \fBpcre2_compile()\fP is not
+supported by \fBpcre2_dfa_match()\fP.
+.
+.
+.SH "ADVANTAGES OF THE ALTERNATIVE ALGORITHM"
+.rs
+.sp
+The main advantage of the alternative algorithm is that all possible matches
+(at a single point in the subject) are automatically found, and in particular,
+the longest match is found. To find more than one match at the same point using
+the standard algorithm, you have to do kludgy things with callouts.
+.P
+Partial matching is possible with this algorithm, though it has some
+limitations. The
+.\" HREF
+\fBpcre2partial\fP
+.\"
+documentation gives details of partial matching and discusses multi-segment
+matching.
+.
+.
+.SH "DISADVANTAGES OF THE ALTERNATIVE ALGORITHM"
+.rs
+.sp
+The alternative algorithm suffers from a number of disadvantages:
+.P
+1. It is substantially slower than the standard algorithm. This is partly
+because it has to search for all possible matches, but is also because it is
+less susceptible to optimization.
+.P
+2. Capturing parentheses and other features such as backreferences that rely on
+them are not supported.
+.P
+3. Matching within invalid UTF strings is not supported.
+.P
+4. Although atomic groups are supported, their use does not provide the
+performance advantage that it does for the standard algorithm.
+.P
+5. JIT optimization is not supported.
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 22 February 2025
+Copyright (c) 1997-2024 University of Cambridge.
+.fi
diff --git a/doc/pcre2partial.3 b/doc/pcre2partial.3
new file mode 100644
index 0000000..2b7ad09
--- /dev/null
+++ b/doc/pcre2partial.3
@@ -0,0 +1,386 @@
+.TH PCRE2PARTIAL 3 "16 August 2026" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH "PARTIAL MATCHING IN PCRE2"
+.rs
+.sp
+In normal use of PCRE2, if there is a match up to the end of a subject string,
+but more characters are needed to match the entire pattern, PCRE2_ERROR_NOMATCH
+is returned, just like any other failing match. There are circumstances where
+it might be helpful to distinguish this "partial match" case.
+.P
+One example is an application where the subject string is very long, and not
+all available at once. The requirement here is to be able to do the matching
+segment by segment, but special action is needed when a matched substring spans
+the boundary between two segments.
+.P
+Another example is checking a user input string as it is typed, to ensure that
+it conforms to a required format. Invalid characters can be immediately
+diagnosed and rejected, giving instant feedback.
+.P
+Partial matching is a PCRE2-specific feature; it is not Perl-compatible. It is
+requested by setting one of the PCRE2_PARTIAL_HARD or PCRE2_PARTIAL_SOFT
+options when calling a matching function. The difference between the two
+options is whether or not a partial match is preferred to an alternative
+complete match, though the details differ between the two types of matching
+function. If both options are set, PCRE2_PARTIAL_HARD takes precedence.
+.P
+If you want to use partial matching with just-in-time optimized code, as well
+as setting a partial match option for the matching function, you must also call
+\fBpcre2_jit_compile()\fP with one or both of these options:
+.sp
+ PCRE2_JIT_PARTIAL_HARD
+ PCRE2_JIT_PARTIAL_SOFT
+.sp
+PCRE2_JIT_COMPLETE should also be set if you are going to run non-partial
+matches on the same pattern. Separate code is compiled for each mode. If the
+appropriate JIT mode has not been compiled, interpretive matching code is used.
+.P
+Setting a partial matching option disables two of PCRE2's standard
+optimization hints. PCRE2 remembers the last literal code unit in a pattern,
+and abandons matching immediately if it is not present in the subject string.
+This optimization cannot be used for a subject string that might match only
+partially. PCRE2 also remembers a minimum length of a matching string, and does
+not bother to run the matching function on shorter strings. This optimization
+is also disabled for partial matching.
+.
+.
+.SH "REQUIREMENTS FOR A PARTIAL MATCH"
+.rs
+.sp
+A possible partial match occurs during matching when the end of the subject
+string is reached successfully, but either more characters are needed to
+complete the match, or the addition of more characters might change what is
+matched.
+.P
+Example 1: if the pattern is /abc/ and the subject is "ab", more characters are
+definitely needed to complete a match. In this case both hard and soft matching
+options yield a partial match.
+.P
+Example 2: if the pattern is /ab+/ and the subject is "ab", a complete match
+can be found, but the addition of more characters might change what is
+matched. In this case, only PCRE2_PARTIAL_HARD returns a partial match;
+PCRE2_PARTIAL_SOFT returns the complete match.
+.P
+On reaching the end of the subject, when PCRE2_PARTIAL_HARD is set, if the next
+pattern item is \ez, \eZ, \eb, \eB, or $ there is always a partial match.
+Otherwise, for both options, the next pattern item must be one that inspects a
+character, and at least one of the following must be true:
+.P
+(1) At least one character has already been inspected. An inspected character
+need not form part of the final matched string; lookbehind assertions and the
+\eK escape sequence provide ways of inspecting characters before the start of a
+matched string.
+.P
+(2) The pattern contains one or more lookbehind assertions. This condition
+exists in case there is a lookbehind that inspects characters before the start
+of the match.
+.P
+(3) There is a special case when the whole pattern can match an empty string.
+When the starting point is at the end of the subject, the empty string match is
+a possibility, and if PCRE2_PARTIAL_SOFT is set and neither of the above
+conditions is true, it is returned. However, because adding more characters
+might result in a non-empty match, PCRE2_PARTIAL_HARD returns a partial match,
+which in this case means "there is going to be a match at this point, but until
+some more characters are added, we do not know if it will be an empty string or
+something longer".
+.
+.
+.
+.SH "PARTIAL MATCHING USING pcre2_match()"
+.rs
+.sp
+When a partial matching option is set, the result of calling
+\fBpcre2_match()\fP can be one of the following:
+.TP 2
+\fBA successful match\fP
+A complete match has been found, starting and ending within this subject.
+.TP
+\fBPCRE2_ERROR_NOMATCH\fP
+No match can start anywhere in this subject.
+.TP
+\fBPCRE2_ERROR_PARTIAL\fP
+Adding more characters may result in a complete match that uses one or more
+characters from the end of this subject.
+.P
+When a partial match is returned, the first two elements in the ovector point
+to the portion of the subject that was matched, but the values in the rest of
+the ovector are undefined. The appearance of \eK in the pattern has no effect
+for a partial match. Consider this pattern:
+.sp
+ /abc\eK123/
+.sp
+If it is matched against "456abc123xyz" the result is a complete match, and the
+ovector defines the matched string as "123", because \eK resets the "start of
+match" point. However, if a partial match is requested and the subject string
+is "456abc12", a partial match is found for the string "abc12", because all
+these characters are needed for a subsequent re-match with additional
+characters.
+.P
+If there is more than one partial match, the first one that was found provides
+the data that is returned. Consider this pattern:
+.sp
+ /123\ew+X|dogY/
+.sp
+If this is matched against the subject string "abc123dog", both alternatives
+fail to match, but the end of the subject is reached during matching, so
+PCRE2_ERROR_PARTIAL is returned. The offsets are set to 3 and 9, identifying
+"123dog" as the first partial match. (In this example, there are two partial
+matches, because "dog" on its own partially matches the second alternative.)
+.
+.
+.SS "How a partial match is processed by pcre2_match()"
+.rs
+.sp
+What happens when a partial match is identified depends on which of the two
+partial matching options is set.
+.P
+If PCRE2_PARTIAL_HARD is set, PCRE2_ERROR_PARTIAL is returned as soon as a
+partial match is found, without continuing to search for possible complete
+matches. This option is "hard" because it prefers an earlier partial match over
+a later complete match. For this reason, the assumption is made that the end of
+the supplied subject string is not the true end of the available data, which is
+why \ez, \eZ, \eb, \eB, and $ always give a partial match.
+.P
+If PCRE2_PARTIAL_SOFT is set, the partial match is remembered, but matching
+continues as normal, and other alternatives in the pattern are tried. If no
+complete match can be found, PCRE2_ERROR_PARTIAL is returned instead of
+PCRE2_ERROR_NOMATCH. This option is "soft" because it prefers a complete match
+over a partial match. All the various matching items in a pattern behave as if
+the subject string is potentially complete; \ez, \eZ, and $ match at the end of
+the subject, as normal, and for \eb and \eB the end of the subject is treated
+as a non-alphanumeric.
+.P
+The difference between the two partial matching options can be illustrated by a
+pattern such as:
+.sp
+ /dog(sbody)?/
+.sp
+This matches either "dog" or "dogsbody", greedily (that is, it prefers the
+longer string if possible). If it is matched against the string "dog" with
+PCRE2_PARTIAL_SOFT, it yields a complete match for "dog". However, if
+PCRE2_PARTIAL_HARD is set, the result is PCRE2_ERROR_PARTIAL. On the other
+hand, if the pattern is made ungreedy the result is different:
+.sp
+ /dog(sbody)??/
+.sp
+In this case the result is always a complete match because that is found first,
+and matching never continues after finding a complete match. It might be easier
+to follow this explanation by thinking of the two patterns like this:
+.sp
+ /dog(sbody)?/ is the same as /dogsbody|dog/
+ /dog(sbody)??/ is the same as /dog|dogsbody/
+.sp
+The second pattern will never match "dogsbody", because it will always find the
+shorter match first.
+.
+.
+.SS "Example of partial matching using pcre2test"
+.rs
+.sp
+The \fBpcre2test\fP data modifiers \fBpartial_hard\fP (or \fBph\fP) and
+\fBpartial_soft\fP (or \fBps\fP) set PCRE2_PARTIAL_HARD and PCRE2_PARTIAL_SOFT,
+respectively, when calling \fBpcre2_match()\fP. Here is a run of
+\fBpcre2test\fP using a pattern that matches the whole subject in the form of a
+date:
+.sp
+ re> /^\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed$/
+ data> 25dec3\e=ph
+ Partial match: 23dec3
+ data> 3ju\e=ph
+ Partial match: 3ju
+ data> 3juj\e=ph
+ No match
+.sp
+This example gives the same results for both hard and soft partial matching
+options. Here is an example where there is a difference:
+.sp
+ re> /^\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed$/
+ data> 25jun04\e=ps
+ 0: 25jun04
+ 1: jun
+ data> 25jun04\e=ph
+ Partial match: 25jun04
+.sp
+With PCRE2_PARTIAL_SOFT, the subject is matched completely. For
+PCRE2_PARTIAL_HARD, however, the subject is assumed not to be complete, so
+there is only a partial match.
+.
+.
+.
+.SH "MULTI-SEGMENT MATCHING WITH pcre2_match()"
+.rs
+.sp
+PCRE was not originally designed with multi-segment matching in mind. However,
+over time, features (including partial matching) that make multi-segment
+matching possible have been added. A very long string can be searched segment
+by segment by calling \fBpcre2_match()\fP repeatedly, with the aim of achieving
+the same results that would happen if the entire string was available for
+searching all the time. Normally, the strings that are being sought are much
+shorter than each individual segment, and are in the middle of very long
+strings, so the pattern is normally not anchored.
+.P
+Special logic must be implemented to handle a matched substring that spans a
+segment boundary. PCRE2_PARTIAL_HARD should be used, because it returns a
+partial match at the end of a segment whenever there is the possibility of
+changing the match by adding more characters. The PCRE2_NOTBOL option should
+also be set for all but the first segment.
+.P
+When a partial match occurs, the next segment must be added to the current
+subject and the match re-run, using the \fIstartoffset\fP argument of
+\fBpcre2_match()\fP to begin at the point where the partial match started.
+For example:
+.sp
+ re> /\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed/
+ data> ...the date is 23ja\e=ph
+ Partial match: 23ja
+ data> ...the date is 23jan19 and on that day...\e=offset=15
+ 0: 23jan19
+ 1: jan
+.sp
+Note the use of the \fBoffset\fP modifier to start the new match where the
+partial match was found. In this example, the next segment was added to the one
+in which the partial match was found. This is the most straightforward
+approach, typically using a memory buffer that is twice the size of each
+segment. After a partial match, the first half of the buffer is discarded, the
+second half is moved to the start of the buffer, and a new segment is added
+before repeating the match as in the example above. After a no match, the
+entire buffer can be discarded.
+.P
+If there are memory constraints, you may want to discard text that precedes a
+partial match before adding the next segment. Unfortunately, this is not at
+present straightforward. In cases such as the above, where the pattern does not
+contain any lookbehinds, it is sufficient to retain only the partially matched
+substring. However, if the pattern contains a lookbehind assertion, characters
+that precede the start of the partial match may have been inspected during the
+matching process. When \fBpcre2test\fP displays a partial match, it indicates
+these characters with '<' if the \fBallusedtext\fP modifier is set:
+.sp
+ re> "(?<=123)abc"
+ data> xx123ab\e=ph,allusedtext
+ Partial match: 123ab
+ <<<
+.sp
+However, the \fBallusedtext\fP modifier is not available for JIT matching,
+because JIT matching does not record the first (or last) consulted characters.
+For this reason, this information is not available via the API. It is therefore
+not possible in general to obtain the exact number of characters that must be
+retained in order to get the right match result. If you cannot retain the
+entire segment, you must find some heuristic way of choosing.
+.P
+If you know the approximate length of the matching substrings, you can use that
+to decide how much text to retain. The only lookbehind information that is
+currently available via the API is the length of the longest individual
+lookbehind in a pattern, but this can be misleading if there are nested
+lookbehinds. The value returned by calling \fBpcre2_pattern_info()\fP with the
+PCRE2_INFO_MAXLOOKBEHIND option is the maximum number of characters (not code
+units) that any individual lookbehind moves back when it is processed. A
+pattern such as "(?<=(? /^\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed$/
+ data> 23ja\e=dfa,ps
+ Partial match: 23ja
+ data> n05\e=dfa,dfa_restart
+ 0: n05
+.sp
+The first call has "23ja" as the subject, and requests partial matching; the
+second call has "n05" as the subject for the continued (restarted) match.
+Notice that when the match is complete, only the last part is shown; PCRE2 does
+not retain the previously partially-matched string. It is up to the calling
+program to do that if it needs to. This means that, for an unanchored pattern,
+if a continued match fails, it is not possible to try again at a new starting
+point. All this facility is capable of doing is continuing with the previous
+match attempt. For example, consider this pattern:
+.sp
+ 1234|3789
+.sp
+If the first part of the subject is "ABC123", a partial match of the first
+alternative is found at offset 3. There is no partial match for the second
+alternative, because such a match does not start at the same point in the
+subject string. Attempting to continue with the string "7890" does not yield a
+match because only those alternatives that match at one point in the subject
+are remembered. Depending on the application, this may or may not be what you
+want.
+.P
+If you do want to allow for starting again at the next character, one way of
+doing it is to retain some or all of the segment and try a new complete match,
+as described for \fBpcre2_match()\fP above. Another possibility is to work with
+two buffers. If a partial match at offset \fIn\fP in the first buffer is
+followed by "no match" when PCRE2_DFA_RESTART is used on the second buffer, you
+can then try a new match starting at offset \fIn+1\fP in the first buffer.
+.P
+Therefore, PCRE2_DFA_RESTART does not remove the need to keep earlier subject
+data. In order to perform a bumpalong and continue matching at the next
+character, all subject data from the current match start must be retained,
+together with enough preceding data to satisfy the requirements of lookbehind
+assertions (remembering as above that PCRE2_INFO_MAXLOOKBEHIND only describes
+the buffer requirement of a single lookbehind, and nested lookbehinds can read
+back further from the match start). This makes streaming match processing
+using PCRE2_DFA_RESTART challenging, and the application cannot easily set a
+bound on the number of chunks to buffer. For multi-segment searching that is
+intended to produce the same result as searching the whole subject, it is
+usually simpler to avoid PCRE2_DFA_RESTART and run a fresh match, using either
+matching function, over the retained text.
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 16 August 2026
+Copyright (c) 1997-2019 University of Cambridge.
+.fi
diff --git a/doc/pcre2pattern.3 b/doc/pcre2pattern.3
new file mode 100644
index 0000000..ad946b4
--- /dev/null
+++ b/doc/pcre2pattern.3
@@ -0,0 +1,4235 @@
+.TH PCRE2PATTERN 3 "25 October 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH "PCRE2 REGULAR EXPRESSION DETAILS"
+.rs
+.sp
+The syntax and semantics of the regular expressions that are supported by PCRE2
+are described in detail below. There is a quick-reference syntax summary in the
+.\" HREF
+\fBpcre2syntax\fP
+.\"
+page. PCRE2 tries to match Perl syntax and semantics as closely as it can.
+PCRE2 also supports some alternative regular expression syntax that does not
+conflict with the Perl syntax in order to provide some compatibility with
+regular expressions in Python, .NET, and Oniguruma. There are in addition some
+options that enable alternative syntax and semantics that are not the same as
+in Perl.
+.P
+Perl's regular expressions are described in its own documentation, and regular
+expressions in general are covered in a number of books, some of which have
+copious examples. Jeffrey Friedl's "Mastering Regular Expressions", published
+by O'Reilly, covers regular expressions in great detail. This description of
+PCRE2's regular expressions is intended as reference material.
+.P
+This document discusses the regular expression patterns that are supported by
+PCRE2 when its main matching function, \fBpcre2_match()\fP, is used. PCRE2 also
+has an alternative matching function, \fBpcre2_dfa_match()\fP, which matches
+using a different algorithm that is not Perl-compatible. Some of the features
+discussed below are not available when DFA matching is used. The advantages and
+disadvantages of the alternative function, and how it differs from the normal
+function, are discussed in the
+.\" HREF
+\fBpcre2matching\fP
+.\"
+page.
+.
+.
+.SH "EBCDIC CHARACTER CODES"
+.rs
+.sp
+Most computers use ASCII or Unicode for encoding characters, and PCRE2 assumes
+this by default. However, it can be compiled to run in an environment that uses
+the EBCDIC code, which is the case for some IBM mainframe operating systems. In
+the sections below, character code values are ASCII or Unicode; in an EBCDIC
+environment these characters may have different code values, and there are no
+code points greater than 255. Differences in behaviour when PCRE2 is running in
+an EBCDIC environment are described in the section
+.\" HTML
+.\"
+"EBCDIC environments"
+.\"
+below, which you can ignore unless you really are in an EBCDIC environment.
+.
+.
+.SH "SPECIAL START-OF-PATTERN ITEMS"
+.rs
+.sp
+A number of options that can be passed to \fBpcre2_compile()\fP can also be set
+by special items at the start of a pattern. These are not Perl-compatible, but
+are provided to make these options accessible to pattern writers who are not
+able to change the program that processes the pattern. Any number of these
+items may appear, but they must all be together right at the start of the
+pattern string, and the letters must be in upper case.
+.
+.
+.SS "UTF support"
+.rs
+.sp
+In the 8-bit and 16-bit PCRE2 libraries, characters may be coded either as
+single code units, or as multiple UTF-8 or UTF-16 code units. UTF-32 can be
+specified for the 32-bit library, in which case it constrains the character
+values to valid Unicode code points. To process UTF strings, PCRE2 must be
+built to include Unicode support (which is the default). When using UTF strings
+you must either call the compiling function with one or both of the PCRE2_UTF
+or PCRE2_MATCH_INVALID_UTF options, or the pattern must start with the special
+sequence (*UTF), which is equivalent to setting the relevant PCRE2_UTF. How
+setting a UTF mode affects pattern matching is mentioned in several places
+below. There is also a summary of features in the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+page.
+.P
+Some applications that allow their users to supply patterns may wish to
+restrict them to non-UTF data for security reasons. If the PCRE2_NEVER_UTF
+option is passed to \fBpcre2_compile()\fP, (*UTF) is not allowed, and its
+appearance in a pattern causes an error.
+.
+.
+.SS "Unicode property support"
+.rs
+.sp
+Another special sequence that may appear at the start of a pattern is (*UCP).
+This has the same effect as setting the PCRE2_UCP option: it causes sequences
+such as \ed and \ew to use Unicode properties to determine character types,
+instead of recognizing only characters with codes less than 256 via a lookup
+table. If also causes upper/lower casing operations to use Unicode properties
+for characters with code points greater than 127, even when UTF is not set.
+These behaviours can be changed within the pattern; see the section entitled
+.\" HTML
+.\"
+"Internal Option Setting"
+.\"
+below.
+.P
+Some applications that allow their users to supply patterns may wish to
+restrict them for security reasons. If the PCRE2_NEVER_UCP option is passed to
+\fBpcre2_compile()\fP, (*UCP) is not allowed, and its appearance in a pattern
+causes an error.
+.
+.
+.SS "Locking out empty string matching"
+.rs
+.sp
+Starting a pattern with (*NOTEMPTY) or (*NOTEMPTY_ATSTART) has the same effect
+as passing the PCRE2_NOTEMPTY or PCRE2_NOTEMPTY_ATSTART option to whichever
+matching function is subsequently called to match the pattern. These options
+lock out the matching of empty strings, either entirely, or only at the start
+of the subject.
+.
+.
+.SS "Disabling auto-possessification"
+.rs
+.sp
+If a pattern starts with (*NO_AUTO_POSSESS), it has the same effect as setting
+the PCRE2_NO_AUTO_POSSESS option, or calling \fBpcre2_set_optimize()\fP with
+a PCRE2_AUTO_POSSESS_OFF directive. This stops PCRE2 from making quantifiers
+possessive when what follows cannot match the repeated item. For example, by
+default a+b is treated as a++b. For more details, see the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation.
+.
+.
+.SS "Disabling start-up optimizations"
+.rs
+.sp
+If a pattern starts with (*NO_START_OPT), it has the same effect as setting the
+PCRE2_NO_START_OPTIMIZE option, or calling \fBpcre2_set_optimize()\fP with
+a PCRE2_START_OPTIMIZE_OFF directive. This disables several optimizations for
+quickly reaching "no match" results. For more details, see the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation.
+.
+.
+.SS "Disabling automatic anchoring"
+.rs
+.sp
+If a pattern starts with (*NO_DOTSTAR_ANCHOR), it has the same effect as
+setting the PCRE2_NO_DOTSTAR_ANCHOR option, or
+calling \fBpcre2_set_optimize()\fP with a PCRE2_DOTSTAR_ANCHOR_OFF directive.
+This disables optimizations that apply to patterns whose top-level branches
+all start with .* (match any number of arbitrary characters). For more details,
+see the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation.
+.
+.
+.SS "Disabling JIT compilation"
+.rs
+.sp
+If a pattern that starts with (*NO_JIT) is successfully compiled, an attempt by
+the application to apply the JIT optimization by calling
+\fBpcre2_jit_compile()\fP is ignored.
+.
+.
+.SS "Setting match resource limits"
+.rs
+.sp
+The \fBpcre2_match()\fP function contains a counter that is incremented every
+time it goes round its main loop. The caller of \fBpcre2_match()\fP can set a
+limit on this counter, which therefore limits the amount of computing resource
+used for a match. The maximum depth of nested backtracking can also be limited;
+this indirectly restricts the amount of heap memory that is used, but there is
+also an explicit memory limit that can be set.
+.P
+These facilities are provided to catch runaway matches that are provoked by
+patterns with huge matching trees. A common example is a pattern with nested
+unlimited repeats applied to a long string that does not match. When one of
+these limits is reached, \fBpcre2_match()\fP gives an error return. The limits
+can also be set by items at the start of the pattern of the form
+.sp
+ (*LIMIT_HEAP=d)
+ (*LIMIT_MATCH=d)
+ (*LIMIT_DEPTH=d)
+.sp
+where d is any number of decimal digits. However, the value of the setting must
+be less than the value set (or defaulted) by the caller of \fBpcre2_match()\fP
+for it to have any effect. In other words, the pattern writer can lower the
+limits set by the programmer, but not raise them. If there is more than one
+setting of one of these limits, the lower value is used. The heap limit is
+specified in kibibytes (units of 1024 bytes).
+.P
+Prior to release 10.30, LIMIT_DEPTH was called LIMIT_RECURSION. This name is
+still recognized for backwards compatibility.
+.P
+The heap limit applies only when the \fBpcre2_match()\fP or
+\fBpcre2_dfa_match()\fP interpreters are used for matching. It does not apply
+to JIT. The match limit is used (but in a different way) when JIT is being
+used, or when \fBpcre2_dfa_match()\fP is called, to limit computing resource
+usage by those matching functions. The depth limit is ignored by JIT but is
+relevant for DFA matching, which uses function recursion for recursions within
+the pattern and for lookaround assertions and atomic groups. In this case, the
+depth limit controls the depth of such recursion.
+.
+.
+.\" HTML
+.SS "Newline conventions"
+.rs
+.sp
+PCRE2 supports six different conventions for indicating line breaks in
+strings: a single CR (carriage return) character, a single LF (linefeed)
+character, the two-character sequence CRLF, any of the three preceding, any
+Unicode newline sequence, or the NUL character (binary zero). The
+.\" HREF
+\fBpcre2api\fP
+.\"
+page has
+.\" HTML
+.\"
+further discussion
+.\"
+about newlines, and shows how to set the newline convention when calling
+\fBpcre2_compile()\fP.
+.P
+It is also possible to specify a newline convention by starting a pattern
+string with one of the following sequences:
+.sp
+ (*CR) carriage return
+ (*LF) linefeed
+ (*CRLF) carriage return, followed by linefeed
+ (*ANYCRLF) any of the three above
+ (*ANY) all Unicode newline sequences
+ (*NUL) the NUL character (binary zero)
+.sp
+These override the default and the options given to the compiling function. For
+example, on a Unix system where LF is the default newline sequence, the pattern
+.sp
+ (*CR)a.b
+.sp
+changes the convention to CR. That pattern matches "a\enb" because LF is no
+longer a newline. If more than one of these settings is present, the last one
+is used.
+.P
+The newline convention affects where the circumflex and dollar assertions are
+true. It also affects the interpretation of the dot metacharacter when
+PCRE2_DOTALL is not set, and the behaviour of \eN when not followed by an
+opening brace. However, it does not affect what the \eR escape sequence
+matches. By default, this is any Unicode newline sequence, for Perl
+compatibility. However, this can be changed; see the next section and the
+description of \eR in the section entitled
+.\" HTML
+.\"
+"Newline sequences"
+.\"
+below. A change of \eR setting can be combined with a change of newline
+convention.
+.
+.
+.SS "Specifying what \eR matches"
+.rs
+.sp
+It is possible to restrict \eR to match only CR, LF, or CRLF (instead of the
+complete set of Unicode line endings) by setting the option PCRE2_BSR_ANYCRLF
+at compile time. This effect can also be achieved by starting a pattern with
+(*BSR_ANYCRLF). For completeness, (*BSR_UNICODE) is also recognized,
+corresponding to PCRE2_BSR_UNICODE.
+.
+.
+.SH "CHARACTERS AND METACHARACTERS"
+.rs
+.sp
+A regular expression is a pattern that is matched against a subject string from
+left to right. Most characters stand for themselves in a pattern, and match the
+corresponding characters in the subject. As a trivial example, the pattern
+.sp
+ The quick brown fox
+.sp
+matches a portion of a subject string that is identical to itself. When
+caseless matching is specified (the PCRE2_CASELESS option or (?i) within the
+pattern), letters are matched independently of case. Note that there are two
+ASCII characters, K and S, that, in addition to their lower case ASCII
+equivalents, are case-equivalent with Unicode U+212A (Kelvin sign) and U+017F
+(long S) respectively when either PCRE2_UTF or PCRE2_UCP is set, unless the
+PCRE2_EXTRA_CASELESS_RESTRICT option is in force (either passed to
+\fBpcre2_compile()\fP or set by (*CASELESS_RESTRICT) or (?r) within the
+pattern). If the PCRE2_EXTRA_TURKISH_CASING option is in force (either passed
+to \fBpcre2_compile()\fP or set by (*TURKISH_CASING) within the pattern), then
+the 'i' letters are matched according to Turkish and Azeri languages.
+.P
+The power of regular expressions comes from the ability to include wild cards,
+character classes, alternatives, and repetitions in the pattern. These are
+encoded in the pattern by the use of \fImetacharacters\fP, which do not stand
+for themselves but instead are interpreted in some special way.
+.P
+There are two different sets of metacharacters: those that are recognized
+anywhere in the pattern except within square brackets, and those that are
+recognized within square brackets. Outside square brackets, the metacharacters
+are as follows:
+.sp
+ \e general escape character with several uses
+ ^ assert start of string (or line, in multiline mode)
+ $ assert end of string (or line, in multiline mode)
+ . match any character except newline (by default)
+ [ start character class definition
+ | start of alternative branch
+ ( start group or control verb
+ ) end group or control verb
+ * 0 or more quantifier
+ + 1 or more quantifier; also "possessive quantifier"
+ ? 0 or 1 quantifier; also quantifier minimizer
+ { potential start of min/max quantifier
+.sp
+Brace characters { and } are also used to enclose data for constructions such
+as \eg{2} or \ek{name}. In almost all uses of braces, space and/or horizontal
+tab characters that follow { or precede } are allowed and are ignored. In the
+case of quantifiers, they may also appear before or after the comma. The
+exception to this is \eu{...} which is an ECMAScript compatibility feature
+that is recognized only when the PCRE2_EXTRA_ALT_BSUX option is set. ECMAScript
+does not ignore such white space; it causes the item to be interpreted as
+literal.
+.P
+Part of a pattern that is in square brackets is called a "character class". In
+a character class the only metacharacters are:
+.sp
+ \e general escape character
+ ^ negate the class, but only if the first character
+ - indicates character range
+ [ POSIX character class (if followed by POSIX syntax)
+ ] terminates the character class
+.sp
+If a pattern is compiled with the PCRE2_EXTENDED option, most white space in
+the pattern, other than in a character class, within a \eQ...\eE sequence, or
+between a # outside a character class and the next newline, inclusive, is
+ignored. An escaping backslash can be used to include a white space or a #
+character as part of the pattern. If the PCRE2_EXTENDED_MORE option is set, the
+same applies, but in addition unescaped space and horizontal tab characters are
+ignored inside a character class. Note: only these two characters are ignored,
+not the full set of pattern white space characters that are ignored outside a
+character class. Option settings can be changed within a pattern; see the
+section entitled
+.\" HTML
+.\"
+"Internal Option Setting"
+.\"
+below.
+.P
+The following sections describe the use of each of the metacharacters.
+.
+.
+.SH BACKSLASH
+.rs
+.sp
+The backslash character has several uses. Firstly, if it is followed by a
+character that is not a digit or a letter, it takes away any special meaning
+that character may have. This use of backslash as an escape character applies
+both inside and outside character classes.
+.P
+For example, if you want to match a * character, you must write \e* in the
+pattern. This escaping action applies whether or not the following character
+would otherwise be interpreted as a metacharacter, so it is always safe to
+precede a non-alphanumeric with backslash to specify that it stands for itself.
+In particular, if you want to match a backslash, you write \e\e.
+.P
+Only ASCII digits and letters have any special meaning after a backslash. All
+other characters (in particular, those whose code points are greater than 127)
+are treated as literals.
+.P
+If you want to treat all characters in a sequence as literals, you can do so by
+putting them between \eQ and \eE. Note that this includes white space even when
+the PCRE2_EXTENDED option is set so that most other white space is ignored. The
+behaviour is different from Perl in that $ and @ are handled as literals in
+\eQ...\eE sequences in PCRE2, whereas in Perl, $ and @ cause variable
+interpolation. Also, Perl does "double-quotish backslash interpolation" on any
+backslashes between \eQ and \eE which, its documentation says, "may lead to
+confusing results". PCRE2 treats a backslash between \eQ and \eE just like any
+other character. Note the following examples:
+.sp
+ Pattern PCRE2 matches Perl matches
+.sp
+.\" JOIN
+ \eQabc$xyz\eE abc$xyz abc followed by the
+ contents of $xyz
+ \eQabc\e$xyz\eE abc\e$xyz abc\e$xyz
+ \eQabc\eE\e$\eQxyz\eE abc$xyz abc$xyz
+ \eQA\eB\eE A\eB A\eB
+ \eQ\e\eE \e \e\eE
+.sp
+The \eQ...\eE sequence is recognized both inside and outside character classes.
+An isolated \eE that is not preceded by \eQ is ignored. If \eQ is not followed
+by \eE later in the pattern, the literal interpretation continues to the end of
+the pattern (that is, \eE is assumed at the end). If the isolated \eQ is inside
+a character class, this causes an error, because the character class is then
+not terminated by a closing square bracket.
+.P
+Another difference from Perl is that any appearance of \eQ or \eE inside what
+might otherwise be a quantifier causes PCRE2 not to recognize the sequence as a
+quantifier. Perl recognizes a quantifier if (redundantly) either of the numbers
+is inside \eQ...\eE, but not if the separating comma is. When not recognized as
+a quantifier a sequence such as {\eQ1\eE,2} is treated as the literal string
+"{1,2}".
+.
+.
+.\" HTML
+.SS "Non-printing characters"
+.rs
+.sp
+A second use of backslash provides a way of encoding non-printing characters
+in patterns in a visible manner. There is no restriction on the appearance of
+non-printing characters in a pattern, but when a pattern is being prepared by
+text editing, it is often easier to use one of the following escape sequences
+instead of the binary character it represents. In an ASCII or Unicode
+environment, these escapes are as follows:
+.sp
+ \ea alarm, that is, the BEL character (hex 07)
+ \ecx "control-x", where x is a non-control ASCII character
+ \ee escape (hex 1B)
+ \ef form feed (hex 0C)
+ \en linefeed (hex 0A)
+ \er carriage return (hex 0D) (but see below)
+ \et tab (hex 09)
+ \e0dd character with octal code 0dd
+ \eddd character with octal code ddd, or back reference
+ \eo{ddd..} character with octal code ddd..
+ \exhh character with hex code hh
+ \ex{hhh..} character with hex code hhh..
+ \eN{U+hhh..} character with Unicode hex code point hhh..
+.sp
+A description of how back references work is given
+.\" HTML
+.\"
+later,
+.\"
+following the discussion of
+.\" HTML
+.\"
+parenthesized groups.
+.\"
+.P
+By default, after \ex that is not followed by {, one or two hexadecimal
+digits are read (letters can be in upper or lower case). If the character that
+follows \ex is neither { nor a hexadecimal digit, an error occurs. This is
+different from Perl's default behaviour, which generates a NUL character, but
+is in line with the behaviour of Perl's 'strict' mode in re.
+.P
+Any number of hexadecimal digits may appear between \ex{ and }. If a character
+other than a hexadecimal digit appears between \ex{ and }, or if there is no
+terminating }, an error occurs.
+.P
+Characters whose code points are less than 256 can be defined by either of the
+two syntaxes for \ex or by an octal sequence. There is no difference in the way
+they are handled. For example, \exdc is exactly the same as \ex{dc} or \e334.
+However, using the braced versions does make such sequences easier to read.
+.P
+Support is available for some ECMAScript (aka JavaScript) escape sequences via
+two compile-time options. If PCRE2_ALT_BSUX is set, the sequence \ex followed
+by { is not recognized. Only if \ex is followed by two hexadecimal digits is it
+recognized as a character escape. Otherwise it is interpreted as a literal "x"
+character. In this mode, support for code points greater than 256 is provided
+by \eu, which must be followed by four hexadecimal digits; otherwise it is
+interpreted as a literal "u" character.
+.P
+PCRE2_EXTRA_ALT_BSUX has the same effect as PCRE2_ALT_BSUX and, in addition,
+\eu{hhh..} is recognized as the character specified by hexadecimal code point.
+There may be any number of hexadecimal digits, but unlike other places that
+also use curly brackets, spaces are not allowed and would result in the string
+being interpreted as a literal. This syntax is from ECMAScript 6.
+.P
+The \eN{U+hhh..} escape sequence is recognized only when PCRE2 is operating in
+UTF mode. Perl also uses \eN{name} to specify characters by Unicode name; PCRE2
+does not support this. Note that when \eN is not followed by an opening brace
+(curly bracket) it has an entirely different meaning, matching any character
+that is not a newline.
+.P
+There are some legacy applications where the escape sequence \er is expected to
+match a newline. If the PCRE2_EXTRA_ESCAPED_CR_IS_LF option is set, \er in a
+pattern is converted to \en so that it matches a LF (linefeed) instead of a CR
+(carriage return) character.
+.P
+An error occurs if \ec is not followed by a character whose ASCII code point
+is in the range 32 to 126. The precise effect of \ecx is as follows: if x is a
+lower case letter, it is converted to upper case. Then bit 6 of the character
+(hex 40) is inverted. Thus \ecA to \ecZ become hex 01 to hex 1A (A is 41, Z is
+5A), but \ec{ becomes hex 3B ({ is 7B), and \ec; becomes hex 7B (; is 3B). If
+the code unit following \ec has a code point less than 32 or greater than 126,
+a compile-time error occurs.
+.P
+For differences in the way some escapes behave in EBCDIC environments,
+see section
+.\" HTML
+.\"
+"EBCDIC environments"
+.\"
+below.
+.
+.
+.SS "Octal escapes and back references"
+.rs
+.sp
+The escape \eo must be followed by a sequence of octal digits, enclosed in
+braces. An error occurs if this is not the case. This escape provides a way of
+specifying character code points as octal numbers greater than 0777, and it
+also allows octal numbers and backreferences to be unambiguously distinguished.
+.P
+If braces are not used, after \e0 up to two further octal digits are read.
+However, if the PCRE2_EXTRA_NO_BS0 option is set, at least one more octal digit
+must follow \e0 (use \e00 to generate a NUL character). Make sure you supply
+two digits after the initial zero if the pattern character that follows is
+itself an octal digit.
+.P
+Inside a character class, when a backslash is followed by any octal digit, up
+to three octal digits are read to generate a code point. Any subsequent digits
+stand for themselves. The sequences \e8 and \e9 are treated as the literal
+characters "8" and "9".
+.P
+Outside a character class, Perl's handling of a backslash followed by a digit
+other than 0 is complicated by ambiguity, and Perl has changed over time,
+causing PCRE2 also to change. From PCRE2 release 10.45 there is an option
+called PCRE2_EXTRA_PYTHON_OCTAL that causes PCRE2 to use Python's unambiguous
+rules. The next two subsections describe the two sets of rules.
+.P
+For greater clarity and unambiguity, it is best to avoid following \e by a
+digit greater than zero. Instead, use \eo{...} or \ex{...} to specify numerical
+character code points, and \eg{...} to specify backreferences.
+.
+.
+.SS "Perl rules for non-class backslash 1-9"
+.rs
+.sp
+All the digits that follow the backslash are read as a decimal number. If the
+number is less than 10, begins with the digit 8 or 9, or if there are at least
+that many previous capture groups in the expression, the entire sequence is
+taken as a back reference. Otherwise, up to three octal digits are read to form
+a character code. For example:
+.sp
+ \e040 is another way of writing an ASCII space
+.\" JOIN
+ \e40 is the same, provided there are fewer than 40
+ previous capture groups
+ \e7 is always a backreference
+.\" JOIN
+ \e11 might be a backreference, or another way of
+ writing a tab
+ \e011 is always a tab
+ \e0113 is a tab followed by the character "3"
+.\" JOIN
+ \e113 might be a backreference, otherwise the
+ character with octal code 113
+.\" JOIN
+ \e377 might be a backreference, otherwise
+ the value 255 (decimal)
+ \e81 is always a backreference
+.sp
+Note that octal values of 100 or greater that are specified using this syntax
+must not be introduced by a leading zero, because no more than three octal
+digits are ever read.
+.
+.
+.SS "Python rules for non_class backslash 1-9"
+.rs
+.sp
+If there are at least three octal digits after the backslash, exactly three are
+read as an octal code point number, but the value must be no greater than
+\e377, even in modes where higher code point values are supported. Any
+subsequent digits stand for themselves. If there are fewer than three octal
+digits, the sequence is taken as a decimal back reference. Thus, for example,
+\e12 is always a back reference, independent of how many captures there are in
+the pattern. An error is generated for a reference to a non-existent capturing
+group.
+.
+.
+.SS "Constraints on character values"
+.rs
+.sp
+Characters that are specified using octal or hexadecimal numbers are
+limited to certain values, as follows:
+.sp
+ 8-bit non-UTF mode no greater than 0xff
+ 16-bit non-UTF mode no greater than 0xffff
+ 32-bit non-UTF mode no greater than 0xffffffff
+ All UTF modes no greater than 0x10ffff and a valid code point
+.sp
+Invalid Unicode code points are all those in the range 0xd800 to 0xdfff (the
+so-called "surrogate" code points). The check for these can be disabled by the
+caller of \fBpcre2_compile()\fP by setting the option
+PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES. However, this is possible only in UTF-8
+and UTF-32 modes, because these values are not representable in UTF-16.
+.
+.
+.SS "Escape sequences in character classes"
+.rs
+.sp
+All the sequences that define a single character value can be used both inside
+and outside character classes. In addition, inside a character class, \eb is
+interpreted as the backspace character (hex 08).
+.P
+When not followed by an opening brace, \eN is not allowed in a character class.
+\eB, \eR, and \eX are not special inside a character class. Like other
+unrecognized alphabetic escape sequences, they cause an error. Outside a
+character class, these sequences have different meanings.
+.
+.
+.SS "Unsupported escape sequences"
+.rs
+.sp
+In Perl, the sequences \eF, \el, \eL, \eu, and \eU are recognized by its string
+handler and used to modify the case of following characters. By default, PCRE2
+does not support these escape sequences in patterns. However, if either of the
+PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX options is set, \eU matches a "U"
+character, and \eu can be used to define a character by code point, as
+described above.
+.
+.
+.SS "Absolute and relative backreferences"
+.rs
+.sp
+The sequence \eg followed by a signed or unsigned number, optionally enclosed
+in braces, is an absolute or relative backreference. A named backreference
+can be coded as \eg{name}. Backreferences are discussed
+.\" HTML
+.\"
+later,
+.\"
+following the discussion of
+.\" HTML
+.\"
+parenthesized groups.
+.\"
+.
+.
+.SS "Absolute and relative subroutine calls"
+.rs
+.sp
+For compatibility with Oniguruma, the non-Perl syntax \eg followed by a name or
+a number enclosed either in angle brackets or single quotes, is an alternative
+syntax for referencing a capture group as a subroutine. Details are discussed
+.\" HTML
+.\"
+later.
+.\"
+Note that \eg{...} (Perl syntax) and \eg<...> (Oniguruma syntax) are \fInot\fP
+synonymous. The former is a backreference; the latter is a
+.\" HTML
+.\"
+subroutine
+.\"
+call.
+.
+.
+.\" HTML
+.SS "Generic character types"
+.rs
+.sp
+Another use of backslash is for specifying generic character types:
+.sp
+ \ed any decimal digit
+ \eD any character that is not a decimal digit
+ \eh any horizontal white space character
+ \eH any character that is not a horizontal white space character
+ \eN any character that is not a newline
+ \es any white space character
+ \eS any character that is not a white space character
+ \ev any vertical white space character
+ \eV any character that is not a vertical white space character
+ \ew any "word" character
+ \eW any "non-word" character
+.sp
+The \eN escape sequence has the same meaning as
+.\" HTML
+.\"
+the "." metacharacter
+.\"
+when PCRE2_DOTALL is not set, but setting PCRE2_DOTALL does not change the
+meaning of \eN. Note that when \eN is followed by an opening brace it has a
+different meaning. See the section entitled
+.\" HTML
+.\"
+"Non-printing characters"
+.\"
+above for details. Perl also uses \eN{name} to specify characters by Unicode
+name; PCRE2 does not support this.
+.P
+Each pair of lower and upper case escape sequences partitions the complete set
+of characters into two disjoint sets. Any given character matches one, and only
+one, of each pair. The sequences can appear both inside and outside character
+classes. They each match one character of the appropriate type. If the current
+matching point is at the end of the subject string, all of them fail, because
+there is no character to match.
+.P
+The default \es characters are HT (9), LF (10), VT (11), FF (12), CR (13), and
+space (32), which are defined as white space in the "C" locale. This list may
+vary if locale-specific matching is taking place. For example, in some locales
+the "non-breaking space" character (\exA0) is recognized as white space, and in
+others the VT character is not.
+.P
+A "word" character is an underscore or any character that is a letter or digit.
+By default, the definition of letters and digits is controlled by PCRE2's
+low-valued character tables, and may vary if locale-specific matching is taking
+place (see
+.\" HTML
+.\"
+"Locale support"
+.\"
+in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page). For example, in a French locale such as "fr_FR" in Unix-like systems,
+or "french" in Windows, some character codes greater than 127 are used for
+accented letters, and these are then matched by \ew. The use of locales with
+Unicode is discouraged.
+.P
+By default, characters whose code points are greater than 127 never match \ed,
+\es, or \ew, and always match \eD, \eS, and \eW, although this may be different
+for characters in the range 128-255 when locale-specific matching is happening.
+These escape sequences retain their original meanings from before Unicode
+support was available, mainly for efficiency reasons. If the PCRE2_UCP option
+is set, the behaviour is changed so that Unicode properties are used to
+determine character types, as follows:
+.sp
+ \ed any character that matches \ep{Nd} (decimal digit)
+ \es any character that matches \ep{Z} or \eh or \ev
+ \ew any character that matches \ep{L}, \ep{N}, \ep{Mn}, or \ep{Pc}
+.sp
+The addition of \ep{Mn} (non-spacing mark) and the replacement of an explicit
+test for underscore with a test for \ep{Pc} (connector punctuation) happened in
+PCRE2 release 10.43. This brings PCRE2 into line with Perl.
+.P
+The upper case escapes match the inverse sets of characters. Note that \ed
+matches only decimal digits, whereas \ew matches any Unicode digit, as well as
+other character categories. Note also that PCRE2_UCP affects \eb, and
+\eB because they are defined in terms of \ew and \eW. Matching these sequences
+is noticeably slower when PCRE2_UCP is set.
+.P
+The effect of PCRE2_UCP on any one of these escape sequences can be negated by
+the options PCRE2_EXTRA_ASCII_BSD, PCRE2_EXTRA_ASCII_BSS, and
+PCRE2_EXTRA_ASCII_BSW, respectively. These options can be set and reset within
+a pattern by means of an internal option setting
+.\" HTML
+.\"
+(see below).
+.\"
+.P
+The sequences \eh, \eH, \ev, and \eV, in contrast to the other sequences, which
+match only ASCII characters by default, always match a specific list of code
+points, whether or not PCRE2_UCP is set. The horizontal space characters are:
+.sp
+ U+0009 Horizontal tab (HT)
+ U+0020 Space
+ U+00A0 Non-break space
+ U+1680 Ogham space mark
+ U+180E Mongolian vowel separator
+ U+2000 En quad
+ U+2001 Em quad
+ U+2002 En space
+ U+2003 Em space
+ U+2004 Three-per-em space
+ U+2005 Four-per-em space
+ U+2006 Six-per-em space
+ U+2007 Figure space
+ U+2008 Punctuation space
+ U+2009 Thin space
+ U+200A Hair space
+ U+202F Narrow no-break space
+ U+205F Medium mathematical space
+ U+3000 Ideographic space
+.sp
+The vertical space characters are:
+.sp
+ U+000A Linefeed (LF)
+ U+000B Vertical tab (VT)
+ U+000C Form feed (FF)
+ U+000D Carriage return (CR)
+ U+0085 Next line (NEL)
+ U+2028 Line separator
+ U+2029 Paragraph separator
+.sp
+In 8-bit, non-UTF-8 mode, only the characters with code points less than 256
+are relevant.
+.
+.
+.\" HTML
+.SS "Newline sequences"
+.rs
+.sp
+Outside a character class, by default, the escape sequence \eR matches any
+Unicode newline sequence. In 8-bit non-UTF-8 mode \eR is equivalent to the
+following:
+.sp
+ (?>\er\en|\en|\ex0b|\ef|\er|\ex85)
+.sp
+This is an example of an "atomic group", details of which are given
+.\" HTML
+.\"
+below.
+.\"
+This particular group matches either the two-character sequence CR followed by
+LF, or one of the single characters LF (linefeed, U+000A), VT (vertical tab,
+U+000B), FF (form feed, U+000C), CR (carriage return, U+000D), or NEL (next
+line, U+0085). Because this is an atomic group, the two-character sequence is
+treated as a single unit that cannot be split.
+.P
+In other modes, two additional characters whose code points are greater than 255
+are added: LS (line separator, U+2028) and PS (paragraph separator, U+2029).
+Unicode support is not needed for these characters to be recognized.
+.P
+It is possible to restrict \eR to match only CR, LF, or CRLF (instead of the
+complete set of Unicode line endings) by setting the option PCRE2_BSR_ANYCRLF
+at compile time. (BSR is an abbreviation for "backslash R".) This can be made
+the default when PCRE2 is built; if this is the case, the other behaviour can
+be requested via the PCRE2_BSR_UNICODE option. It is also possible to specify
+these settings by starting a pattern string with one of the following
+sequences:
+.sp
+ (*BSR_ANYCRLF) CR, LF, or CRLF only
+ (*BSR_UNICODE) any Unicode newline sequence
+.sp
+These override the default and the options given to the compiling function.
+Note that these special settings, which are not Perl-compatible, are recognized
+only at the very start of a pattern, and that they must be in upper case. If
+more than one of them is present, the last one is used. They can be combined
+with a change of newline convention; for example, a pattern can start with:
+.sp
+ (*ANY)(*BSR_ANYCRLF)
+.sp
+They can also be combined with the (*UTF) or (*UCP) special sequences. Inside a
+character class, \eR is treated as an unrecognized escape sequence, and causes
+an error.
+.
+.
+.\" HTML
+.SS Unicode character properties
+.rs
+.sp
+When PCRE2 is built with Unicode support (the default), three additional escape
+sequences that match characters with specific properties are available. They
+can be used in any mode, though in 8-bit and 16-bit non-UTF modes these
+sequences are of course limited to testing characters whose code points are
+less than U+0100 or U+10000, respectively. In 32-bit non-UTF mode, code points
+greater than 0x10ffff (the Unicode limit) may be encountered. These are all
+treated as being in the Unknown script and with an unassigned type.
+.P
+Matching characters by Unicode property is not fast, because PCRE2 has to do a
+multistage table lookup in order to find a character's property. That is why
+the traditional escape sequences such as \ed and \ew do not use Unicode
+properties in PCRE2 by default, though you can make them do so by setting the
+PCRE2_UCP option or by starting the pattern with (*UCP).
+.P
+The extra escape sequences that provide property support are:
+.sp
+ \ep{\fIxx\fP} a character with the \fIxx\fP property
+ \eP{\fIxx\fP} a character without the \fIxx\fP property
+ \eX a Unicode extended grapheme cluster
+.sp
+For compatibility with Perl, negation can be specified by including a
+circumflex between the opening brace and the property. For example, \ep{^Lu} is
+the same as \eP{Lu}.
+.P
+In accordance with Unicode's "loose matching" rules, ASCII white space
+characters, hyphens, and underscores are ignored in the properties represented
+by \fIxx\fP above. As well as the space character, ASCII white space can be
+tab, linefeed, vertical tab, formfeed, or carriage return.
+.P
+Some properties are specified as a name only; others as a name and a value,
+separated by a colon or an equals sign. The names and values consist of ASCII
+letters and digits (with one Perl-specific exception, see below). They are not
+case sensitive. Note, however, that the escapes themselves, \ep and \eP,
+\fIare\fP case sensitive. There are abbreviations for many names. The following
+examples are all equivalent:
+.sp
+ \ep{bidiclass=al}
+ \ep{BC=al}
+ \ep{ Bidi_Class : AL }
+ \ep{ Bi-di class = Al }
+ \eP{ ^ Bi-di class = Al }
+.sp
+There is support for Unicode script names, Unicode general category properties,
+"Any", which matches any character (including newline), Bidi_Class, a number of
+binary (yes/no) properties, and some special PCRE2 properties (described
+.\" HTML
+.\"
+below).
+.\"
+Certain other Perl properties such as "InMusicalSymbols" are not supported by
+PCRE2. Note that \eP{Any} does not match any characters, so always causes a
+match failure.
+.
+.
+.
+.SS "Script properties for \ep and \eP"
+.rs
+.sp
+There are three different syntax forms for matching a script. Each Unicode
+character has a basic script and, optionally, a list of other scripts ("Script
+Extensions") with which it is commonly used. Using the Adlam script as an
+example, \ep{sc:Adlam} matches characters whose basic script is Adlam, whereas
+\ep{scx:Adlam} matches, in addition, characters that have Adlam in their
+extensions list. The full names "script" and "script extensions" for the
+property types are recognized and, as for all property specifications, an
+equals sign is an alternative to the colon. If a script name is given without a
+property type, for example, \ep{Adlam}, it is treated as \ep{scx:Adlam}. Perl
+changed to this interpretation at release 5.26 and PCRE2 changed at release
+10.40.
+.P
+Unassigned characters (and in non-UTF 32-bit mode, characters with code points
+greater than 0x10FFFF) are assigned the "Unknown" script. Others that are not
+part of an identified script are lumped together as "Common". The current list
+of recognized script names and their 4-character abbreviations can be obtained
+by running this command:
+.sp
+ pcre2test -LS
+.sp
+.
+.
+.
+.SS "The general category property for \ep and \eP"
+.rs
+.sp
+Each character has exactly one Unicode general category property, specified by
+a two-letter abbreviation. If only one letter is specified with \ep or \eP, it
+includes all the general category properties that start with that letter. In
+this case, in the absence of negation, the curly brackets in the escape
+sequence are optional; these two examples have the same effect:
+.sp
+ \ep{L}
+ \epL
+.sp
+The following general category property codes are supported:
+.sp
+ C Other
+ Cc Control
+ Cf Format
+ Cn Unassigned
+ Co Private use
+ Cs Surrogate
+.sp
+ L Letter
+ Lc Cased letter
+ Ll Lower case letter
+ Lm Modifier letter
+ Lo Other letter
+ Lt Title case letter
+ Lu Upper case letter
+.sp
+ M Mark
+ Mc Spacing mark
+ Me Enclosing mark
+ Mn Non-spacing mark
+.sp
+ N Number
+ Nd Decimal number
+ Nl Letter number
+ No Other number
+.sp
+ P Punctuation
+ Pc Connector punctuation
+ Pd Dash punctuation
+ Pe Close punctuation
+ Pf Final punctuation
+ Pi Initial punctuation
+ Po Other punctuation
+ Ps Open punctuation
+.sp
+ S Symbol
+ Sc Currency symbol
+ Sk Modifier symbol
+ Sm Mathematical symbol
+ So Other symbol
+.sp
+ Z Separator
+ Zl Line separator
+ Zp Paragraph separator
+ Zs Space separator
+.sp
+Perl originally used the name L& for the Lc property. This is still supported
+by Perl, but discouraged. PCRE2 also still supports it. This property matches
+any character that has the Lu, Ll, or Lt property, in other words, any letter
+that is not classified as a modifier or "other". From release 10.45 of PCRE2
+the properties Lu, Ll, and Lt are all treated as Lc when case-independent
+matching is set by the PCRE2_CASELESS option or (?i) within the pattern. The
+other properties are not affected by caseless matching.
+.P
+The Cs (Surrogate) property applies only to characters whose code points are in
+the range U+D800 to U+DFFF. These characters are no different to any other
+character when PCRE2 is not in UTF mode (using the 16-bit or 32-bit library).
+However, they are not valid in Unicode strings and so cannot be tested by PCRE2
+in UTF mode, unless UTF validity checking has been turned off (see the
+discussion of PCRE2_NO_UTF_CHECK in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+page).
+.P
+The long synonyms for property names that Perl supports (such as \ep{Letter})
+are not supported by PCRE2, nor is it permitted to prefix any of these
+properties with "Is".
+.P
+No character that is in the Unicode table has the Cn (unassigned) property.
+Instead, this property is assumed for any code point that is not in the
+Unicode table.
+.
+.
+.SS "Binary (yes/no) properties for \ep and \eP"
+.rs
+.sp
+Unicode defines a number of binary properties, that is, properties whose only
+values are true or false. You can obtain a list of those that are recognized by
+\ep and \eP, along with their abbreviations, by running this command:
+.sp
+ pcre2test -LP
+.sp
+.
+.
+.SS "The Bidi_Class property for \ep and \eP"
+.rs
+.sp
+ \ep{Bidi_Class:} matches a character with the given class
+ \ep{BC:} matches a character with the given class
+.sp
+The recognized classes are:
+.sp
+ AL Arabic letter
+ AN Arabic number
+ B paragraph separator
+ BN boundary neutral
+ CS common separator
+ EN European number
+ ES European separator
+ ET European terminator
+ FSI first strong isolate
+ L left-to-right
+ LRE left-to-right embedding
+ LRI left-to-right isolate
+ LRO left-to-right override
+ NSM non-spacing mark
+ ON other neutral
+ PDF pop directional format
+ PDI pop directional isolate
+ R right-to-left
+ RLE right-to-left embedding
+ RLI right-to-left isolate
+ RLO right-to-left override
+ S segment separator
+ WS white space
+.sp
+As in all property specifications, an equals sign may be used instead of a
+colon and the class names are case-insensitive. Only the short names listed
+above are recognized; PCRE2 does not at present support any long alternatives.
+.
+.
+.SS Extended grapheme clusters
+.rs
+.sp
+The \eX escape matches any number of Unicode characters that form an "extended
+grapheme cluster", and treats the sequence as an atomic group
+.\" HTML
+.\"
+(see below).
+.\"
+Unicode supports various kinds of composite character by giving each character
+a grapheme breaking property, and having rules that use these properties to
+define the boundaries of extended grapheme clusters. The rules are defined in
+Unicode Standard Annex 29, "Unicode Text Segmentation". Unicode 11.0.0
+abandoned the use of some previous properties that had been used for emojis.
+Instead it introduced various emoji-specific properties. PCRE2 uses only the
+Extended Pictographic property.
+.P
+\eX always matches at least one character. Then it decides whether to add
+additional characters according to the following rules for ending a cluster:
+.P
+1. End at the end of the subject string.
+.P
+2. Do not end between CR and LF; otherwise end after any control character.
+.P
+3. Do not break Hangul (a Korean script) syllable sequences. Hangul characters
+are of five types: L, V, T, LV, and LVT. An L character may be followed by an
+L, V, LV, or LVT character; an LV or V character may be followed by a V or T
+character; an LVT or T character may be followed only by a T character.
+.P
+4. Do not end before extending characters or spacing marks or the zero-width
+joiner (ZWJ) character. Characters with the "mark" property always have the
+"extend" grapheme breaking property.
+.P
+5. Do not end after prepend characters.
+.P
+6. Do not end within emoji modifier sequences or emoji ZWJ (zero-width
+joiner) sequences. An emoji ZWJ sequence consists of a character with the
+Extended_Pictographic property, optionally followed by one or more characters
+with the Extend property, followed by the ZWJ character, followed by another
+Extended_Pictographic character.
+.P
+7. Do not break within emoji flag sequences. That is, do not break between
+regional indicator (RI) characters if there are an odd number of RI characters
+before the break point.
+.P
+8. Otherwise, end the cluster.
+.
+.
+.\" HTML
+.SS PCRE2's additional properties
+.rs
+.sp
+As well as the standard Unicode properties described above, PCRE2 supports four
+more that make it possible to convert traditional escape sequences such as \ew
+and \es to use Unicode properties. PCRE2 uses these non-standard, non-Perl
+properties internally when PCRE2_UCP is set. However, they may also be used
+explicitly. These properties are:
+.sp
+ Xan Any alphanumeric character
+ Xps Any POSIX space character
+ Xsp Any Perl space character
+ Xwd Any Perl "word" character
+.sp
+Xan matches characters that have either the L (letter) or the N (number)
+property. Xps matches the characters tab, linefeed, vertical tab, form feed, or
+carriage return, and any other character that has the Z (separator) property
+(this includes the space character). Xsp is the same as Xps; in PCRE1 it used
+to exclude vertical tab, for Perl compatibility, but Perl changed. Xwd matches
+the same characters as Xan, plus those that match Mn (non-spacing mark) or Pc
+(connector punctuation, which includes underscore).
+.P
+There is another non-standard property, Xuc, which matches any character that
+can be represented by a Universal Character Name in C++ and other programming
+languages. These are the characters $, @, ` (grave accent), and all characters
+with Unicode code points greater than or equal to U+00A0, except for the
+surrogates U+D800 to U+DFFF. Note that most base (ASCII) characters are
+excluded. (Universal Character Names are of the form \euHHHH or \eUHHHHHHHH
+where H is a hexadecimal digit. Note that the Xuc property does not match these
+sequences but the characters that they represent.)
+.
+.
+.\" HTML
+.SS "Resetting the match start"
+.rs
+.sp
+In normal use, the escape sequence \eK causes any previously matched characters
+not to be included in the final matched sequence that is returned. For example,
+the pattern:
+.sp
+ foo\eKbar
+.sp
+matches "foobar", but reports that it has matched "bar". \eK does not interact
+with anchoring in any way. The pattern:
+.sp
+ ^foo\eKbar
+.sp
+matches only when the subject begins with "foobar" (in single line mode),
+though it again reports the matched string as "bar". This feature is similar to
+a lookbehind assertion
+.\" HTML
+.\"
+(described below),
+.\"
+but the part of the pattern that precedes \eK is not constrained to match a
+limited number of characters, as is required for a lookbehind assertion. The
+use of \eK does not interfere with the setting of
+.\" HTML
+.\"
+captured substrings.
+.\"
+For example, when the pattern
+.sp
+ (foo)\eKbar
+.sp
+matches "foobar", the first substring is still set to "foo".
+.P
+From version 5.32.0 Perl forbids the use of \eK in lookaround assertions. From
+release 10.38 PCRE2 also forbids this by default. However, the
+PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK option can be used when calling
+\fBpcre2_compile()\fP to re-enable the previous behaviour. When this option is
+set, \eK is acted upon when it occurs inside positive assertions, but is
+ignored in negative assertions. Note that when a pattern such as (?=ab\eK)
+matches, the reported start of the match can be greater than the end of the
+match. Using \eK in a lookbehind assertion at the start of a pattern can also
+lead to odd effects. For example, consider this pattern:
+.sp
+ (?<=\eKfoo)bar
+.sp
+If the subject is "foobar", a call to \fBpcre2_match()\fP with a starting
+offset of 3 succeeds and reports the matching string as "foobar", that is, the
+start of the reported match is earlier than where the match started.
+.
+.
+.\" HTML
+.SS "Simple assertions"
+.rs
+.sp
+The final use of backslash is for certain simple assertions. An assertion
+specifies a condition that has to be met at a particular point in a match,
+without consuming any characters from the subject string. The use of
+groups for more complicated assertions is described
+.\" HTML
+.\"
+below.
+.\"
+The backslashed assertions are:
+.sp
+ \eb matches at a word boundary
+ \eB matches when not at a word boundary
+ \eA matches at the start of the subject
+ \eZ matches at the end of the subject
+ also matches before a newline at the end of the subject
+ \ez matches only at the end of the subject
+ \eG matches at the first matching position in the subject
+.sp
+Inside a character class, \eb has a different meaning; it matches the backspace
+character. If any other of these assertions appears in a character class, an
+"invalid escape sequence" error is generated.
+.P
+A word boundary is a position in the subject string where the current character
+and the previous character do not both match \ew or \eW (i.e. one matches
+\ew and the other matches \eW), or the start or end of the string if the
+first or last character matches \ew, respectively. When PCRE2 is built with
+Unicode support, the meanings of \ew and \eW can be changed by setting the
+PCRE2_UCP option. When this is done, it also affects \eb and \eB. Neither PCRE2
+nor Perl has a separate "start of word" or "end of word" metasequence. However,
+whatever follows \eb normally determines which it is. For example, the fragment
+\eba matches "a" at the start of a word.
+.P
+The \eA, \eZ, and \ez assertions differ from the traditional circumflex and
+dollar (described in the next section) in that they only ever match at the very
+start and end of the subject string, whatever options are set. Thus, they are
+independent of multiline mode. These three assertions are not affected by the
+PCRE2_NOTBOL or PCRE2_NOTEOL options, which affect only the behaviour of the
+circumflex and dollar metacharacters. However, if the \fIstartoffset\fP
+argument of \fBpcre2_match()\fP is non-zero, indicating that matching is to
+start at a point other than the beginning of the subject, \eA can never match.
+The difference between \eZ and \ez is that \eZ matches before a newline at the
+end of the string as well as at the very end, whereas \ez matches only at the
+end.
+.P
+The \eG assertion is true only when the current matching position is at the
+start point of the matching process, as specified by the \fIstartoffset\fP
+argument of \fBpcre2_match()\fP. It differs from \eA when the value of
+\fIstartoffset\fP is non-zero. By calling \fBpcre2_match()\fP multiple times
+with appropriate arguments, you can mimic Perl's /g option, and it is in this
+kind of implementation where \eG can be useful.
+.P
+Note, however, that PCRE2's implementation of \eG, being true at the starting
+character of the matching process, is subtly different from Perl's, which
+defines it as true at the end of the previous match. In Perl, these can be
+different when the previously matched string was empty. Because PCRE2 does just
+one match at a time, it cannot reproduce this behaviour.
+.P
+If all the alternatives of a pattern begin with \eG, the expression is anchored
+to the starting match position, and the "anchored" flag is set in the compiled
+regular expression.
+.
+.
+.SH "CIRCUMFLEX AND DOLLAR"
+.rs
+.sp
+The circumflex and dollar metacharacters are zero-width assertions. That is,
+they test for a particular condition being true without consuming any
+characters from the subject string. These two metacharacters are concerned with
+matching the starts and ends of lines. If the newline convention is set so that
+only the two-character sequence CRLF is recognized as a newline, isolated CR
+and LF characters are treated as ordinary data characters, and are not
+recognized as newlines.
+.P
+Outside a character class, in the default matching mode, the circumflex
+character is an assertion that is true only if the current matching point is at
+the start of the subject string. If the \fIstartoffset\fP argument of
+\fBpcre2_match()\fP is non-zero, or if PCRE2_NOTBOL is set, circumflex can
+never match if the PCRE2_MULTILINE option is unset. Inside a character class,
+circumflex has an entirely different meaning
+.\" HTML
+.\"
+(see below).
+.\"
+.P
+Circumflex need not be the first character of the pattern if a number of
+alternatives are involved, but it should be the first thing in each alternative
+in which it appears if the pattern is ever to match that branch. If all
+possible alternatives start with a circumflex, that is, if the pattern is
+constrained to match only at the start of the subject, it is said to be an
+"anchored" pattern. (There are also other constructs that can cause a pattern
+to be anchored.)
+.P
+The dollar character is an assertion that is true only if the current matching
+point is at the end of the subject string, or immediately before a newline at
+the end of the string (by default), unless PCRE2_NOTEOL is set. Note, however,
+that it does not actually match the newline. Dollar need not be the last
+character of the pattern if a number of alternatives are involved, but it
+should be the last item in any branch in which it appears. Dollar has no
+special meaning in a character class.
+.P
+The meaning of dollar can be changed so that it matches only at the very end of
+the string, by setting the PCRE2_DOLLAR_ENDONLY option at compile time. This
+does not affect the \eZ assertion.
+.P
+The meanings of the circumflex and dollar metacharacters are changed if the
+PCRE2_MULTILINE option is set. When this is the case, a dollar character
+matches before any newlines in the string, as well as at the very end, and a
+circumflex matches immediately after internal newlines as well as at the start
+of the subject string. It does not match after a newline that ends the string,
+for compatibility with Perl. However, this can be changed by setting the
+PCRE2_ALT_CIRCUMFLEX option.
+.P
+For example, the pattern /^abc$/ matches the subject string "def\enabc" (where
+\en represents a newline) in multiline mode, but not otherwise. Consequently,
+patterns that are anchored in single line mode because all branches start with
+^ are not anchored in multiline mode, and a match for circumflex is possible
+when the \fIstartoffset\fP argument of \fBpcre2_match()\fP is non-zero. The
+PCRE2_DOLLAR_ENDONLY option is ignored if PCRE2_MULTILINE is set.
+.P
+When the newline convention (see
+.\" HTML
+.\"
+"Newline conventions"
+.\"
+below) recognizes the two-character sequence CRLF as a newline, this is
+preferred, even if the single characters CR and LF are also recognized as
+newlines. For example, if the newline convention is "any", a multiline mode
+circumflex matches before "xyz" in the string "abc\er\enxyz" rather than after
+CR, even though CR on its own is a valid newline. (It also matches at the very
+start of the string, of course.)
+.P
+Note that the sequences \eA, \eZ, and \ez can be used to match the start and
+end of the subject in both modes, and if all branches of a pattern start with
+\eA it is always anchored, whether or not PCRE2_MULTILINE is set.
+.
+.
+.\" HTML
+.SH "FULL STOP (PERIOD, DOT) AND \eN"
+.rs
+.sp
+Outside a character class, a dot in the pattern matches any one character in
+the subject string except (by default) a character that signifies the end of a
+line. One or more characters may be specified as line terminators (see
+.\" HTML
+.\"
+"Newline conventions"
+.\"
+above).
+.P
+Dot never matches a single line-ending character. When the two-character
+sequence CRLF is the only line ending, dot does not match CR if it is
+immediately followed by LF, but otherwise it matches all characters (including
+isolated CRs and LFs). When ANYCRLF is selected for line endings, no occurrences
+of CR of LF match dot. When all Unicode line endings are being recognized, dot
+does not match CR or LF or any of the other line ending characters.
+.P
+The behaviour of dot with regard to newlines can be changed. If the
+PCRE2_DOTALL option is set, a dot matches any one character, without exception.
+If the two-character sequence CRLF is present in the subject string, it takes
+two dots to match it.
+.P
+The handling of dot is entirely independent of the handling of circumflex and
+dollar, the only relationship being that they both involve newlines. Dot has no
+special meaning in a character class.
+.P
+The escape sequence \eN when not followed by an opening brace behaves like a
+dot, except that it is not affected by the PCRE2_DOTALL option. In other words,
+it matches any character except one that signifies the end of a line.
+.P
+When \eN is followed by an opening brace it has a different meaning. See the
+section entitled
+.\" HTML
+.\"
+"Non-printing characters"
+.\"
+above for details. Perl also uses \eN{name} to specify characters by Unicode
+name; PCRE2 does not support this.
+.
+.
+.SH "MATCHING A SINGLE CODE UNIT"
+.rs
+.sp
+Outside a character class, the escape sequence \eC matches any one code unit,
+whether or not a UTF mode is set. In the 8-bit library, one code unit is one
+byte; in the 16-bit library it is a 16-bit unit; in the 32-bit library it is a
+32-bit unit. Unlike a dot, \eC always matches line-ending characters. The
+feature is provided in Perl in order to match individual bytes in UTF-8 mode,
+but it is unclear how it can usefully be used.
+.P
+Because \eC breaks up characters into individual code units, matching one unit
+with \eC in UTF-8 or UTF-16 mode means that the rest of the string may start
+with a malformed UTF character. This has undefined results, because PCRE2
+assumes that it is matching character by character in a valid UTF string (by
+default it checks the subject string's validity at the start of processing
+unless the PCRE2_NO_UTF_CHECK or PCRE2_MATCH_INVALID_UTF option is used).
+.P
+An application can lock out the use of \eC by setting the
+PCRE2_NEVER_BACKSLASH_C option when compiling a pattern. It is also possible to
+build PCRE2 with the use of \eC permanently disabled.
+.P
+PCRE2 does not allow \eC to appear in lookbehind assertions
+.\" HTML
+.\"
+(described below)
+.\"
+in UTF-8 or UTF-16 modes, because this would make it impossible to calculate
+the length of the lookbehind. Neither the alternative matching function
+\fBpcre2_dfa_match()\fP nor the JIT optimizer support \eC in these UTF modes.
+The former gives a match-time error; the latter fails to optimize and so the
+match is always run using the interpreter.
+.P
+In the 32-bit library, however, \eC is always supported (when not explicitly
+locked out) because it always matches a single code unit, whether or not UTF-32
+is specified.
+.P
+In general, the \eC escape sequence is best avoided. However, one way of using
+it that avoids the problem of malformed UTF-8 or UTF-16 characters is to use a
+lookahead to check the length of the next character, as in this pattern, which
+could be used with a UTF-8 string (ignore white space and line breaks):
+.sp
+ (?| (?=[\ex00-\ex7f])(\eC) |
+ (?=[\ex80-\ex{7ff}])(\eC)(\eC) |
+ (?=[\ex{800}-\ex{ffff}])(\eC)(\eC)(\eC) |
+ (?=[\ex{10000}-\ex{1fffff}])(\eC)(\eC)(\eC)(\eC))
+.sp
+In this example, a group that starts with (?| resets the capturing parentheses
+numbers in each alternative (see
+.\" HTML
+.\"
+"Duplicate Group Numbers"
+.\"
+below). The assertions at the start of each branch check the next UTF-8
+character for values whose encoding uses 1, 2, 3, or 4 bytes, respectively. The
+character's individual bytes are then captured by the appropriate number of
+\eC groups.
+.
+.
+.\" HTML
+.SH "SQUARE BRACKETS AND CHARACTER CLASSES"
+.rs
+.sp
+An opening square bracket introduces a character class, terminated by a closing
+square bracket. A closing square bracket on its own is not special by default.
+If a closing square bracket is required as a member of the class, it should be
+the first data character in the class (after an initial circumflex, if present)
+or escaped with a backslash. This means that, by default, an empty class cannot
+be defined. However, if the PCRE2_ALLOW_EMPTY_CLASS option is set, a closing
+square bracket at the start does end the (empty) class.
+.P
+A character class matches a single character in the subject. A matched
+character must be in the set of characters defined by the class, unless the
+first character in the class definition is a circumflex, in which case the
+subject character must not be in the set defined by the class. If a circumflex
+is actually required as a member of the class, ensure it is not the first
+character, or escape it with a backslash.
+.P
+For example, the character class [aeiou] matches any lower case English vowel,
+whereas [^aeiou] matches all other characters. Note that a circumflex is just a
+convenient notation for specifying the characters that are in the class by
+enumerating those that are not. A class that starts with a circumflex is not an
+assertion; it still consumes a character from the subject string, and therefore
+it fails to match if the current pointer is at the end of the string.
+.P
+Characters in a class may be specified by their code points using \eo, \ex, or
+\eN{U+hh..} in the usual way. When caseless matching is set, any letters in a
+class represent both their upper case and lower case versions, so for example,
+a caseless [aeiou] matches "A" as well as "a", and a caseless [^aeiou] does not
+match "A", whereas a caseful version would. Note that there are two ASCII
+characters, K and S, that, in addition to their lower case ASCII equivalents,
+are case-equivalent with Unicode U+212A (Kelvin sign) and U+017F (long S)
+respectively when either PCRE2_UTF or PCRE2_UCP is set. If you do not want
+these ASCII/non-ASCII case equivalences, you can suppress them by setting
+PCRE2_EXTRA_CASELESS_RESTRICT, either as an option in a compile context, or by
+including (*CASELESS_RESTRICT) or (?r) within a pattern.
+.P
+Characters that might indicate line breaks are never treated in any special way
+when matching character classes, whatever line-ending sequence is in use, and
+whatever setting of the PCRE2_DOTALL and PCRE2_MULTILINE options is used. A
+class such as [^a] always matches one of these characters.
+.P
+The generic character type escape sequences \ed, \eD, \eh, \eH, \ep, \eP, \es,
+\eS, \ev, \eV, \ew, and \eW may appear in a character class, and add the
+characters that they match to the class. For example, [\edABCDEF] matches any
+hexadecimal digit. In UTF modes, the PCRE2_UCP option affects the meanings of
+\ed, \es, \ew and their upper case partners, just as it does when they appear
+outside a character class, as described in the section entitled
+.\" HTML
+.\"
+"Generic character types"
+.\"
+above. The escape sequence \eb has a different meaning inside a character
+class; it matches the backspace character. The sequences \eB, \eR, and \eX are
+not special inside a character class. Like any other unrecognized escape
+sequences, they cause an error. The same is true for \eN when not followed by
+an opening brace.
+.P
+The minus (hyphen) character can be used to specify a range of characters in a
+character class. For example, [d-m] matches any letter between d and m,
+inclusive. If a minus character is required in a class, it must be escaped with
+a backslash or appear in a position where it cannot be interpreted as
+indicating a range, typically as the first or last character in the class,
+or immediately after a range. For example, [b-d-z] matches letters in the range
+b to d, a hyphen character, or z.
+.P
+There is some special treatment for alphabetic ranges in EBCDIC environments;
+see the section
+.\" HTML
+.\"
+"EBCDIC environments"
+.\"
+below.
+.P
+Perl treats a hyphen as a literal if it appears before or after a POSIX class
+(see below) or before or after a character type escape such as \ed or \eH.
+However, unless the hyphen is the last character in the class, Perl outputs a
+warning in its warning mode, as this is most likely a user error. As PCRE2 has
+no facility for warning, an error is given in these cases.
+.P
+It is not possible to have the literal character "]" as the end character of a
+range. A pattern such as [W-]46] is interpreted as a class of two characters
+("W" and "-") followed by a literal string "46]", so it would match "W46]" or
+"-46]". However, if the "]" is escaped with a backslash it is interpreted as
+the end of a range, so [W-\e]46] is interpreted as a class containing a range
+and two other characters. The octal or hexadecimal representation of "]" can
+also be used to end a range.
+.P
+Ranges normally include all code points between the start and end characters,
+inclusive. They can also be used for code points specified numerically, for
+example [\e000-\e037]. Ranges can include any characters that are valid for the
+current mode. In any UTF mode, the so-called "surrogate" characters (those
+whose code points lie between 0xd800 and 0xdfff inclusive) may not be specified
+explicitly by default (the PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES option disables
+this check). However, ranges such as [\ex{d7ff}-\ex{e000}], which include the
+surrogates, are always permitted.
+.P
+If a range that includes letters is used when caseless matching is set, it
+matches the letters in either case. For example, [W-c] is equivalent to
+[][\e\e^_`wxyzabc], matched caselessly, and in a non-UTF mode, if character
+tables for a French locale are in use, [\exc8-\excb] matches accented E
+characters in both cases.
+.P
+A circumflex can conveniently be used with the upper case character types to
+specify a more restricted set of characters than the matching lower case type.
+For example, the class [^\eW_] matches any letter or digit, but not underscore,
+whereas [\ew] includes underscore. A positive character class should be read as
+"something OR something OR ..." and a negative class as "NOT something AND NOT
+something AND NOT ...".
+.P
+The metacharacters that are recognized in character classes are backslash,
+hyphen (when it can be interpreted as specifying a range), circumflex
+(only at the start), and the terminating closing square bracket. An opening
+square bracket is also special when it can be interpreted as introducing a
+POSIX class (see
+.\" HTML
+.\"
+"Posix character classes"
+.\"
+below), or a special compatibility feature (see
+.\" HTML
+.\"
+"Compatibility feature for word boundaries"
+.\"
+below. Escaping any non-alphanumeric character in a class turns it into a
+literal, whether or not it would otherwise be a metacharacter.
+.
+.
+.SH "PERL EXTENDED CHARACTER CLASSES"
+.rs
+.sp
+From release 10.45 PCRE2 supports Perl's (?[...]) extended character class
+syntax. This can be used to perform set operations such as intersection on
+character classes.
+.P
+The syntax permitted within (?[...]) is quite different to ordinary character
+classes. Inside the extended class, there is an expression syntax consisting of
+"atoms", operators, and ordinary parentheses "()" used for grouping. Such
+classes always have the Perl /xx modifier (PCRE2 option PCRE2_EXTENDED_MORE)
+turned on within them. This means that literal space and tab characters are
+ignored everywhere in the class.
+.P
+The allowed atoms are individual characters specified by escape sequences such
+as \en or \ex{123}, character types such as \ed, POSIX classes such as
+[:alpha:], and nested ordinary (non-extended) character classes. For example,
+in (?[\ed & [...]]) the nested class [...] follows the usual rules for ordinary
+character classes, in which parentheses are not metacharacters, and character
+literals and ranges are permitted.
+.P
+Character literals and ranges may not appear outside a nested ordinary
+character class because they are not atoms in the extended syntax. The extended
+syntax does not introduce any additional escape sequences, so (?[\ey]) is an
+unknown escape, as it would be in [\ey].
+.P
+In the extended syntax, ^ does not negate a class (except within an
+ordinary class nested inside an extended class); it is instead a binary
+operator.
+.P
+The binary operators are "&" (intersection), "|" or "+" (union), "-"
+(subtraction) and "^" (symmetric difference). These are left-associative and
+"&" has higher (tighter) precedence, while the others have equal lower
+precedence. The one prefix unary operator is "!" (complement), with highest
+precedence.
+.
+.
+.SH "UTS#18 EXTENDED CHARACTER CLASSES"
+.rs
+.sp
+The PCRE2_ALT_EXTENDED_CLASS option enables an alternative to Perl's (?[...])
+syntax, allowing instead extended class behaviour inside ordinary [...]
+character classes. This altered syntax for [...] classes is loosely described
+by the Unicode standard UTS#18. The PCRE2_ALT_EXTENDED_CLASS option does not
+prevent use of (?[...]) classes; it just changes the meaning of all
+[...] classes that are not nested inside a Perl (?[...]) class.
+.P
+Firstly, in ordinary Perl [...] syntax, an expression such as "[a[]" is a
+character class with two literal characters "a" and "[", but in UTS#18 extended
+classes the "[" character becomes an additional metacharacter within classes,
+denoting the start of a nested class, so a literal "[" must be escaped as "\e[".
+.P
+Secondly, within the UTS#18 extended syntax, there are operators "||", "&&",
+"--" and "~~" which denote character class union, intersection, subtraction,
+and symmetric difference respectively. In standard Perl syntax, these would
+simply be needlessly-repeated literals (except for "--" which could be the
+start or end of a range). In UTS#18 extended classes these operators can be used
+in constructs such as [\ep{L}--[QW]] for "Unicode letters, other than Q and W".
+A literal "-" at the start or end of a range must be escaped, so while "[--1]"
+in Perl syntax is the range from hyphen to "1", it must be escaped as "[\e--1]"
+in UTS#18 extended classes.
+.P
+Unlike Perl's (?[...]) extended classes, the PCRE2_EXTENDED_MORE option to
+ignore space and tab characters is not automatically enabled for UTS#18
+extended classes, but it is honoured if set.
+.P
+Extended UTS#18 classes can be nested, and nested classes are themselves
+extended classes (unlike Perl, where nested classes must be simple classes).
+For example, [\ep{L}&&[\ep{Thai}||\ep{Greek}]] matches any letter that is in
+the Thai or Greek scripts. Note that this means that no special grouping
+characters (such as the parentheses used in Perl's (?[...]) class syntax) are
+needed.
+.P
+Individual class items (literal characters, literal ranges, properties such as
+\ed or \ep{...}, and nested classes) can be combined by juxtaposition or by an
+operator. Juxtaposition is the implicit union operator, and binds more tightly
+than any explicit operator. Thus a sequence of literals and/or ranges behaves
+as if it is enclosed in square brackets. For example, [A-Z0-9&&[^E8]] is the
+same as [[A-Z0-9]&&[^E8]], which matches any upper case alphanumeric character
+except "E" or "8".
+.P
+Precedence between the explicit operators is not defined, so mixing operators
+is a syntax error. For example, [A&&B--C] is an error, but [A&&[B--C]] is
+valid.
+.P
+This is an emerging syntax which is being adopted gradually across the regex
+ecosystem: for example JavaScript adopted the "/v" flag in ECMAScript 2024;
+Python's "re" module reserves the syntax for future use with a FutureWarning
+for unescaped use of "[" as a literal within character classes. Due to UTS#18
+providing insufficient guidance, engines interpret the syntax differently.
+Rust's "regex" crate and Python's "regex" PyPi module both implement UTS#18
+extended classes, but with slight incompatibilities ([A||B&&C] is parsed as
+[A||[B&&C]] in Python's "regex" but as [[A||B]&&C] in Rust's "regex").
+.P
+PCRE2's syntax adds syntax restrictions similar to ECMASCript's /v flag, so
+that all the UTS#18 extended classes accepted as valid by PCRE2 have the
+property that they are interpreted either with the same behaviour, or as
+invalid, by all other major engines. Please file an issue if you are aware of
+cross-engine differences in behaviour between PCRE2 and another major engine.
+.
+.
+.\" HTML
+.SH "POSIX CHARACTER CLASSES"
+.rs
+.sp
+Perl supports the POSIX notation for character classes. This uses names
+enclosed by [: and :] within the enclosing square brackets. PCRE2 also supports
+this notation, in both ordinary and extended classes. For example,
+.sp
+ [01[:alpha:]%]
+.sp
+matches "0", "1", any alphabetic character, or "%". The supported class names
+are:
+.sp
+ alnum letters and digits
+ alpha letters
+ ascii character codes 0 - 127
+ blank space or tab only
+ cntrl control characters
+ digit decimal digits (same as \ed)
+ graph printing characters, excluding space
+ lower lower case letters
+ print printing characters, including space
+ punct printing characters, excluding letters and digits and space
+ space white space (the same as \es from PCRE2 8.34)
+ upper upper case letters
+ word "word" characters (same as \ew)
+ xdigit hexadecimal digits
+.sp
+The default "space" characters are HT (9), LF (10), VT (11), FF (12), CR (13),
+and space (32). If locale-specific matching is taking place, the list of space
+characters may be different; there may be fewer or more of them. "Space" and
+\es match the same set of characters, as do "word" and \ew.
+.P
+The name "word" is a Perl extension, and "blank" is a GNU extension from Perl
+5.8. Another Perl extension is negation, which is indicated by a ^ character
+after the colon. For example,
+.sp
+ [12[:^digit:]]
+.sp
+matches "1", "2", or any non-digit. PCRE2 (and Perl) also recognize the POSIX
+syntax [.ch.] and [=ch=] where "ch" is a "collating element", but these are not
+supported, and an error is given if they are encountered.
+.P
+By default, characters with values greater than 127 do not match any of the
+POSIX character classes, although this may be different for characters in the
+range 128-255 when locale-specific matching is happening. However, in UCP mode,
+unless certain options are set (see below), some of the classes are changed so
+that Unicode character properties are used. This is achieved by replacing
+POSIX classes with other sequences, as follows:
+.sp
+ [:alnum:] becomes \ep{Xan}
+ [:alpha:] becomes \ep{L}
+ [:blank:] becomes \eh
+ [:cntrl:] becomes \ep{Cc}
+ [:digit:] becomes \ep{Nd}
+ [:lower:] becomes \ep{Ll}
+ [:space:] becomes \ep{Xps}
+ [:upper:] becomes \ep{Lu}
+ [:word:] becomes \ep{Xwd}
+.sp
+Negated versions, such as [:^alpha:] use \eP instead of \ep. Four other POSIX
+classes are handled specially in UCP mode:
+.TP 10
+[:graph:]
+This matches characters that have glyphs that mark the page when printed. In
+Unicode property terms, it matches all characters with the L, M, N, P, S, or Cf
+properties, except for:
+.sp
+ U+061C Arabic Letter Mark
+ U+180E Mongolian Vowel Separator
+ U+2066 - U+2069 Various "isolate"s
+.sp
+.TP 10
+[:print:]
+This matches the same characters as [:graph:] plus space characters that are
+not controls, that is, characters with the Zs property.
+.TP 10
+[:punct:]
+This matches all characters that have the Unicode P (punctuation) property,
+plus those characters with code points less than 256 that have the S (Symbol)
+property.
+.TP 10
+[:xdigit:]
+In addition to the ASCII hexadecimal digits, this also matches the "fullwidth"
+versions of those characters, whose Unicode code points start at U+FF10. This
+is a change that was made in PCRE2 release 10.43 for Perl compatibility.
+.P
+The other POSIX classes are unchanged by PCRE2_UCP, and match only characters
+with code points less than 256.
+.P
+There are two options that can be used to restrict the POSIX classes to ASCII
+characters when PCRE2_UCP is set. The option PCRE2_EXTRA_ASCII_DIGIT affects
+just [:digit:] and [:xdigit:]. Within a pattern, this can be set and unset by
+(?aT) and (?-aT). The PCRE2_EXTRA_ASCII_POSIX option disables UCP processing
+for all POSIX classes, including [:digit:] and [:xdigit:]. Within a pattern,
+(?aP) and (?-aP) set and unset both these options for consistency.
+.
+.
+.\" HTML
+.SH "COMPATIBILITY FEATURE FOR WORD BOUNDARIES"
+.rs
+.sp
+In the POSIX.2 compliant library that was included in 4.4BSD Unix, the ugly
+syntax [[:<:]] and [[:>:]] is used for matching "start of word" and "end of
+word". PCRE2 treats these items as follows:
+.sp
+ [[:<:]] is converted to \eb(?=\ew)
+ [[:>:]] is converted to \eb(?<=\ew)
+.sp
+Only these exact character sequences are recognized. A sequence such as
+[a[:<:]b] provokes error for an unrecognized POSIX class name. This support is
+not compatible with Perl. It is provided to help migrations from other
+environments, and is best not used in any new patterns. Note that \eb matches
+at the start and the end of a word (see
+.\" HTML
+.\"
+"Simple assertions"
+.\"
+above), and in a Perl-style pattern the preceding or following character
+normally shows which is wanted, without the need for the assertions that are
+used above in order to give exactly the POSIX behaviour. Note also that the
+PCRE2_UCP option changes the meaning of \ew (and therefore \eb) by default, so
+it also affects these POSIX sequences.
+.
+.
+.SH "VERTICAL BAR"
+.rs
+.sp
+Vertical bar characters are used to separate alternative patterns. For example,
+the pattern
+.sp
+ gilbert|sullivan
+.sp
+matches either "gilbert" or "sullivan". Any number of alternatives may appear,
+and an empty alternative is permitted (matching the empty string). The matching
+process tries each alternative in turn, from left to right, and the first one
+that succeeds is used. If the alternatives are within a group
+.\" HTML
+.\"
+(defined below),
+.\"
+"succeeds" means matching the rest of the main pattern as well as the
+alternative in the group.
+.
+.
+.\" HTML
+.SH "INTERNAL OPTION SETTING"
+.rs
+.sp
+The settings of several options can be changed within a pattern by a sequence
+of letters enclosed between "(?" and ")". The following are Perl-compatible,
+and are described in detail in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation. The option letters are:
+.sp
+ i for PCRE2_CASELESS
+ m for PCRE2_MULTILINE
+ n for PCRE2_NO_AUTO_CAPTURE
+ s for PCRE2_DOTALL
+ x for PCRE2_EXTENDED
+ xx for PCRE2_EXTENDED_MORE
+.sp
+For example, (?im) sets caseless, multiline matching. It is also possible to
+unset these options by preceding the relevant letters with a hyphen, for
+example (?-im). The two "extended" options are not independent; unsetting
+either one cancels the effects of both of them.
+.P
+A combined setting and unsetting such as (?im-sx), which sets PCRE2_CASELESS
+and PCRE2_MULTILINE while unsetting PCRE2_DOTALL and PCRE2_EXTENDED, is also
+permitted. Only one hyphen may appear in the options string. If a letter
+appears both before and after the hyphen, the option is unset. An empty options
+setting "(?)" is allowed. Needless to say, it has no effect.
+.P
+If the first character following (? is a circumflex, it causes all of the above
+options to be unset. Letters may follow the circumflex to cause some options to
+be re-instated, but a hyphen may not appear.
+.P
+Some PCRE2-specific options can be changed by the same mechanism using these
+pairs or individual letters:
+.sp
+ aD for PCRE2_EXTRA_ASCII_BSD
+ aS for PCRE2_EXTRA_ASCII_BSS
+ aW for PCRE2_EXTRA_ASCII_BSW
+ aP for PCRE2_EXTRA_ASCII_POSIX and PCRE2_EXTRA_ASCII_DIGIT
+ aT for PCRE2_EXTRA_ASCII_DIGIT
+ r for PCRE2_EXTRA_CASELESS_RESTRICT
+ J for PCRE2_DUPNAMES
+ U for PCRE2_UNGREEDY
+.sp
+However, except for 'r', these are not unset by (?^), which is equivalent to
+(?-imnrsx). If 'a' is not followed by any of the upper case letters shown
+above, it sets (or unsets) all the ASCII options.
+.P
+PCRE2_EXTRA_ASCII_DIGIT has no additional effect when PCRE2_EXTRA_ASCII_POSIX
+is set, but including it in (?aP) means that (?-aP) suppresses all ASCII
+restrictions for POSIX classes.
+.P
+When one of these option changes occurs at top level (that is, not inside group
+parentheses), the change applies until a subsequent change, or the end of the
+pattern. An option change within a group (see below for a description of
+groups) affects only that part of the group that follows it. At the end of the
+group these options are reset to the state they were before the group. For
+example,
+.sp
+ (a(?i)b)c
+.sp
+matches abc and aBc and no other strings (assuming PCRE2_CASELESS is not set
+externally). Any changes made in one alternative do carry on into subsequent
+branches within the same group. For example,
+.sp
+ (a(?i)b|c)
+.sp
+matches "ab", "aB", "c", and "C", even though when matching "C" the first
+branch is abandoned before the option setting. This is because the effects of
+option settings happen at compile time. There would be some very weird
+behaviour otherwise.
+.P
+As a convenient shorthand, if any option settings are required at the start of
+a non-capturing group (see the next section), the option letters may
+appear between the "?" and the ":". Thus the two patterns
+.sp
+ (?i:saturday|sunday)
+ (?:(?i)saturday|sunday)
+.sp
+match exactly the same set of strings.
+.P
+\fBNote:\fP There are other PCRE2-specific options, applying to the whole
+pattern, which can be set by the application when the compiling function is
+called. In addition, the pattern can contain special leading sequences such as
+(*CRLF) to override what the application has set or what has been defaulted.
+Details are given in the section entitled
+.\" HTML
+.\"
+"Newline sequences"
+.\"
+above. There are also the (*UTF) and (*UCP) leading sequences that can be used
+to set UTF and Unicode property modes; they are equivalent to setting the
+PCRE2_UTF and PCRE2_UCP options, respectively. However, the application can set
+the PCRE2_NEVER_UTF or PCRE2_NEVER_UCP options, which lock out the use of the
+(*UTF) and (*UCP) sequences.
+.
+.
+.\" HTML
+.SH GROUPS
+.rs
+.sp
+Groups are delimited by parentheses (round brackets), which can be nested.
+Turning part of a pattern into a group does two things:
+.sp
+1. It localizes a set of alternatives. For example, the pattern
+.sp
+ cat(aract|erpillar|)
+.sp
+matches "cataract", "caterpillar", or "cat". Without the parentheses, it would
+match "cataract", "erpillar" or an empty string.
+.sp
+2. It creates a "capture group". This means that, when the whole pattern
+matches, the portion of the subject string that matched the group is passed
+back to the caller, separately from the portion that matched the whole pattern.
+(This applies only to the traditional matching function; the DFA matching
+function does not support capturing.)
+.P
+Opening parentheses are counted from left to right (starting from 1) to obtain
+numbers for capture groups. For example, if the string "the red king" is
+matched against the pattern
+.sp
+ the ((red|white) (king|queen))
+.sp
+the captured substrings are "red king", "red", and "king", and are numbered 1,
+2, and 3, respectively.
+.P
+The fact that plain parentheses fulfil two functions is not always helpful.
+There are often times when grouping is required without capturing. If an
+opening parenthesis is followed by a question mark and a colon, the group
+does not do any capturing, and is not counted when computing the number of any
+subsequent capture groups. For example, if the string "the white queen"
+is matched against the pattern
+.sp
+ the ((?:red|white) (king|queen))
+.sp
+the captured substrings are "white queen" and "queen", and are numbered 1 and
+2. The maximum number of capture groups is 65535.
+.P
+As a convenient shorthand, if any option settings are required at the start of
+a non-capturing group, the option letters may appear between the "?" and the
+":". Thus the two patterns
+.sp
+ (?i:saturday|sunday)
+ (?:(?i)saturday|sunday)
+.sp
+match exactly the same set of strings. Because alternative branches are tried
+from left to right, and options are not reset until the end of the group is
+reached, an option setting in one branch does affect subsequent branches, so
+the above patterns match "SUNDAY" as well as "Saturday".
+.
+.
+.\" HTML
+.SH "DUPLICATE GROUP NUMBERS"
+.rs
+.sp
+Perl 5.10 introduced a feature whereby each alternative in a group uses the
+same numbers for its capturing parentheses. Such a group starts with (?| and is
+itself a non-capturing group. For example, consider this pattern:
+.sp
+ (?|(Sat)ur|(Sun))day
+.sp
+Because the two alternatives are inside a (?| group, both sets of capturing
+parentheses are numbered one. Thus, when the pattern matches, you can look
+at captured substring number one, whichever alternative matched. This construct
+is useful when you want to capture part, but not all, of one of a number of
+alternatives. Inside a (?| group, parentheses are numbered as usual, but the
+number is reset at the start of each branch. The numbers of any capturing
+parentheses that follow the whole group start after the highest number used in
+any branch. The following example is taken from the Perl documentation. The
+numbers underneath show in which buffer the captured content will be stored.
+.sp
+ # before ---------------branch-reset----------- after
+ / ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x
+ # 1 2 2 3 2 3 4
+.sp
+A backreference to a capture group uses the most recent value that is set for
+the group. The following pattern matches "abcabc" or "defdef":
+.sp
+ /(?|(abc)|(def))\e1/
+.sp
+In contrast, a subroutine call to a capture group always refers to the
+first one in the pattern with the given number. The following pattern matches
+"abcabc" or "defabc":
+.sp
+ /(?|(abc)|(def))(?1)/
+.sp
+A relative reference such as (?-1) is no different: it is just a convenient way
+of computing an absolute group number.
+.P
+If a
+.\" HTML
+.\"
+condition test
+.\"
+for a group's having matched refers to a non-unique number, the test is
+true if any group with that number has matched.
+.P
+An alternative approach to using this "branch reset" feature is to use
+duplicate named groups, as described in the next section.
+.
+.
+.SH "NAMED CAPTURE GROUPS"
+.rs
+.sp
+Identifying capture groups by number is simple, but it can be very hard to keep
+track of the numbers in complicated patterns. Furthermore, if an expression is
+modified, the numbers may change. To help with this difficulty, PCRE2 supports
+the naming of capture groups. This feature was not added to Perl until release
+5.10. Python had the feature earlier, and PCRE1 introduced it at release 4.0,
+using the Python syntax. PCRE2 supports both the Perl and the Python syntax.
+.P
+In PCRE2, a capture group can be named in one of three ways: (?...) or
+(?'name'...) as in Perl, or (?P...) as in Python. Names may be up to
+.\" DEFINE MAX_NAME_SIZE
+128 code units long. When PCRE2_UTF is not set, they may contain only ASCII
+alphanumeric characters and underscores, but must start with a non-digit. When
+PCRE2_UTF is set, the syntax of group names is extended to allow any Unicode
+letter or Unicode decimal digit. In other words, group names must match one of
+these patterns:
+.sp
+ ^[_A-Za-z][_A-Za-z0-9]*\ez when PCRE2_UTF is not set
+ ^[_\ep{L}][_\ep{L}\ep{Nd}]*\ez when PCRE2_UTF is set
+.sp
+References to capture groups from other parts of the pattern, such as
+.\" HTML
+.\"
+backreferences,
+.\"
+.\" HTML
+.\"
+recursion,
+.\"
+and
+.\" HTML
+.\"
+conditions,
+.\"
+can all be made by name as well as by number.
+.P
+Named capture groups are allocated numbers as well as names, exactly as
+if the names were not present. In both PCRE2 and Perl, capture groups
+are primarily identified by numbers; any names are just aliases for these
+numbers. The PCRE2 API provides function calls for extracting the complete
+name-to-number translation table from a compiled pattern, as well as
+convenience functions for extracting captured substrings by name.
+.P
+\fBWarning:\fP When more than one capture group has the same number, as
+described in the previous section, a name given to one of them applies to all
+of them. Perl allows identically numbered groups to have different names.
+Consider this pattern, where there are two capture groups, both numbered 1:
+.sp
+ (?|(?aa)|(?bb))
+.sp
+Perl allows this, with both names AA and BB as aliases of group 1. Thus, after
+a successful match, both names yield the same value (either "aa" or "bb").
+.P
+In an attempt to reduce confusion, PCRE2 does not allow the same group number
+to be associated with more than one name. The example above provokes a
+compile-time error. However, there is still scope for confusion. Consider this
+pattern:
+.sp
+ (?|(?aa)|(bb))
+.sp
+Although the second group number 1 is not explicitly named, the name AA is
+still an alias for any group 1. Whether the pattern matches "aa" or "bb", a
+reference by name to group AA yields the matched string.
+.P
+By default, a name must be unique within a pattern, except that duplicate names
+are permitted for groups with the same number, for example:
+.sp
+ (?|(?aa)|(?bb))
+.sp
+The duplicate name constraint can be disabled by setting the PCRE2_DUPNAMES
+option at compile time, or by the use of (?J) within the pattern, as described
+in the section entitled
+.\" HTML
+.\"
+"Internal Option Setting"
+.\"
+above.
+.P
+Duplicate names can be useful for patterns where only one instance of the named
+capture group can match. Suppose you want to match the name of a weekday,
+either as a 3-letter abbreviation or as the full name, and in both cases you
+want to extract the abbreviation. This pattern (ignoring the line breaks) does
+the job:
+.sp
+ (?J)
+ (?Mon|Fri|Sun)(?:day)?|
+ (?Tue)(?:sday)?|
+ (?Wed)(?:nesday)?|
+ (?Thu)(?:rsday)?|
+ (?Sat)(?:urday)?
+.sp
+There are five capture groups, but only one is ever set after a match. The
+convenience functions for extracting the data by name returns the substring for
+the first (and in this example, the only) group of that name that matched. This
+saves searching to find which numbered group it was. (An alternative way of
+solving this problem is to use a "branch reset" group, as described in the
+previous section.)
+.P
+If you make a backreference to a non-unique named group from elsewhere in the
+pattern, the groups to which the name refers are checked in the order in which
+they appear in the overall pattern. The first one that is set is used for the
+reference. For example, this pattern matches both "foofoo" and "barbar" but not
+"foobar" or "barfoo":
+.sp
+ (?J)(?:(?foo)|(?bar))\ek
+.sp
+.P
+If you make a subroutine call to a non-unique named group, the one that
+corresponds to the first occurrence of the name is used. In the absence of
+duplicate numbers this is the one with the lowest number.
+.P
+If you use a named reference in a condition
+test (see the
+.\"
+.\" HTML
+.\"
+section about conditions
+.\"
+below), either to check whether a capture group has matched, or to check for
+recursion, all groups with the same name are tested. If the condition is true
+for any one of them, the overall condition is true. This is the same behaviour
+as testing by number. For further details of the interfaces for handling named
+capture groups, see the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation.
+.
+.
+.SH REPETITION
+.rs
+.sp
+Repetition is specified by quantifiers, which may follow any one of these
+items:
+.sp
+ a literal data character
+ the dot metacharacter
+ the \eC escape sequence
+ the \eR escape sequence
+ the \eX escape sequence
+ any escape sequence that matches a single character
+ a character class
+ a backreference
+ a parenthesized group (including lookaround assertions)
+ a subroutine call (recursive or otherwise)
+.sp
+If a quantifier does not follow a repeatable item, an error occurs. The
+general repetition quantifier specifies a minimum and maximum number of
+permitted matches by giving two numbers in curly brackets (braces), separated
+by a comma. The numbers must be less than 65536, and the first must be less
+than or equal to the second. For example,
+.sp
+ z{2,4}
+.sp
+matches "zz", "zzz", or "zzzz". A closing brace on its own is not a special
+character. If the second number is omitted, but the comma is present, there is
+no upper limit; if the second number and the comma are both omitted, the
+quantifier specifies an exact number of required matches. Thus
+.sp
+ [aeiou]{3,}
+.sp
+matches at least 3 successive vowels, but may match many more, whereas
+.sp
+ \ed{8}
+.sp
+matches exactly 8 digits. If the first number is omitted, the lower limit is
+taken as zero; in this case the upper limit must be present.
+.sp
+ X{,4} is interpreted as X{0,4}
+.sp
+This is a change in behaviour that happened in Perl 5.34.0 and PCRE2 10.43. In
+earlier versions such a sequence was not interpreted as a quantifier. Other
+regular expression engines may behave either way.
+.P
+If the characters that follow an opening brace do not match the syntax of a
+quantifier, the brace is taken as a literal character. In particular, this
+means that {,} is a literal string of three characters.
+.P
+Note that not every opening brace is potentially the start of a quantifier
+because braces are used in other items such as \eN{U+345} or \ek{name}.
+.P
+In UTF modes, quantifiers apply to characters rather than to individual code
+units. Thus, for example, \ex{100}{2} matches two characters, each of
+which is represented by a two-byte sequence in a UTF-8 string. Similarly,
+\eX{3} matches three Unicode extended grapheme clusters, each of which may be
+several code units long (and they may be of different lengths).
+.P
+The quantifier {0} is permitted, causing the expression to behave as if the
+previous item and the quantifier were not present. This may be useful for
+capture groups that are referenced as
+.\" HTML
+.\"
+subroutines
+.\"
+from elsewhere in the pattern (but see also the section entitled
+.\" HTML
+.\"
+"Defining capture groups for use by reference only"
+.\"
+below). Except for parenthesized groups, items that have a {0} quantifier are
+omitted from the compiled pattern.
+.P
+For convenience, the three most common quantifiers have single-character
+abbreviations:
+.sp
+ * is equivalent to {0,}
+ + is equivalent to {1,}
+ ? is equivalent to {0,1}
+.sp
+It is possible to construct infinite loops by following a group that can match
+no characters with a quantifier that has no upper limit, for example:
+.sp
+ (a?)*
+.sp
+Earlier versions of Perl and PCRE1 used to give an error at compile time for
+such patterns. However, because there are cases where this can be useful, such
+patterns are now accepted, but whenever an iteration of such a group matches no
+characters, matching moves on to the next item in the pattern instead of
+repeatedly matching an empty string. This does not prevent backtracking into
+any of the iterations if a subsequent item fails to match.
+.P
+By default, quantifiers are "greedy", that is, they match as much as possible
+(up to the maximum number of permitted repetitions), without causing the rest
+of the pattern to fail. The classic example of where this gives problems is in
+trying to match comments in C programs. These appear between /* and */ and
+within the comment, individual * and / characters may appear. An attempt to
+match C comments by applying the pattern
+.sp
+ /\e*.*\e*/
+.sp
+to the string
+.sp
+ /* first comment */ not comment /* second comment */
+.sp
+fails, because it matches the entire string owing to the greediness of the .*
+item. However, if a quantifier is followed by a question mark, it ceases to be
+greedy, and instead matches the minimum number of times possible, so the
+pattern
+.sp
+ /\e*.*?\e*/
+.sp
+does the right thing with C comments. The meaning of the various quantifiers is
+not otherwise changed, just the preferred number of matches. Do not confuse
+this use of question mark with its use as a quantifier in its own right.
+Because it has two uses, it can sometimes appear doubled, as in
+.sp
+ \ed??\ed
+.sp
+which matches one digit by preference, but can match two if that is the only
+way the rest of the pattern matches.
+.P
+If the PCRE2_UNGREEDY option is set (an option that is not available in Perl),
+the quantifiers are not greedy by default, but individual ones can be made
+greedy by following them with a question mark. In other words, it inverts the
+default behaviour.
+.P
+When a parenthesized group is quantified with a minimum repeat count that
+is greater than 1 or with a limited maximum, more memory is required for the
+compiled pattern, in proportion to the size of the minimum or maximum.
+.P
+If a pattern starts with .* or .{0,} and the PCRE2_DOTALL option (equivalent
+to Perl's /s) is set, thus allowing the dot to match newlines, the pattern is
+implicitly anchored, because whatever follows will be tried against every
+character position in the subject string, so there is no point in retrying the
+overall match at any position after the first. PCRE2 normally treats such a
+pattern as though it were preceded by \eA.
+.P
+In cases where it is known that the subject string contains no newlines, it is
+worth setting PCRE2_DOTALL in order to obtain this optimization, or
+alternatively, using ^ to indicate anchoring explicitly.
+.P
+However, there are some cases where the optimization cannot be used. When .*
+is inside capturing parentheses that are the subject of a backreference
+elsewhere in the pattern, a match at the start may fail where a later one
+succeeds. Consider, for example:
+.sp
+ (.*)abc\e1
+.sp
+If the subject is "xyz123abc123" the match point is the fourth character. For
+this reason, such a pattern is not implicitly anchored.
+.P
+Another case where implicit anchoring is not applied is when the leading .* is
+inside an atomic group. Once again, a match at the start may fail where a later
+one succeeds. Consider this pattern:
+.sp
+ (?>.*?a)b
+.sp
+It matches "ab" in the subject "aab". The use of the backtracking control verbs
+(*PRUNE) and (*SKIP) also disable this optimization. To do so explicitly,
+either pass the compile option PCRE2_NO_DOTSTAR_ANCHOR, or call
+\fBpcre2_set_optimize()\fP with a PCRE2_DOTSTAR_ANCHOR_OFF directive.
+.P
+When a capture group is repeated, the value captured is the substring that
+matched the final iteration. For example, after
+.sp
+ (tweedle[dume]{3}\es*)+
+.sp
+has matched "tweedledum tweedledee" the value of the captured substring is
+"tweedledee". However, if there are nested capture groups, the corresponding
+captured values may have been set in previous iterations. For example, after
+.sp
+ (a|(b))+
+.sp
+matches "aba" the value of the second captured substring is "b".
+.
+.
+.\" HTML
+.SH "ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS"
+.rs
+.sp
+With both maximizing ("greedy") and minimizing ("ungreedy" or "lazy")
+repetition, failure of what follows normally causes the repeated item to be
+re-evaluated to see if a different number of repeats allows the rest of the
+pattern to match. Sometimes it is useful to prevent this, either to change the
+nature of the match, or to cause it fail earlier than it otherwise might, when
+the author of the pattern knows there is no point in carrying on.
+.P
+Consider, for example, the pattern \ed+foo when applied to the subject line
+.sp
+ 123456bar
+.sp
+After matching all 6 digits and then failing to match "foo", the normal
+action of the matcher is to try again with only 5 digits matching the \ed+
+item, and then with 4, and so on, before ultimately failing. "Atomic grouping"
+(a term taken from Jeffrey Friedl's book) provides the means for specifying
+that once a group has matched, it is not to be re-evaluated in this way.
+.P
+If we use atomic grouping for the previous example, the matcher gives up
+immediately on failing to match "foo" the first time. The notation is a kind of
+special parenthesis, starting with (?> as in this example:
+.sp
+ (?>\ed+)foo
+.sp
+Perl 5.28 introduced an experimental alphabetic form starting with (* which may
+be easier to remember:
+.sp
+ (*atomic:\ed+)foo
+.sp
+This kind of parenthesized group "locks up" the part of the pattern it contains
+once it has matched, and a failure further into the pattern is prevented from
+backtracking into it. Backtracking past it to previous items, however, works as
+normal.
+.P
+An alternative description is that a group of this type matches exactly the
+string of characters that an identical standalone pattern would match, if
+anchored at the current point in the subject string.
+.P
+Atomic groups are not capture groups. Simple cases such as the above example
+can be thought of as a maximizing repeat that must swallow everything it can.
+So, while both \ed+ and \ed+? are prepared to adjust the number of digits they
+match in order to make the rest of the pattern match, (?>\ed+) can only match
+an entire sequence of digits.
+.P
+Atomic groups in general can of course contain arbitrarily complicated
+expressions, and can be nested. However, when the contents of an atomic
+group is just a single repeated item, as in the example above, a simpler
+notation, called a "possessive quantifier" can be used. This consists of an
+additional + character following a quantifier. Using this notation, the
+previous example can be rewritten as
+.sp
+ \ed++foo
+.sp
+Note that a possessive quantifier can be used with an entire group, for
+example:
+.sp
+ (abc|xyz){2,3}+
+.sp
+Possessive quantifiers are always greedy; the setting of the PCRE2_UNGREEDY
+option is ignored. They are a convenient notation for the simpler forms of
+atomic group. However, there is no difference in the meaning of a possessive
+quantifier and the equivalent atomic group, though there may be a performance
+difference; possessive quantifiers should be slightly faster.
+.P
+The possessive quantifier syntax is an extension to the Perl 5.8 syntax.
+Jeffrey Friedl originated the idea (and the name) in the first edition of his
+book. Mike McCloskey liked it, so implemented it when he built Sun's Java
+package, and PCRE1 copied it from there. It found its way into Perl at release
+5.10.
+.P
+PCRE2 has an optimization that automatically "possessifies" certain simple
+pattern constructs. For example, the sequence A+B is treated as A++B because
+there is no point in backtracking into a sequence of A's when B must follow.
+This feature can be disabled by the PCRE2_NO_AUTO_POSSESS option, by calling
+\fBpcre2_set_optimize()\fP with a PCRE2_AUTO_POSSESS_OFF directive, or by
+starting the pattern with (*NO_AUTO_POSSESS).
+.P
+When a pattern contains an unlimited repeat inside a group that can itself be
+repeated an unlimited number of times, the use of an atomic group is the only
+way to avoid some failing matches taking a very long time indeed. The pattern
+.sp
+ (\eD+|<\ed+>)*[!?]
+.sp
+matches an unlimited number of substrings that either consist of non-digits, or
+digits enclosed in <>, followed by either ! or ?. When it matches, it runs
+quickly. However, if it is applied to
+.sp
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+.sp
+it takes a long time before reporting failure. This is because the string can
+be divided between the internal \eD+ repeat and the external * repeat in a
+large number of ways, and all have to be tried. (The example uses [!?] rather
+than a single character at the end, because both PCRE2 and Perl have an
+optimization that allows for fast failure when a single character is used. They
+remember the last single character that is required for a match, and fail early
+if it is not present in the string.) If the pattern is changed so that it uses
+an atomic group, like this:
+.sp
+ ((?>\eD+)|<\ed+>)*[!?]
+.sp
+sequences of non-digits cannot be broken, and failure happens quickly.
+.
+.
+.\" HTML
+.SH "BACKREFERENCES"
+.rs
+.sp
+Outside a character class, a backslash followed by a digit greater than 0 (and
+possibly further digits) is a backreference to a capture group earlier (that
+is, to its left) in the pattern, provided there have been that many previous
+capture groups.
+.P
+However, if the decimal number following the backslash is less than 8, it is
+always taken as a backreference, and causes an error only if there are not that
+many capture groups in the entire pattern. In other words, the group that is
+referenced need not be to the left of the reference for numbers less than 8. A
+"forward backreference" of this type can make sense when a repetition is
+involved and the group to the right has participated in an earlier iteration.
+.P
+It is not possible to have a numerical "forward backreference" to a group whose
+number is 8 or more using this syntax because a sequence such as \e50 is
+interpreted as a character defined in octal. See the subsection entitled
+"Non-printing characters"
+.\" HTML
+.\"
+above
+.\"
+for further details of the handling of digits following a backslash. Other
+forms of backreferencing do not suffer from this restriction. In particular,
+there is no problem when named capture groups are used (see below).
+.P
+Another way of avoiding the ambiguity inherent in the use of digits following a
+backslash is to use the \eg escape sequence. This escape must be followed by a
+signed or unsigned number, optionally enclosed in braces. These examples are
+all identical:
+.sp
+ (ring), \e1
+ (ring), \eg1
+ (ring), \eg{1}
+.sp
+An unsigned number specifies an absolute reference without the ambiguity that
+is present in the older syntax. It is also useful when literal digits follow
+the reference. A signed number is a relative reference. Consider this example:
+.sp
+ (abc(def)ghi)\eg{-1}
+.sp
+The sequence \eg{-1} is a reference to the capture group whose number is one
+less than the number of the next group to be started, so in this example (where
+the next group would be numbered 3) is it equivalent to \e2, and \eg{-2} would
+be equivalent to \e1. Note that if this construct is inside a capture group,
+that group is included in the count, so in this example \eg{-2} also refers to
+group 1:
+.sp
+ (A)(\eg{-2}B)
+.sp
+The use of relative references can be helpful in long patterns, and also in
+patterns that are created by joining together fragments that contain references
+within themselves.
+.P
+The sequence \eg{+1} is a reference to the next capture group that is started
+after this item, and \eg{+2} refers to the one after that, and so on. This kind
+of forward reference can be useful in patterns that repeat. Perl does not
+support the use of + in this way.
+.P
+A backreference matches whatever actually most recently matched the capture
+group in the current subject string, rather than anything at all that matches
+the group (see
+.\" HTML
+.\"
+"Groups as subroutines"
+.\"
+below for a way of doing that). So the pattern
+.sp
+ (sens|respons)e and \e1ibility
+.sp
+matches "sense and sensibility" and "response and responsibility", but not
+"sense and responsibility". If caseful matching is in force at the time of the
+backreference, the case of letters is relevant. For example,
+.sp
+ ((?i)rah)\es+\e1
+.sp
+matches "rah rah" and "RAH RAH", but not "RAH rah", even though the original
+capture group is matched caselessly.
+.P
+There are several different ways of writing backreferences to named capture
+groups. The .NET syntax is \ek{name}, the Python syntax is (?=name), and the
+original Perl syntax is \ek or \ek'name'. All of these are now supported
+by both Perl and PCRE2. Perl 5.10's unified backreference syntax, in which \eg
+can be used for both numeric and named references, is also supported by PCRE2.
+We could rewrite the above example in any of the following ways:
+.sp
+ (?(?i)rah)\es+\ek
+ (?'p1'(?i)rah)\es+\ek{p1}
+ (?P(?i)rah)\es+(?P=p1)
+ (?(?i)rah)\es+\eg{p1}
+.sp
+A capture group that is referenced by name may appear in the pattern before or
+after the reference.
+.P
+There may be more than one backreference to the same group. If a group has not
+actually been used in a particular match, backreferences to it always fail by
+default. For example, the pattern
+.sp
+ (a|(bc))\e2
+.sp
+always fails if it starts to match "a" rather than "bc". However, if the
+PCRE2_MATCH_UNSET_BACKREF option is set at compile time, a backreference to an
+unset value matches an empty string.
+.P
+Because there may be many capture groups in a pattern, all digits following a
+backslash are taken as part of a potential backreference number. If the pattern
+continues with a digit character, some delimiter must be used to terminate the
+backreference. If the PCRE2_EXTENDED or PCRE2_EXTENDED_MORE option is set, this
+can be white space. Otherwise, the \eg{} syntax or an empty comment (see
+.\" HTML
+.\"
+"Comments"
+.\"
+below) can be used.
+.
+.
+.SS "Recursive backreferences"
+.rs
+.sp
+A backreference that occurs inside the group to which it refers fails when the
+group is first used, so, for example, (a\e1) never matches. However, such
+references can be useful inside repeated groups. For example, the pattern
+.sp
+ (a|b\e1)+
+.sp
+matches any number of "a"s and also "aba", "ababbaa" etc. At each iteration of
+the group, the backreference matches the character string corresponding to the
+previous iteration. In order for this to work, the pattern must be such that
+the first iteration does not need to match the backreference. This can be done
+using alternation, as in the example above, or by a quantifier with a minimum
+of zero.
+.P
+For versions of PCRE2 less than 10.25, backreferences of this type used to
+cause the group that they reference to be treated as an
+.\" HTML
+.\"
+atomic group.
+.\"
+This restriction no longer applies, and backtracking into such groups can occur
+as normal.
+.
+.
+.\" HTML
+.SH ASSERTIONS
+.rs
+.sp
+An assertion is a test that does not consume any characters. The test must
+succeed for the match to continue. The simple assertions coded as \eb, \eB,
+\eA, \eG, \eZ, \ez, ^ and $ are described
+.\" HTML
+.\"
+above.
+.\"
+.P
+More complicated assertions are coded as parenthesized groups. If matching such
+a group succeeds, matching continues after it, but with the matching position
+in the subject string reset to what it was before the assertion was processed.
+.P
+A special kind of assertion, called a "scan substring" assertion, matches a
+subpattern against a previously captured substring. This is described in the
+section entitled
+.\" HTML
+.\"
+"Scan substring assertions"
+.\"
+below. It is a PCRE2 extension, not compatible with Perl.
+.P
+The other goup-based assertions are of two kinds: those that look ahead of the
+current position in the subject string, and those that look behind it, and in
+each case an assertion may be positive (must match for the assertion to be
+true) or negative (must not match for the assertion to be true).
+.P
+The Perl-compatible lookaround assertions are atomic. If an assertion is true,
+but there is a subsequent matching failure, there is no backtracking into the
+assertion. However, there are some cases where non-atomic assertions can be
+useful. PCRE2 has some support for these, described in the section entitled
+.\" HTML
+.\"
+"Non-atomic assertions"
+.\"
+below, but they are not Perl-compatible.
+.P
+A lookaround assertion may appear as the condition in a
+.\" HTML
+.\"
+conditional group
+.\"
+(see below). In this case, the result of matching the assertion determines
+which branch of the condition is followed.
+.P
+Assertion groups are not capture groups. If an assertion contains capture
+groups within it, these are counted for the purposes of numbering the capture
+groups in the whole pattern. Within each branch of an assertion, locally
+captured substrings may be referenced in the usual way. For example, a sequence
+such as (.)\eg{-1} can be used to check that two adjacent characters are the
+same.
+.P
+When a branch within an assertion fails to match, any substrings that were
+captured are discarded (as happens with any pattern branch that fails to
+match). A negative assertion is true only when all its branches fail to match;
+this means that no captured substrings are ever retained after a successful
+negative assertion. When an assertion contains a matching branch, what happens
+depends on the type of assertion.
+.P
+For a positive assertion, internally captured substrings in the successful
+branch are retained, and matching continues with the next pattern item after
+the assertion. For a negative assertion, a matching branch means that the
+assertion is not true. If such an assertion is being used as a condition in a
+.\" HTML
+.\"
+conditional group
+.\"
+(see below), captured substrings are retained, because matching continues with
+the "no" branch of the condition. For other failing negative assertions,
+control passes to the previous backtracking point, thus discarding any captured
+strings within the assertion.
+.P
+Most assertion groups may be repeated; though it makes no sense to assert the
+same thing several times, the side effect of capturing in positive assertions
+may occasionally be useful. However, an assertion that forms the condition for
+a conditional group may not be quantified. PCRE2 used to restrict the
+repetition of assertions, but from release 10.35 the only restriction is that
+an unlimited maximum repetition is changed to be one more than the minimum. For
+example, {3,} is treated as {3,4}.
+.
+.
+.SS "Alphabetic assertion names"
+.rs
+.sp
+Traditionally, symbolic sequences such as (?= and (?<= have been used to
+specify lookaround assertions. Perl 5.28 introduced some experimental
+alphabetic alternatives which might be easier to remember. They all start with
+(* instead of (? and must be written using lower case letters. PCRE2 supports
+the following synonyms:
+.sp
+ (*positive_lookahead: or (*pla: is the same as (?=
+ (*negative_lookahead: or (*nla: is the same as (?!
+ (*positive_lookbehind: or (*plb: is the same as (?<=
+ (*negative_lookbehind: or (*nlb: is the same as (?
+.SS "Lookbehind assertions"
+.rs
+.sp
+Lookbehind assertions start with (?<= for positive assertions and (?
+.\"
+(see above)
+.\"
+can be used instead of a lookbehind assertion at the start of a pattern to get
+round the length limit restriction.
+.P
+In UTF-8 and UTF-16 modes, PCRE2 does not allow the \eC escape (which matches a
+single code unit even in a UTF mode) to appear in lookbehind assertions,
+because it makes it impossible to calculate the length of the lookbehind. The
+\eX and \eR escapes, which can match different numbers of code units, are never
+permitted in lookbehinds.
+.P
+.\" HTML
+.\"
+"Subroutine"
+.\"
+calls (see below) such as (?2) or (?&X) are permitted in lookbehinds, as long
+as the called capture group matches a limited-length string. However,
+.\" HTML
+.\"
+recursion,
+.\"
+that is, a "subroutine" call into a group that is already active,
+is not supported.
+.P
+PCRE2 supports backreferences in lookbehinds, but only if certain conditions
+are met. The PCRE2_MATCH_UNSET_BACKREF option must not be set, there must be no
+use of (?| in the pattern (it creates duplicate group numbers), and if the
+backreference is by name, the name must be unique. Of course, the referenced
+group must itself match a limited length substring. The following pattern
+matches words containing at least two characters that begin and end with the
+same character:
+.sp
+ \eb(\ew)\ew++(?<=\e1)
+.P
+Possessive quantifiers can be used in conjunction with lookbehind assertions to
+specify efficient matching at the end of subject strings. Consider a simple
+pattern such as
+.sp
+ abcd$
+.sp
+when applied to a long string that does not match. Because matching proceeds
+from left to right, PCRE2 will look for each "a" in the subject and then see if
+what follows matches the rest of the pattern. If the pattern is specified as
+.sp
+ ^.*abcd$
+.sp
+the initial .* matches the entire string at first, but when this fails (because
+there is no following "a"), it backtracks to match all but the last character,
+then all but the last two characters, and so on. Once again the search for "a"
+covers the entire string, from right to left, so we are no better off. However,
+if the pattern is written as
+.sp
+ ^.*+(?<=abcd)
+.sp
+there can be no backtracking for the .*+ item because of the possessive
+quantifier; it can match only the entire string. The subsequent lookbehind
+assertion does a single test on the last four characters. If it fails, the
+match fails immediately. For long strings, this approach makes a significant
+difference to the processing time.
+.
+.
+.SS "Using multiple assertions"
+.rs
+.sp
+Several assertions (of any sort) may occur in succession. For example,
+.sp
+ (?<=\ed{3})(?
+.SH "NON-ATOMIC ASSERTIONS"
+.rs
+.sp
+Traditional lookaround assertions are atomic. That is, if an assertion is true,
+but there is a subsequent matching failure, there is no backtracking into the
+assertion. However, there are some cases where non-atomic positive assertions
+can be useful. PCRE2 provides these using the following syntax:
+.sp
+ (*non_atomic_positive_lookahead: or (*napla: or (?*
+ (*non_atomic_positive_lookbehind: or (*naplb: or (?<*
+.sp
+Consider the problem of finding the right-most word in a string that also
+appears earlier in the string, that is, it must appear at least twice in total.
+This pattern returns the required result as captured substring 1:
+.sp
+ ^(?x)(*napla: .* \eb(\ew++)) (?> .*? \eb\e1\eb ){2}
+.sp
+For a subject such as "word1 word2 word3 word2 word3 word4" the result is
+"word3". How does it work? At the start, ^(?x) anchors the pattern and sets the
+"x" option, which causes white space (introduced for readability) to be
+ignored. Inside the assertion, the greedy .* at first consumes the entire
+string, but then has to backtrack until the rest of the assertion can match a
+word, which is captured by group 1. In other words, when the assertion first
+succeeds, it captures the right-most word in the string.
+.P
+The current matching point is then reset to the start of the subject, and the
+rest of the pattern match checks for two occurrences of the captured word,
+using an ungreedy .*? to scan from the left. If this succeeds, we are done, but
+if the last word in the string does not occur twice, this part of the pattern
+fails. If a traditional atomic lookahead (?= or (*pla: had been used, the
+assertion could not be re-entered, and the whole match would fail. The pattern
+would succeed only if the very last word in the subject was found twice.
+.P
+Using a non-atomic lookahead, however, means that when the last word does not
+occur twice in the string, the lookahead can backtrack and find the second-last
+word, and so on, until either the match succeeds, or all words have been
+tested.
+.P
+Two conditions must be met for a non-atomic assertion to be useful: the
+contents of one or more capturing groups must change after a backtrack into the
+assertion, and there must be a backreference to a changed group later in the
+pattern. If this is not the case, the rest of the pattern match fails exactly
+as before because nothing has changed, so using a non-atomic assertion just
+wastes resources.
+.P
+There is one exception to backtracking into a non-atomic assertion. If an
+(*ACCEPT) control verb is triggered, the assertion succeeds atomically. That
+is, a subsequent match failure cannot backtrack into the assertion.
+.P
+Non-atomic assertions are not supported by the alternative matching function
+\fBpcre2_dfa_match()\fP. They are supported by JIT, but only if they do not
+contain any control verbs such as (*ACCEPT). (This may change in future). Note
+that assertions that appear as conditions for
+.\" HTML
+.\"
+conditional groups
+.\"
+(see below) must be atomic.
+.
+.
+.\" HTML
+.SH "SCAN SUBSTRING ASSERTIONS"
+.rs
+.sp
+A special kind of assertion, not compatible with Perl, makes it possible to
+check the contents of a captured substring by matching it with a subpattern.
+Because this involves capturing, this feature is not supported by
+\fBpcre2_dfa_match()\fP.
+.P
+A scan substring assertion starts with the sequence (*scan_substring: or
+(*scs: which is followed by a list of substring numbers (absolute or relative)
+and/or substring names enclosed in single quotes or angle brackets, all within
+parentheses. The rest of the item is the subpattern that is applied to the
+substring, as shown in these examples:
+.sp
+ (*scan_substring:(1)...)
+ (*scs:(-2)...)
+ (*scs:('AB')...)
+ (*scs:(1,'AB',-2)...)
+.sp
+The list of groups is checked in the order they are given, and it is the
+contents of the first one that is found to be set that are scanned. When
+PCRE2_DUPNAMES is set and there are ambiguous group names, all groups with the
+same name are checked in numerical order. A scan substring assertion fails if
+none of the groups it references have been set.
+.P
+The pattern match on the substring is always anchored, that is, it must match
+from the start of the substring. There is no "bumpalong" if it does not match
+at the start. The end of the subject is temporarily reset to be the end of the
+substring, so \eZ, \ez, and $ will match there. However, the start of the
+subject is \fInot\fP reset. This means that ^ matches only if the substring is
+actually at the start of the main subject, but it also means that lookbehind
+assertions into what precedes the substring are possible.
+.P
+Here is a very simple example: find a word that contains the rare (in English)
+sequence of letters "rh" not at the start:
+.sp
+ \eb(\ew++)(*scs:(1).+rh)
+.sp
+The first group captures a word which is then scanned by the second group.
+This example does not actually need this heavyweight feature; the same match
+can be achieved with:
+.sp
+ \eb\ew+?rh\ew*\eb
+.sp
+When things are more complicated, however, scanning a captured substring can be
+a useful way to describe the required match. For exmple, there is a rather
+complicated pattern in the PCRE2 test data that checks an entire subject string
+for a palindrome, that is, the sequence of letters is the same in both
+directions. Suppose you want to search for individual words of two or more
+characters such as "level" that are palindromes:
+.sp
+ (\eb\ew{2,}+\eb)(*scs:(1)...palindrome-matching-pattern...)
+.sp
+Within a substring scanning subpattern, references to other groups work as
+normal. Capturing groups may appear, and will retain their values during
+ongoing matching if the assertion succeeds.
+.
+.
+.SH "SCRIPT RUNS"
+.rs
+.sp
+In concept, a script run is a sequence of characters that are all from the same
+Unicode script such as Latin or Greek. However, because some scripts are
+commonly used together, and because some diacritical and other marks are used
+with multiple scripts, it is not that simple. There is a full description of
+the rules that PCRE2 uses in the section entitled
+.\" HTML
+.\"
+"Script Runs"
+.\"
+in the
+.\" HREF
+\fBpcre2unicode\fP
+.\"
+documentation.
+.P
+If part of a pattern is enclosed between (*script_run: or (*sr: and a closing
+parenthesis, it fails if the sequence of characters that it matches are not a
+script run. After a failure, normal backtracking occurs. Script runs can be
+used to detect spoofing attacks using characters that look the same, but are
+from different scripts. The string "paypal.com" is an infamous example, where
+the letters could be a mixture of Latin and Cyrillic. This pattern ensures that
+the matched characters in a sequence of non-spaces that follow white space are
+a script run:
+.sp
+ \es+(*sr:\eS+)
+.sp
+To be sure that they are all from the Latin script (for example), a lookahead
+can be used:
+.sp
+ \es+(?=\ep{Latin})(*sr:\eS+)
+.sp
+This works as long as the first character is expected to be a character in that
+script, and not (for example) punctuation, which is allowed with any script. If
+this is not the case, a more creative lookahead is needed. For example, if
+digits, underscore, and dots are permitted at the start:
+.sp
+ \es+(?=[0-9_.]*\ep{Latin})(*sr:\eS+)
+.sp
+.P
+In many cases, backtracking into a script run pattern fragment is not
+desirable. The script run can employ an atomic group to prevent this. Because
+this is a common requirement, a shorthand notation is provided by
+(*atomic_script_run: or (*asr:
+.sp
+ (*asr:...) is the same as (*sr:(?>...))
+.sp
+Note that the atomic group is inside the script run. Putting it outside would
+not prevent backtracking into the script run pattern.
+.P
+Support for script runs is not available if PCRE2 is compiled without Unicode
+support. A compile-time error is given if any of the above constructs is
+encountered. Script runs are not supported by the alternate matching function,
+\fBpcre2_dfa_match()\fP because they use the same mechanism as capturing
+parentheses.
+.P
+\fBWarning:\fP The (*ACCEPT) control verb
+.\" HTML
+.\"
+(see below)
+.\"
+should not be used within a script run group, because it causes an immediate
+exit from the group, bypassing the script run checking.
+.
+.
+.\" HTML
+.SH "CONDITIONAL GROUPS"
+.rs
+.sp
+It is possible to cause the matching process to obey a pattern fragment
+conditionally or to choose between two alternative fragments, depending on
+the result of an assertion, or whether a specific capture group has
+already been matched. The two possible forms of conditional group are:
+.sp
+ (?(condition)yes-pattern)
+ (?(condition)yes-pattern|no-pattern)
+.sp
+If the condition is satisfied, the yes-pattern is used; otherwise the
+no-pattern (if present) is used. An absent no-pattern is equivalent to an empty
+string (it always matches). If there are more than two alternatives in the
+group, a compile-time error occurs. Each of the two alternatives may itself
+contain nested groups of any form, including conditional groups; the
+restriction to two alternatives applies only at the level of the condition
+itself. This pattern fragment is an example where the alternatives are complex:
+.sp
+ (?(1) (A|B|C) | (D | (?(2)E|F) | E) )
+.sp
+.P
+There are five kinds of condition: references to capture groups, references to
+recursion, two pseudo-conditions called DEFINE and VERSION, and assertions.
+.
+.
+.SS "Checking for a used capture group by number"
+.rs
+.sp
+If the text between the parentheses consists of a sequence of digits, the
+condition is true if a capture group of that number has previously matched. If
+there is more than one capture group with the same number (see the earlier
+.\"
+.\" HTML
+.\"
+section about duplicate group numbers),
+.\"
+the condition is true if any of them have matched. An alternative notation,
+which is a PCRE2 extension, not supported by Perl, is to precede the digits
+with a plus or minus sign. In this case, the group number is relative rather
+than absolute. The most recently opened capture group (which could be enclosing
+this condition) can be referenced by (?(-1), the next most recent by (?(-2),
+and so on. Inside loops it can also make sense to refer to subsequent groups.
+The next capture group to be opened can be referenced as (?(+1), and so on. The
+value zero in any of these forms is not used; it provokes a compile-time error.
+.P
+Consider the following pattern, which contains non-significant white space to
+make it more readable (assume the PCRE2_EXTENDED option) and to divide it into
+three parts for ease of discussion:
+.sp
+ ( \e( )? [^()]+ (?(1) \e) )
+.sp
+The first part matches an optional opening parenthesis, and if that
+character is present, sets it as the first captured substring. The second part
+matches one or more characters that are not parentheses. The third part is a
+conditional group that tests whether or not the first capture group
+matched. If it did, that is, if subject started with an opening parenthesis,
+the condition is true, and so the yes-pattern is executed and a closing
+parenthesis is required. Otherwise, since no-pattern is not present, the
+conditional group matches nothing. In other words, this pattern matches a
+sequence of non-parentheses, optionally enclosed in parentheses.
+.P
+If you were embedding this pattern in a larger one, you could use a relative
+reference:
+.sp
+ ...other stuff... ( \e( )? [^()]+ (?(-1) \e) ) ...
+.sp
+This makes the fragment independent of the parentheses in the larger pattern.
+.
+.
+.SS "Checking for a used capture group by name"
+.rs
+.sp
+Perl uses the syntax (?()...) or (?('name')...) to test for a used
+capture group by name. For compatibility with earlier versions of PCRE1, which
+had this facility before Perl, the syntax (?(name)...) is also recognized.
+Note, however, that undelimited names consisting of the letter R followed by
+digits are ambiguous (see the following section). Rewriting the above example
+to use a named group gives this:
+.sp
+ (? \e( )? [^()]+ (?() \e) )
+.sp
+If the name used in a condition of this kind is a duplicate, the test is
+applied to all groups of the same name, and is true if any one of them has
+matched.
+.
+.
+.SS "Checking for pattern recursion"
+.rs
+.sp
+"Recursion" in this sense refers to any subroutine-like call from one part of
+the pattern to another, whether or not it is actually recursive. See the
+sections entitled
+.\" HTML
+.\"
+"Recursive patterns"
+.\"
+and
+.\" HTML
+.\"
+"Groups as subroutines"
+.\"
+below for details of recursion and subroutine calls.
+.P
+If a condition is the string (R), and there is no capture group with the name
+R, the condition is true if matching is currently in a recursion or subroutine
+call to the whole pattern or any capture group. If digits follow the letter R,
+and there is no group with that name, the condition is true if the most recent
+call is into a group with the given number, which must exist somewhere in the
+overall pattern. This is a contrived example that is equivalent to a+b:
+.sp
+ ((?(R1)a+|(?1)b))
+.sp
+However, in both cases, if there is a capture group with a matching name, the
+condition tests for its being set, as described in the section above, instead
+of testing for recursion. For example, creating a group with the name R1 by
+adding (?) to the above pattern completely changes its meaning.
+.P
+If a name preceded by ampersand follows the letter R, for example:
+.sp
+ (?(R&name)...)
+.sp
+the condition is true if the most recent recursion is into a group of that name
+(which must exist within the pattern).
+.P
+This condition does not check the entire recursion stack. It tests only the
+current level. If the name used in a condition of this kind is a duplicate, the
+test is applied to all groups of the same name, and is true if any one of
+them is the most recent recursion.
+.P
+At "top level", all these recursion test conditions are false.
+.
+.
+.\" HTML
+.SS "Defining capture groups for use by reference only"
+.rs
+.sp
+If the condition is the string (DEFINE), the condition is always false, even if
+there is a group with the name DEFINE. In this case, there may be only one
+alternative in the rest of the conditional group. It is always skipped if
+control reaches this point in the pattern; the idea of DEFINE is that it can be
+used to define subroutines that can be referenced from elsewhere. (The use of
+.\" HTML
+.\"
+subroutines
+.\"
+is described below.) For example, a pattern to match an IPv4 address such as
+"192.168.23.245" could be written like this (ignore white space and line
+breaks):
+.sp
+ (?(DEFINE) (? 2[0-4]\ed | 25[0-5] | 1\ed\ed | [1-9]?\ed) )
+ \eb (?&byte) (\e.(?&byte)){3} \eb
+.sp
+The first part of the pattern is a DEFINE group inside which another group
+named "byte" is defined. This matches an individual component of an IPv4
+address (a number less than 256). When matching takes place, this part of the
+pattern is skipped because DEFINE acts like a false condition. The rest of the
+pattern uses references to the named group to match the four dot-separated
+components of an IPv4 address, insisting on a word boundary at each end.
+.
+.
+.SS "Checking the PCRE2 version"
+.rs
+.sp
+Programs that link with a PCRE2 library can check the version by calling
+\fBpcre2_config()\fP with appropriate arguments. Users of applications that do
+not have access to the underlying code cannot do this. A special "condition"
+called VERSION exists to allow such users to discover which version of PCRE2
+they are dealing with by using this condition to match a string such as
+"yesno". VERSION must be followed either by "=" or ">=" and a version number.
+For example:
+.sp
+ (?(VERSION>=10.4)yes|no)
+.sp
+This pattern matches "yes" if the PCRE2 version is greater or equal to 10.4, or
+"no" otherwise. The fractional part of the version number could be ommited.
+.
+.
+.SS "Assertion conditions"
+.rs
+.sp
+If the condition is not in any of the above formats, it must be a parenthesized
+assertion. This may be a positive or negative lookahead or lookbehind
+assertion. However, it must be a traditional atomic assertion, not one of the
+.\" HTML
+.\"
+non-atomic assertions.
+.\"
+.P
+Consider this pattern, again containing non-significant white space, and with
+the two alternatives on the second line:
+.sp
+ (?(?=[^a-z]*[a-z])
+ \ed{2}-[a-z]{3}-\ed{2} | \ed{2}-\ed{2}-\ed{2} )
+.sp
+The condition is a positive lookahead assertion that matches an optional
+sequence of non-letters followed by a letter. In other words, it tests for the
+presence of at least one letter in the subject. If a letter is found, the
+subject is matched against the first alternative; otherwise it is matched
+against the second. This pattern matches strings in one of the two forms
+dd-aaa-dd or dd-dd-dd, where aaa are letters and dd are digits.
+.P
+When an assertion that is a condition contains capture groups, any
+capturing that occurs in a matching branch is retained afterwards, for both
+positive and negative assertions, because matching always continues after the
+assertion, whether it succeeds or fails. (Compare non-conditional assertions,
+for which captures are retained only for positive assertions that succeed.)
+.
+.
+.\" HTML
+.SH COMMENTS
+.rs
+.sp
+There are two ways of including comments in patterns that are processed by
+PCRE2. In both cases, the start of the comment must not be in a character
+class, nor in the middle of any other sequence of related characters such as
+(?: or a group name or number or a Unicode property name. The characters that
+make up a comment play no part in the pattern matching.
+.P
+The sequence (?# marks the start of a comment that continues up to the next
+closing parenthesis. Nested parentheses are not permitted. If the
+PCRE2_EXTENDED or PCRE2_EXTENDED_MORE option is set, an unescaped # character
+also introduces a comment, which in this case continues to immediately after
+the next newline character or character sequence in the pattern. Which
+characters are interpreted as newlines is controlled by an option passed to the
+compiling function or by a special sequence at the start of the pattern, as
+described in the section entitled
+.\" HTML
+.\"
+"Newline conventions"
+.\"
+above. Note that the end of this type of comment is a literal newline sequence
+in the pattern; escape sequences that happen to represent a newline do not
+count. For example, consider this pattern when PCRE2_EXTENDED is set, and the
+default newline convention (a single linefeed character) is in force:
+.sp
+ abc #comment \en still comment
+.sp
+On encountering the # character, \fBpcre2_compile()\fP skips along, looking for
+a newline in the pattern. The sequence \en is still literal at this stage, so
+it does not terminate the comment. Only an actual character with the code value
+0x0a (the default newline) does so.
+.
+.
+.\" HTML
+.SH "RECURSIVE PATTERNS"
+.rs
+.sp
+Consider the problem of matching a string in parentheses, allowing for
+unlimited nested parentheses. Without the use of recursion, the best that can
+be done is to use a pattern that matches up to some fixed depth of nesting. It
+is not possible to handle an arbitrary nesting depth.
+.P
+For some time, Perl has provided a facility that allows regular expressions to
+recurse (amongst other things). It does this by interpolating Perl code in the
+expression at run time, and the code can refer to the expression itself. A Perl
+pattern using code interpolation to solve the parentheses problem can be
+created like this:
+.sp
+ $re = qr{\e( (?: (?>[^()]+) | (?p{$re}) )* \e)}x;
+.sp
+The (?p{...}) item interpolates Perl code at run time, and in this case refers
+recursively to the pattern in which it appears.
+.P
+Obviously, PCRE2 cannot support the interpolation of Perl code. Instead, it
+supports special syntax for recursion of the entire pattern, and also for
+individual capture group recursion. After its introduction in PCRE1 and Python,
+this kind of recursion was subsequently introduced into Perl at release 5.10.
+.P
+A special item that consists of (? followed by a number greater than zero and a
+closing parenthesis is a recursive subroutine call of the capture group of the
+given number, provided that it occurs inside that group. (If not, it is a
+.\" HTML
+.\"
+non-recursive subroutine
+.\"
+call, which is described in the next section.) The special item (?R) or (?0) is
+a recursive call of the entire regular expression.
+.P
+This PCRE2 pattern solves the nested parentheses problem (assume the
+PCRE2_EXTENDED option is set so that white space is ignored):
+.sp
+ \e( ( [^()]++ | (?R) )* \e)
+.sp
+First it matches an opening parenthesis. Then it matches any number of
+substrings which can either be a sequence of non-parentheses, or a recursive
+match of the pattern itself (that is, a correctly parenthesized substring).
+Finally there is a closing parenthesis. Note the use of a possessive quantifier
+to avoid backtracking into sequences of non-parentheses.
+.P
+If this were part of a larger pattern, you would not want to recurse the entire
+pattern, so instead you could use this:
+.sp
+ ( \e( ( [^()]++ | (?1) )* \e) )
+.sp
+We have put the pattern into parentheses, and caused the recursion to refer to
+them instead of the whole pattern.
+.P
+In a larger pattern, keeping track of parenthesis numbers can be tricky. This
+is made easier by the use of relative references. Instead of (?1) in the
+pattern above you can write (?-2) to refer to the second most recently opened
+parentheses preceding the recursion. In other words, a negative number counts
+capturing parentheses leftwards from the point at which it is encountered.
+.P
+Be aware however, that if
+.\" HTML
+.\"
+duplicate capture group numbers
+.\"
+are in use, relative references refer to the earliest group with the
+appropriate number. Consider, for example:
+.sp
+ (?|(a)|(b)) (c) (?-2)
+.sp
+The first two capture groups (a) and (b) are both numbered 1, and group (c)
+is number 2. When the reference (?-2) is encountered, the second most recently
+opened parentheses has the number 1, but it is the first such group (the (a)
+group) to which the recursion refers. This would be the same if an absolute
+reference (?1) was used. In other words, relative references are just a
+shorthand for computing a group number.
+.P
+It is also possible to refer to subsequent capture groups, by writing
+references such as (?+2). However, these cannot be recursive because the
+reference is not inside the parentheses that are referenced. They are always
+.\" HTML
+.\"
+non-recursive subroutine
+.\"
+calls, as described in the next section.
+.P
+An alternative approach is to use named parentheses. The Perl syntax for this
+is (?&name); PCRE1's earlier syntax (?P>name) is also supported. We could
+rewrite the above example as follows:
+.sp
+ (? \e( ( [^()]++ | (?&pn) )* \e) )
+.sp
+If there is more than one group with the same name, the earliest one is
+used.
+.P
+The example pattern that we have been looking at contains nested unlimited
+repeats, and so the use of a possessive quantifier for matching strings of
+non-parentheses is important when applying the pattern to strings that do not
+match. For example, when this pattern is applied to
+.sp
+ (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
+.sp
+it yields "no match" quickly. However, if a possessive quantifier is not used,
+the match runs for a very long time indeed because there are so many different
+ways the + and * repeats can carve up the subject, and all have to be tested
+before failure can be reported.
+.P
+At the end of a match, the values of capturing parentheses are those from
+the outermost level. If you want to obtain intermediate values, a callout
+function can be used (see below and the
+.\" HREF
+\fBpcre2callout\fP
+.\"
+documentation). If the pattern above is matched against
+.sp
+ (ab(cd)ef)
+.sp
+the value for the inner capturing parentheses (numbered 2) is "ef", which is
+the last value taken on at the top level. If a capture group is not matched at
+the top level, its final captured value is unset, even if it was (temporarily)
+set at a deeper level during the matching process.
+.P
+Do not confuse the (?R) item with the condition (R), which tests for recursion.
+Consider this pattern, which matches text in angle brackets, allowing for
+arbitrary nesting. Only digits are allowed in nested brackets (that is, when
+recursing), whereas any characters are permitted at the outer level.
+.sp
+ < (?: (?(R) \ed++ | [^<>]*+) | (?R)) * >
+.sp
+In this pattern, (?(R) is the start of a conditional group, with two different
+alternatives for the recursive and non-recursive cases. The (?R) item is the
+actual recursive call.
+.
+.
+.\" HTML
+.SS "Differences in recursion processing between PCRE2 and Perl"
+.rs
+.sp
+Some former differences between PCRE2 and Perl no longer exist.
+.P
+Before release 10.30, recursion processing in PCRE2 differed from Perl in that
+a recursive subroutine call was always treated as an atomic group. That is,
+once it had matched some of the subject string, it was never re-entered, even
+if it contained untried alternatives and there was a subsequent matching
+failure. (Historical note: PCRE implemented recursion before Perl did.)
+.P
+Starting with release 10.30, recursive subroutine calls are no longer treated
+as atomic. That is, they can be re-entered to try unused alternatives if there
+is a matching failure later in the pattern. This is now compatible with the way
+Perl works. If you want a subroutine call to be atomic, you must explicitly
+enclose it in an atomic group.
+.P
+Supporting backtracking into recursions simplifies certain types of recursive
+pattern. For example, this pattern matches palindromic strings:
+.sp
+ ^((.)(?1)\e2|.?)$
+.sp
+The second branch in the group matches a single central character in the
+palindrome when there are an odd number of characters, or nothing when there
+are an even number of characters, but in order to work it has to be able to try
+the second case when the rest of the pattern match fails. If you want to match
+typical palindromic phrases, the pattern has to ignore all non-word characters,
+which can be done like this:
+.sp
+ ^\eW*+((.)\eW*+(?1)\eW*+\e2|\eW*+.?)\eW*+$
+.sp
+If run with the PCRE2_CASELESS option, this pattern matches phrases such as "A
+man, a plan, a canal: Panama!". Note the use of the possessive quantifier *+ to
+avoid backtracking into sequences of non-word characters. Without this, PCRE2
+takes a great deal longer (ten times or more) to match typical phrases, and
+Perl takes so long that you think it has gone into a loop.
+.P
+Another way in which PCRE2 and Perl used to differ in their recursion
+processing is in the handling of captured values. Formerly in Perl, when a
+group was called recursively or as a subroutine (see the next section), it
+had no access to any values that were captured outside the recursion, whereas
+in PCRE2 these values can be referenced. Consider this pattern:
+.sp
+ ^(.)(\e1|a(?2))
+.sp
+This pattern matches "bab". The first capturing parentheses match "b", then in
+the second group, when the backreference \e1 fails to match "b", the second
+alternative matches "a" and then recurses. In the recursion, \e1 does now match
+"b" and so the whole match succeeds. This match used to fail in Perl, but in
+later versions (I tried 5.024) it now works.
+.
+.
+.\" HTML
+.SS "Groups as subroutines"
+.rs
+.sp
+If the syntax for a recursive group call (either by number or by name) is used
+outside the parentheses to which it refers, it operates a bit like a subroutine
+in a programming language. More accurately, PCRE2 treats the referenced group
+as an independent subpattern which it tries to match at the current matching
+position. The called group may be defined before or after the reference. A
+numbered reference can be absolute or relative, as in these examples:
+.sp
+ (...(absolute)...)...(?2)...
+ (...(relative)...)...(?-1)...
+ (...(?+1)...(relative)...
+.sp
+An earlier example pointed out that the pattern
+.sp
+ (sens|respons)e and \e1ibility
+.sp
+matches "sense and sensibility" and "response and responsibility", but not
+"sense and responsibility". If instead the pattern
+.sp
+ (sens|respons)e and (?1)ibility
+.sp
+is used, it does match "sense and responsibility" as well as the other two
+strings. Another example is given in the discussion of DEFINE above.
+.P
+Like recursions, subroutine calls used to be treated as atomic, but this
+changed at PCRE2 release 10.30, so backtracking into subroutine calls can now
+occur. However, any capturing parentheses that are set during the subroutine
+call revert to their previous values afterwards.
+.P
+Processing options such as case-independence are fixed when a group is
+defined, so if it is used as a subroutine, such options cannot be changed for
+different calls. For example, consider this pattern:
+.sp
+ (abc)(?i:(?-1))
+.sp
+It matches "abcabc". It does not match "abcABC" because the change of
+processing option does not affect the called group.
+.P
+The behaviour of
+.\" HTML
+.\"
+backtracking control verbs
+.\"
+in groups when called as subroutines is described in the section entitled
+.\" HTML
+.\"
+"Backtracking verbs in subroutines"
+.\"
+below.
+.
+.
+.SS "Recursion and subroutines with returned capture groups"
+.rs
+.sp
+Since PCRE2 10.47, recursion and subroutine calls may also specify a list of
+capture groups to return. This is a PCRE2 syntax extension not supported by
+Perl. The pattern matching recurses into the referenced expression as described
+above, however, when the recursion returns to the calling expression the
+subgroups captured during the recursion can be retained when the calling
+expression's context is restored.
+.P
+When used as a subroutine, this allows the subroutine's capture groups to
+be used as return values.
+.P
+Only the specific capture groups listed by the caller will be retained, using
+the following syntax:
+.sp
+ (?R(grouplist)) recurse whole pattern, returning capture groups
+ (?n(grouplist)) )
+ (?+n(grouplist)) )
+ (?-n(grouplist)) ) call subroutine, returning capture groups
+ (?&name(grouplist)) )
+ (?P>name(grouplist)) )
+.P
+The list of capture groups "grouplist" is a comma-separated list of (absolute
+or relative) group numbers, and group names enclosed in single quotes or angle
+brackets.
+.P
+Here is an example which first uses the DEFINE condition to create a re-usable
+routine for matching a weekday, then calls that subroutine and retains the
+groups it captures for use later:
+.sp
+ (?x: # ignore whitespace for clarity
+ # Define the routine "weekendday" which matches Saturday or
+ # Sunday, and returns the Sat/Sun prefix as \ek.
+ (?(DEFINE) (?
+ (?|(?Sat)urday|(?Sun)day) ) )
+ # Call the routine. Matches "Saturday,Sat" or "Sunday,Sun".
+ (?&weekendday()),\ek )
+.P
+This feature is not available using the Oniguruma syntax \eg<...> or \eg'...'
+below.
+.
+.
+.\" HTML
+.SS "Oniguruma subroutine syntax"
+.rs
+.sp
+For compatibility with Oniguruma, the non-Perl syntax \eg followed by a name or
+a number enclosed either in angle brackets or single quotes, is an alternative
+syntax for calling a group as a subroutine, possibly recursively. Here are two
+of the examples used above, rewritten using this syntax:
+.sp
+ (? \e( ( (?>[^()]+) | \eg )* \e) )
+ (sens|respons)e and \eg'1'ibility
+.sp
+PCRE2 supports an extension to Oniguruma: if a number is preceded by a
+plus or a minus sign it is taken as a relative reference. For example:
+.sp
+ (abc)(?i:\eg<-1>)
+.sp
+Note that \eg{...} (Perl syntax) and \eg<...> (Oniguruma syntax) are \fInot\fP
+synonymous. The former is a backreference; the latter is a subroutine call.
+.
+.
+.SH CALLOUTS
+.rs
+.sp
+Perl has a feature whereby using the sequence (?{...}) causes arbitrary Perl
+code to be obeyed in the middle of matching a regular expression. This makes it
+possible, amongst other things, to extract different substrings that match the
+same pair of parentheses when there is a repetition.
+.P
+PCRE2 provides a similar feature, but of course it cannot obey arbitrary Perl
+code. The feature is called "callout". The caller of PCRE2 provides an external
+function by putting its entry point in a match context using the function
+\fBpcre2_set_callout()\fP, and then passing that context to \fBpcre2_match()\fP
+or \fBpcre2_dfa_match()\fP. If no match context is passed, or if the callout
+entry point is set to NULL, callout points will be passed over silently during
+matching. To disallow callouts in the pattern syntax, you may use the
+PCRE2_EXTRA_NEVER_CALLOUT option.
+.P
+Within a regular expression, (?C) indicates a point at which the external
+function is to be called. There are two kinds of callout: those with a
+numerical argument and those with a string argument. (?C) on its own with no
+argument is treated as (?C0). A numerical argument allows the application to
+distinguish between different callouts. String arguments were added for release
+10.20 to make it possible for script languages that use PCRE2 to embed short
+scripts within patterns in a similar way to Perl.
+.P
+During matching, when PCRE2 reaches a callout point, the external function is
+called. It is provided with the number or string argument of the callout, the
+position in the pattern, and one item of data that is also set in the match
+block. The callout function may cause matching to proceed, to backtrack, or to
+fail.
+.P
+By default, PCRE2 implements a number of optimizations at matching time, and
+one side-effect is that sometimes callouts are skipped. If you need all
+possible callouts to happen, you need to set options that disable the relevant
+optimizations. More details, including a complete description of the
+programming interface to the callout function, are given in the
+.\" HREF
+\fBpcre2callout\fP
+.\"
+documentation.
+.
+.
+.SS "Callouts with numerical arguments"
+.rs
+.sp
+If you just want to have a means of identifying different callout points, put a
+number less than 256 after the letter C. For example, this pattern has two
+callout points:
+.sp
+ (?C1)abc(?C2)def
+.sp
+If the PCRE2_AUTO_CALLOUT flag is passed to \fBpcre2_compile()\fP, numerical
+callouts are automatically installed before each item in the pattern. They are
+all numbered 255. If there is a conditional group in the pattern whose
+condition is an assertion, an additional callout is inserted just before the
+condition. An explicit callout may also be set at this position, as in this
+example:
+.sp
+ (?(?C9)(?=a)abc|def)
+.sp
+Note that this applies only to assertion conditions, not to other types of
+condition.
+.
+.
+.SS "Callouts with string arguments"
+.rs
+.sp
+A delimited string may be used instead of a number as a callout argument. The
+starting delimiter must be one of ` ' " ^ % # $ { and the ending delimiter is
+the same as the start, except for {, where the ending delimiter is }. If the
+ending delimiter is needed within the string, it must be doubled. For
+example:
+.sp
+ (?C'ab ''c'' d')xyz(?C{any text})pqr
+.sp
+The doubling is removed before the string is passed to the callout function.
+.
+.
+.\" HTML
+.SH "BACKTRACKING CONTROL"
+.rs
+.sp
+There are a number of special "Backtracking Control Verbs" (to use Perl's
+terminology) that modify the behaviour of backtracking during matching. They
+are generally of the form (*VERB) or (*VERB:NAME). Some verbs take either form,
+and may behave differently depending on whether or not a name argument is
+present. The names are not required to be unique within the pattern.
+.P
+By default, for compatibility with Perl, a name is any sequence of characters
+that does not include a closing parenthesis. The name is not processed in
+any way, and it is not possible to include a closing parenthesis in the name.
+This can be changed by setting the PCRE2_ALT_VERBNAMES option, but the result
+is no longer Perl-compatible.
+.P
+When PCRE2_ALT_VERBNAMES is set, backslash processing is applied to verb names
+and only an unescaped closing parenthesis terminates the name. However, the
+only backslash items that are permitted are \eQ, \eE, and sequences such as
+\ex{100} that define character code points. Character type escapes such as \ed
+are faulted.
+.P
+A closing parenthesis can be included in a name either as \e) or between \eQ
+and \eE. In addition to backslash processing, if the PCRE2_EXTENDED or
+PCRE2_EXTENDED_MORE option is also set, unescaped white space in verb names is
+skipped, and #-comments are recognized, exactly as in the rest of the pattern.
+PCRE2_EXTENDED and PCRE2_EXTENDED_MORE do not affect verb names unless
+PCRE2_ALT_VERBNAMES is also set.
+.P
+The maximum length of a name is 255 in the 8-bit library and 65535 in the
+16-bit and 32-bit libraries. If the name is empty, that is, if the closing
+parenthesis immediately follows the colon, the effect is as if the colon were
+not there. Any number of these verbs may occur in a pattern. Except for
+(*ACCEPT), they may not be quantified.
+.P
+Since these verbs are specifically related to backtracking, most of them can be
+used only when the pattern is to be matched using the traditional matching
+function or JIT, because they use backtracking algorithms. With the exception
+of (*FAIL), which behaves like a failing negative assertion, the backtracking
+control verbs cause an error if encountered by the DFA matching function.
+.P
+The behaviour of these verbs in
+.\" HTML
+.\"
+repeated groups,
+.\"
+.\" HTML
+.\"
+assertions,
+.\"
+and in
+.\" HTML
+.\"
+capture groups called as subroutines
+.\"
+(whether or not recursively) is documented below.
+.
+.
+.\" HTML
+.SS "Optimizations that affect backtracking verbs"
+.rs
+.sp
+PCRE2 contains some optimizations that are used to speed up matching by running
+some checks at the start of each match attempt. For example, it may know the
+minimum length of matching subject, or that a particular character must be
+present. When one of these optimizations bypasses the running of a match, any
+included backtracking verbs will not, of course, be processed. You can suppress
+the start-of-match optimizations by setting the PCRE2_NO_START_OPTIMIZE option
+when calling \fBpcre2_compile()\fP, by calling \fBpcre2_set_optimize()\fP with a
+PCRE2_START_OPTIMIZE_OFF directive, or by starting the pattern with
+(*NO_START_OPT). There is more discussion of this option in the section
+entitled
+.\" HTML
+.\"
+"Compiling a pattern"
+.\"
+in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation.
+.P
+Experiments with Perl suggest that it too has similar optimizations, and like
+PCRE2, turning them off can change the result of a match.
+.
+.
+.\" HTML
+.SS "Verbs that act immediately"
+.rs
+.sp
+The following verbs act as soon as they are encountered.
+.sp
+ (*ACCEPT) or (*ACCEPT:NAME)
+.sp
+This verb causes the match to end successfully, skipping the remainder of the
+pattern. However, when it is inside a capture group that is called as a
+subroutine, only that group is ended successfully. Matching then continues
+at the outer level. If (*ACCEPT) in triggered in a positive assertion, the
+assertion succeeds; in a negative assertion, the assertion fails.
+.P
+If (*ACCEPT) is inside capturing parentheses, the data so far is captured. For
+example:
+.sp
+ A((?:A|B(*ACCEPT)|C)D)
+.sp
+This matches "AB", "AAD", or "ACD"; when it matches "AB", "B" is captured by
+the outer parentheses.
+.P
+(*ACCEPT) is the only backtracking verb that is allowed to be quantified
+because an ungreedy quantification with a minimum of zero acts only when a
+backtrack happens. Consider, for example,
+.sp
+ (A(*ACCEPT)??B)C
+.sp
+where A, B, and C may be complex expressions. After matching "A", the matcher
+processes "BC"; if that fails, causing a backtrack, (*ACCEPT) is triggered and
+the match succeeds. In both cases, all but C is captured. Whereas (*COMMIT)
+(see below) means "fail on backtrack", a repeated (*ACCEPT) of this type means
+"succeed on backtrack".
+.P
+\fBWarning:\fP (*ACCEPT) should not be used within a script run group, because
+it causes an immediate exit from the group, bypassing the script run checking.
+.sp
+ (*FAIL) or (*FAIL:NAME)
+.sp
+This verb causes a matching failure, forcing backtracking to occur. It may be
+abbreviated to (*F). It is equivalent to (?!) but easier to read. The Perl
+documentation notes that it is probably useful only when combined with (?{}) or
+(??{}). Those are, of course, Perl features that are not present in PCRE2. The
+nearest equivalent is the callout feature, as for example in this pattern:
+.sp
+ a+(?C)(*FAIL)
+.sp
+A match with the string "aaaa" always fails, but the callout is taken before
+each backtrack happens (in this example, 10 times).
+.P
+(*ACCEPT:NAME) and (*FAIL:NAME) behave the same as (*MARK:NAME)(*ACCEPT) and
+(*MARK:NAME)(*FAIL), respectively, that is, a (*MARK) is recorded just before
+the verb acts.
+.
+.
+.SS "Recording which path was taken"
+.rs
+.sp
+There is one verb whose main purpose is to track how a match was arrived at,
+though it also has a secondary use in conjunction with advancing the match
+starting point (see (*SKIP) below).
+.sp
+ (*MARK:NAME) or (*:NAME)
+.sp
+A name is always required with this verb. For all the other backtracking
+control verbs, a NAME argument is optional.
+.P
+When a match succeeds, the name of the last-encountered mark name on the
+matching path is passed back to the caller as described in the section entitled
+.\" HTML
+.\"
+"Other information about the match"
+.\"
+in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation. This applies to all instances of (*MARK) and other verbs,
+including those inside assertions and atomic groups. However, there are
+differences in those cases when (*MARK) is used in conjunction with (*SKIP) as
+described below.
+.P
+The mark name that was last encountered on the matching path is passed back. A
+verb without a NAME argument is ignored for this purpose. Here is an example of
+\fBpcre2test\fP output, where the "mark" modifier requests the retrieval and
+outputting of (*MARK) data:
+.sp
+ re> /X(*MARK:A)Y|X(*MARK:B)Z/mark
+ data> XY
+ 0: XY
+ MK: A
+ XZ
+ 0: XZ
+ MK: B
+.sp
+The (*MARK) name is tagged with "MK:" in this output, and in this example it
+indicates which of the two alternatives matched. This is a more efficient way
+of obtaining this information than putting each alternative in its own
+capturing parentheses.
+.P
+If a verb with a name is encountered in a positive assertion that is true, the
+name is recorded and passed back if it is the last-encountered. This does not
+happen for negative assertions or failing positive assertions.
+.P
+After a partial match or a failed match, the last encountered name in the
+entire match process is returned. For example:
+.sp
+ re> /X(*MARK:A)Y|X(*MARK:B)Z/mark
+ data> XP
+ No match, mark = B
+.sp
+Note that in this unanchored example the mark is retained from the match
+attempt that started at the letter "X" in the subject. Subsequent match
+attempts starting at "P" and then with an empty string do not get as far as the
+(*MARK) item, but nevertheless do not reset it.
+.P
+If you are interested in (*MARK) values after failed matches, you should
+probably either set the PCRE2_NO_START_OPTIMIZE option or call
+\fBpcre2_set_optimize()\fP with a PCRE2_START_OPTIMIZE_OFF directive
+.\" HTML
+.\"
+(see above)
+.\"
+to ensure that the match is always attempted.
+.
+.
+.SS "Verbs that act after backtracking"
+.rs
+.sp
+The following verbs do nothing when they are encountered. Matching continues
+with what follows, but if there is a subsequent match failure, causing a
+backtrack to the verb, a failure is forced. That is, backtracking cannot pass
+to the left of the verb. However, when one of these verbs appears inside an
+atomic group or in an atomic lookaround assertion that is true, its effect is
+confined to that group, because once the group has been matched, there is never
+any backtracking into it. Backtracking from beyond an atomic assertion or group
+ignores the entire group, and seeks a preceding backtracking point.
+.P
+These verbs differ in exactly what kind of failure occurs when backtracking
+reaches them. The behaviour described below is what happens when the verb is
+not in a subroutine or an assertion. Subsequent sections cover these special
+cases.
+.sp
+ (*COMMIT) or (*COMMIT:NAME)
+.sp
+This verb causes the whole match to fail outright if there is a later matching
+failure that causes backtracking to reach it. Even if the pattern is
+unanchored, no further attempts to find a match by advancing the starting point
+take place. If (*COMMIT) is the only backtracking verb that is encountered,
+once it has been passed \fBpcre2_match()\fP is committed to finding a match at
+the current starting point, or not at all. For example:
+.sp
+ a+(*COMMIT)b
+.sp
+This matches "xxaab" but not "aacaab". It can be thought of as a kind of
+dynamic anchor, or "I've started, so I must finish."
+.P
+The behaviour of (*COMMIT:NAME) is not the same as (*MARK:NAME)(*COMMIT). It is
+like (*MARK:NAME) in that the name is remembered for passing back to the
+caller. However, (*SKIP:NAME) searches only for names that are set with
+(*MARK), ignoring those set by any of the other backtracking verbs.
+.P
+If there is more than one backtracking verb in a pattern, a different one that
+follows (*COMMIT) may be triggered first, so merely passing (*COMMIT) during a
+match does not always guarantee that a match must be at this starting point.
+.P
+Note that (*COMMIT) at the start of a pattern is not the same as an anchor,
+unless PCRE2's start-of-match optimizations are turned off, as shown in this
+output from \fBpcre2test\fP:
+.sp
+ re> /(*COMMIT)abc/
+ data> xyzabc
+ 0: abc
+ data>
+ re> /(*COMMIT)abc/no_start_optimize
+ data> xyzabc
+ No match
+.sp
+For the first pattern, PCRE2 knows that any match must start with "a", so the
+optimization skips along the subject to "a" before applying the pattern to the
+first set of data. The match attempt then succeeds. The second pattern disables
+the optimization that skips along to the first character. The pattern is now
+applied starting at "x", and so the (*COMMIT) causes the match to fail without
+trying any other starting points.
+.sp
+ (*PRUNE) or (*PRUNE:NAME)
+.sp
+This verb causes the match to fail at the current starting position in the
+subject if there is a later matching failure that causes backtracking to reach
+it. If the pattern is unanchored, the normal "bumpalong" advance to the next
+starting character then happens. Backtracking can occur as usual to the left of
+(*PRUNE), before it is reached, or when matching to the right of (*PRUNE), but
+if there is no match to the right, backtracking cannot cross (*PRUNE). In
+simple cases, the use of (*PRUNE) is just an alternative to an atomic group or
+possessive quantifier, but there are some uses of (*PRUNE) that cannot be
+expressed in any other way. In an anchored pattern (*PRUNE) has the same effect
+as (*COMMIT).
+.P
+The behaviour of (*PRUNE:NAME) is not the same as (*MARK:NAME)(*PRUNE). It is
+like (*MARK:NAME) in that the name is remembered for passing back to the
+caller. However, (*SKIP:NAME) searches only for names set with (*MARK),
+ignoring those set by other backtracking verbs.
+.sp
+ (*SKIP)
+.sp
+This verb, when given without a name, is like (*PRUNE), except that if the
+pattern is unanchored, the "bumpalong" advance is not to the next character,
+but to the position in the subject where (*SKIP) was encountered. (*SKIP)
+signifies that whatever text was matched leading up to it cannot be part of a
+successful match if there is a later mismatch. Consider:
+.sp
+ a+(*SKIP)b
+.sp
+If the subject is "aaaac...", after the first match attempt fails (starting at
+the first character in the string), the starting point skips on to start the
+next attempt at "c". Note that a possessive quantifier does not have the same
+effect as this example; although it would suppress backtracking during the
+first match attempt, the second attempt would start at the second character
+instead of skipping on to "c".
+.P
+If (*SKIP) is used to specify a new starting position that is the same as the
+starting position of the current match, or (by being inside a lookbehind)
+earlier, the position specified by (*SKIP) is ignored, and instead the normal
+"bumpalong" occurs.
+.sp
+ (*SKIP:NAME)
+.sp
+When (*SKIP) has an associated name, its behaviour is modified. When such a
+(*SKIP) is triggered, the previous path through the pattern is searched for the
+most recent (*MARK) that has the same name. If one is found, the "bumpalong"
+advance is to the subject position that corresponds to that (*MARK) instead of
+to where (*SKIP) was encountered. If no (*MARK) with a matching name is found,
+the (*SKIP) is ignored.
+.P
+The search for a (*MARK) name uses the normal backtracking mechanism, which
+means that it does not see (*MARK) settings that are inside atomic groups or
+assertions, because they are never re-entered by backtracking. Compare the
+following \fBpcre2test\fP examples:
+.sp
+ re> /a(?>(*MARK:X))(*SKIP:X)(*F)|(.)/
+ data: abc
+ 0: a
+ 1: a
+ data:
+ re> /a(?:(*MARK:X))(*SKIP:X)(*F)|(.)/
+ data: abc
+ 0: b
+ 1: b
+.sp
+In the first example, the (*MARK) setting is in an atomic group, so it is not
+seen when (*SKIP:X) triggers, causing the (*SKIP) to be ignored. This allows
+the second branch of the pattern to be tried at the first character position.
+In the second example, the (*MARK) setting is not in an atomic group. This
+allows (*SKIP:X) to find the (*MARK) when it backtracks, and this causes a new
+matching attempt to start at the second character. This time, the (*MARK) is
+never seen because "a" does not match "b", so the matcher immediately jumps to
+the second branch of the pattern.
+.P
+Note that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It ignores
+names that are set by other backtracking verbs.
+.sp
+ (*THEN) or (*THEN:NAME)
+.sp
+This verb causes a skip to the next innermost alternative when backtracking
+reaches it. That is, it cancels any further backtracking within the current
+alternative. Its name comes from the observation that it can be used for a
+pattern-based if-then-else block:
+.sp
+ ( COND1 (*THEN) FOO | COND2 (*THEN) BAR | COND3 (*THEN) BAZ ) ...
+.sp
+If the COND1 pattern matches, FOO is tried (and possibly further items after
+the end of the group if FOO succeeds); on failure, the matcher skips to the
+second alternative and tries COND2, without backtracking into COND1. If that
+succeeds and BAR fails, COND3 is tried. If subsequently BAZ fails, there are no
+more alternatives, so there is a backtrack to whatever came before the entire
+group. If (*THEN) is not inside an alternation, it acts like (*PRUNE).
+.P
+The behaviour of (*THEN:NAME) is not the same as (*MARK:NAME)(*THEN). It is
+like (*MARK:NAME) in that the name is remembered for passing back to the
+caller. However, (*SKIP:NAME) searches only for names set with (*MARK),
+ignoring those set by other backtracking verbs.
+.P
+A group that does not contain a | character is just a part of the enclosing
+alternative; it is not a nested alternation with only one alternative. The
+effect of (*THEN) extends beyond such a group to the enclosing alternative.
+Consider this pattern, where A, B, etc. are complex pattern fragments that do
+not contain any | characters at this level:
+.sp
+ A (B(*THEN)C) | D
+.sp
+If A and B are matched, but there is a failure in C, matching does not
+backtrack into A; instead it moves to the next alternative, that is, D.
+However, if the group containing (*THEN) is given an alternative, it
+behaves differently:
+.sp
+ A (B(*THEN)C | (*FAIL)) | D
+.sp
+The effect of (*THEN) is now confined to the inner group. After a failure in C,
+matching moves to (*FAIL), which causes the whole group to fail because there
+are no more alternatives to try. In this case, matching does backtrack into A.
+.P
+Note that a conditional group is not considered as having two alternatives,
+because only one is ever used. In other words, the | character in a conditional
+group has a different meaning. Ignoring white space, consider:
+.sp
+ ^.*? (?(?=a) a | b(*THEN)c )
+.sp
+If the subject is "ba", this pattern does not match. Because .*? is ungreedy,
+it initially matches zero characters. The condition (?=a) then fails, the
+character "b" is matched, but "c" is not. At this point, matching does not
+backtrack to .*? as might perhaps be expected from the presence of the |
+character. The conditional group is part of the single alternative that
+comprises the whole pattern, and so the match fails. (If there was a backtrack
+into .*?, allowing it to match "b", the match would succeed.)
+.P
+The verbs just described provide four different "strengths" of control when
+subsequent matching fails. (*THEN) is the weakest, carrying on the match at the
+next alternative. (*PRUNE) comes next, failing the match at the current
+starting position, but allowing an advance to the next character (for an
+unanchored pattern). (*SKIP) is similar, except that the advance may be more
+than one character. (*COMMIT) is the strongest, causing the entire match to
+fail.
+.
+.
+.SS "More than one backtracking verb"
+.rs
+.sp
+If more than one backtracking verb is present in a pattern, the one that is
+backtracked onto first acts. For example, consider this pattern, where A, B,
+etc. are complex pattern fragments:
+.sp
+ (A(*COMMIT)B(*THEN)C|ABD)
+.sp
+If A matches but B fails, the backtrack to (*COMMIT) causes the entire match to
+fail. However, if A and B match, but C fails, the backtrack to (*THEN) causes
+the next alternative (ABD) to be tried. This behaviour is consistent, but is
+not always the same as Perl's. It means that if two or more backtracking verbs
+appear in succession, all but the last of them has no effect. Consider this
+example:
+.sp
+ ...(*COMMIT)(*PRUNE)...
+.sp
+If there is a matching failure to the right, backtracking onto (*PRUNE) causes
+it to be triggered, and its action is taken. There can never be a backtrack
+onto (*COMMIT).
+.
+.
+.\" HTML
+.SS "Backtracking verbs in repeated groups"
+.rs
+.sp
+PCRE2 sometimes differs from Perl in its handling of backtracking verbs in
+repeated groups. For example, consider:
+.sp
+ /(a(*COMMIT)b)+ac/
+.sp
+If the subject is "abac", Perl matches unless its optimizations are disabled,
+but PCRE2 always fails because the (*COMMIT) in the second repeat of the group
+acts.
+.
+.
+.\" HTML
+.SS "Backtracking verbs in assertions"
+.rs
+.sp
+(*FAIL) in any assertion has its normal effect: it forces an immediate
+backtrack. The behaviour of the other backtracking verbs depends on whether or
+not the assertion is standalone or acting as the condition in a conditional
+group.
+.P
+(*ACCEPT) in a standalone positive assertion causes the assertion to succeed
+without any further processing; captured strings and a mark name (if set) are
+retained. In a standalone negative assertion, (*ACCEPT) causes the assertion to
+fail without any further processing; captured substrings and any mark name are
+discarded.
+.P
+If the assertion is a condition, (*ACCEPT) causes the condition to be true for
+a positive assertion and false for a negative one; captured substrings are
+retained in both cases.
+.P
+The remaining verbs act only when a later failure causes a backtrack to
+reach them. This means that, for the Perl-compatible assertions, their effect
+is confined to the assertion, because Perl lookaround assertions are atomic. A
+backtrack that occurs after such an assertion is complete does not jump back
+into the assertion. Note in particular that a (*MARK) name that is set in an
+assertion is not "seen" by an instance of (*SKIP:NAME) later in the pattern.
+.P
+PCRE2 now supports non-atomic positive assertions and also "scan substring"
+assertions, as described in the sections entitled
+.\" HTML
+.\"
+"Non-atomic assertions"
+.\"
+and
+.\" HTML
+.\"
+"Scan substring assertions"
+.\"
+above. These assertions must be standalone (not used as conditions). They are
+not Perl-compatible. For these assertions, a later backtrack does jump back
+into the assertion, and therefore verbs such as (*COMMIT) can be triggered by
+backtracks from later in the pattern.
+.P
+The effect of (*THEN) is not allowed to escape beyond an assertion. If there
+are no more branches to try, (*THEN) causes a positive assertion to be false,
+and a negative assertion to be true. This behaviour differs from Perl when the
+assertion has only one branch.
+.P
+The other backtracking verbs are not treated specially if they appear in a
+standalone positive assertion. In a conditional positive assertion,
+backtracking (from within the assertion) into (*COMMIT), (*SKIP), or (*PRUNE)
+causes the condition to be false. However, for both standalone and conditional
+negative assertions, backtracking into (*COMMIT), (*SKIP), or (*PRUNE) causes
+the assertion to be true, without considering any further alternative branches.
+.
+.
+.\" HTML
+.SS "Backtracking verbs in subroutines"
+.rs
+.sp
+These behaviours occur whether or not the group is called recursively.
+.P
+(*ACCEPT) in a group called as a subroutine causes the subroutine match to
+succeed without any further processing. Matching then continues after the
+subroutine call. Perl documents this behaviour. Perl's treatment of the other
+verbs in subroutines is different in some cases.
+.P
+(*FAIL) in a group called as a subroutine has its normal effect: it forces
+an immediate backtrack.
+.P
+(*COMMIT), (*SKIP), and (*PRUNE) cause the subroutine match to fail when
+triggered by being backtracked to in a group called as a subroutine. There is
+then a backtrack at the outer level.
+.P
+(*THEN), when triggered, skips to the next alternative in the innermost
+enclosing group that has alternatives (its normal behaviour). However, if there
+is no such group within the subroutine's group, the subroutine match fails and
+there is a backtrack at the outer level.
+.
+.
+.\" HTML
+.SH "EBCDIC ENVIRONMENTS"
+.rs
+.sp
+Differences in the way PCRE behaves when it is running in an EBCDIC environment
+are covered in this section.
+.
+.
+.SS "Escape sequences"
+.rs
+.sp
+When PCRE2 is compiled in EBCDIC mode, \eN{U+hhh..} is not supported. \ea, \ee,
+\ef, \en, \er, and \et generate the appropriate EBCDIC code values. The \ec
+escape is processed as specified for Perl in the \fBperlebcdic\fP document. The
+only characters that are allowed after \ec are A-Z, a-z, or one of @, [, \e, ],
+^, _, or ?. Any other character provokes a compile-time error. The sequence
+\ec@ encodes character code 0; after \ec the letters (in either case) encode
+characters 1-26 (hex 01 to hex 1A); [, \e, ], ^, and _ encode characters 27-31
+(hex 1B to hex 1F), and \ec? becomes either 255 (hex FF) or 95 (hex 5F).
+.P
+Thus, apart from \ec?, these escapes generate the same character code values as
+they do in an ASCII or Unicode environment, though the meanings of the values
+mostly differ. For example, \ecG always generates code value 7, which is BEL in
+ASCII but DEL in EBCDIC.
+.P
+The sequence \ec? generates DEL (127, hex 7F) in an ASCII environment, but
+because 127 is not a control character in EBCDIC, Perl makes it generate the
+APC character. Unfortunately, there are several variants of EBCDIC. In most of
+them the APC character has the value 255 (hex FF), but in the one Perl calls
+POSIX-BC its value is 95 (hex 5F). If certain other characters have POSIX-BC
+values, PCRE2 makes \ec? generate 95; otherwise it generates 255.
+.
+.
+.SS "Character classes"
+.rs
+.sp
+In character classes there is a special case in EBCDIC environments for ranges
+whose end points are both specified as literal letters in the same case. For
+compatibility with Perl, EBCDIC code points within the range that are not
+letters are omitted. For example, [h-k] matches only four characters, even
+though the EBCDIC codes for h and k are 0x88 and 0x92, a range of 11 code
+points. However, if the range is specified numerically, for example,
+[\ex88-\ex92] or [h-\ex92], all code points are included.
+.
+.
+.SH "SEE ALSO"
+.rs
+.sp
+\fBpcre2api\fP(3), \fBpcre2callout\fP(3), \fBpcre2matching\fP(3),
+\fBpcre2syntax\fP(3), \fBpcre2\fP(3).
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 25 October 2025
+Copyright (c) 1997-2024 University of Cambridge.
+.fi
diff --git a/doc/pcre2perform.3 b/doc/pcre2perform.3
new file mode 100644
index 0000000..bec85fe
--- /dev/null
+++ b/doc/pcre2perform.3
@@ -0,0 +1,260 @@
+.TH PCRE2PERFORM 3 "06 December 2022" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH "PCRE2 PERFORMANCE"
+.rs
+.sp
+Two aspects of performance are discussed below: memory usage and processing
+time. The way you express your pattern as a regular expression can affect both
+of them.
+.
+.SH "COMPILED PATTERN MEMORY USAGE"
+.rs
+.sp
+Patterns are compiled by PCRE2 into a reasonably efficient interpretive code,
+so that most simple patterns do not use much memory for storing the compiled
+version. However, there is one case where the memory usage of a compiled
+pattern can be unexpectedly large. If a parenthesized group has a quantifier
+with a minimum greater than 1 and/or a limited maximum, the whole group is
+repeated in the compiled code. For example, the pattern
+.sp
+ (abc|def){2,4}
+.sp
+is compiled as if it were
+.sp
+ (abc|def)(abc|def)((abc|def)(abc|def)?)?
+.sp
+(Technical aside: It is done this way so that backtrack points within each of
+the repetitions can be independently maintained.)
+.P
+For regular expressions whose quantifiers use only small numbers, this is not
+usually a problem. However, if the numbers are large, and particularly if such
+repetitions are nested, the memory usage can become an embarrassment. For
+example, the very simple pattern
+.sp
+ ((ab){1,1000}c){1,3}
+.sp
+uses over 50KiB when compiled using the 8-bit library. When PCRE2 is
+compiled with its default internal pointer size of two bytes, the size limit on
+a compiled pattern is 65535 code units in the 8-bit and 16-bit libraries, and
+this is reached with the above pattern if the outer repetition is increased
+from 3 to 4. PCRE2 can be compiled to use larger internal pointers and thus
+handle larger compiled patterns, but it is better to try to rewrite your
+pattern to use less memory if you can.
+.P
+One way of reducing the memory usage for such patterns is to make use of
+PCRE2's
+.\" HTML
+.\"
+"subroutine"
+.\"
+facility. Re-writing the above pattern as
+.sp
+ ((ab)(?2){0,999}c)(?1){0,2}
+.sp
+reduces the memory requirements to around 16KiB, and indeed it remains under
+20KiB even with the outer repetition increased to 100. However, this kind of
+pattern is not always exactly equivalent, because any captures within
+subroutine calls are lost when the subroutine completes. If this is not a
+problem, this kind of rewriting will allow you to process patterns that PCRE2
+cannot otherwise handle. The matching performance of the two different versions
+of the pattern are roughly the same. (This applies from release 10.30 - things
+were different in earlier releases.)
+.
+.
+.SH "STACK AND HEAP USAGE AT RUN TIME"
+.rs
+.sp
+From release 10.30, the interpretive (non-JIT) version of \fBpcre2_match()\fP
+uses very little system stack at run time. In earlier releases recursive
+function calls could use a great deal of stack, and this could cause problems,
+but this usage has been eliminated. Backtracking positions are now explicitly
+remembered in memory frames controlled by the code.
+.P
+The size of each frame depends on the size of pointer variables and the number
+of capturing parenthesized groups in the pattern being matched. On a 64-bit
+system the frame size for a pattern with no captures is 128 bytes. For each
+capturing group the size increases by 16 bytes.
+.P
+Until release 10.41, an initial 20KiB frames vector was allocated on the system
+stack, but this still caused some issues for multi-thread applications where
+each thread has a very small stack. From release 10.41 backtracking memory
+frames are always held in heap memory. An initial heap allocation is obtained
+the first time any match data block is passed to \fBpcre2_match()\fP. This is
+remembered with the match data block and re-used if that block is used for
+another match. It is freed when the match data block itself is freed.
+.P
+The size of the initial block is the larger of 20KiB or ten times the pattern's
+frame size, unless the heap limit is less than this, in which case the heap
+limit is used. If the initial block proves to be too small during matching, it
+is replaced by a larger block, subject to the heap limit. The heap limit is
+checked only when a new block is to be allocated. Reducing the heap limit
+between calls to \fBpcre2_match()\fP with the same match data block does not
+affect the saved block.
+.P
+In contrast to \fBpcre2_match()\fP, \fBpcre2_dfa_match()\fP does use recursive
+function calls, but only for processing atomic groups, lookaround assertions,
+and recursion within the pattern. The original version of the code used to
+allocate quite large internal workspace vectors on the stack, which caused some
+problems for some patterns in environments with small stacks. From release
+10.32 the code for \fBpcre2_dfa_match()\fP has been re-factored to use heap
+memory when necessary for internal workspace when recursing, though recursive
+function calls are still used.
+.P
+The "match depth" parameter can be used to limit the depth of function
+recursion, and the "match heap" parameter to limit heap memory in
+\fBpcre2_dfa_match()\fP.
+.
+.
+.SH "PROCESSING TIME"
+.rs
+.sp
+Certain items in regular expression patterns are processed more efficiently
+than others. It is more efficient to use a character class like [aeiou] than a
+set of single-character alternatives such as (a|e|i|o|u). In general, the
+simplest construction that provides the required behaviour is usually the most
+efficient. Jeffrey Friedl's book contains a lot of useful general discussion
+about optimizing regular expressions for efficient performance. This document
+contains a few observations about PCRE2.
+.P
+Using Unicode character properties (the \ep, \eP, and \eX escapes) is slow,
+because PCRE2 has to use a multi-stage table lookup whenever it needs a
+character's property. If you can find an alternative pattern that does not use
+character properties, it will probably be faster.
+.P
+By default, the escape sequences \eb, \ed, \es, and \ew, and the POSIX
+character classes such as [:alpha:] do not use Unicode properties, partly for
+backwards compatibility, and partly for performance reasons. However, you can
+set the PCRE2_UCP option or start the pattern with (*UCP) if you want Unicode
+character properties to be used. This can double the matching time for items
+such as \ed, when matched with \fBpcre2_match()\fP; the performance loss is
+less with a DFA matching function, and in both cases there is not much
+difference for \eb.
+.P
+When a pattern begins with .* not in atomic parentheses, nor in parentheses
+that are the subject of a backreference, and the PCRE2_DOTALL option is set,
+the pattern is implicitly anchored by PCRE2, since it can match only at the
+start of a subject string. If the pattern has multiple top-level branches, they
+must all be anchorable. The optimization can be disabled by the
+PCRE2_NO_DOTSTAR_ANCHOR option, and is automatically disabled if the pattern
+contains (*PRUNE) or (*SKIP).
+.P
+If PCRE2_DOTALL is not set, PCRE2 cannot make this optimization, because the
+dot metacharacter does not then match a newline, and if the subject string
+contains newlines, the pattern may match from the character immediately
+following one of them instead of from the very start. For example, the pattern
+.sp
+ .*second
+.sp
+matches the subject "first\enand second" (where \en stands for a newline
+character), with the match starting at the seventh character. In order to do
+this, PCRE2 has to retry the match starting after every newline in the subject.
+.P
+If you are using such a pattern with subject strings that do not contain
+newlines, the best performance is obtained by setting PCRE2_DOTALL, or starting
+the pattern with ^.* or ^.*? to indicate explicit anchoring. That saves PCRE2
+from having to scan along the subject looking for a newline to restart at.
+.P
+Beware of patterns that contain nested indefinite repeats. These can take a
+long time to run when applied to a string that does not match. Consider the
+pattern fragment
+.sp
+ ^(a+)*
+.sp
+This can match "aaaa" in 16 different ways, and this number increases very
+rapidly as the string gets longer. (The * repeat can match 0, 1, 2, 3, or 4
+times, and for each of those cases other than 0 or 4, the + repeats can match
+different numbers of times.) When the remainder of the pattern is such that the
+entire match is going to fail, PCRE2 has in principle to try every possible
+variation, and this can take an extremely long time, even for relatively short
+strings.
+.P
+An optimization catches some of the more simple cases such as
+.sp
+ (a+)*b
+.sp
+where a literal character follows. Before embarking on the standard matching
+procedure, PCRE2 checks that there is a "b" later in the subject string, and if
+there is not, it fails the match immediately. However, when there is no
+following literal this optimization cannot be used. You can see the difference
+by comparing the behaviour of
+.sp
+ (a+)*\ed
+.sp
+with the pattern above. The former gives a failure almost instantly when
+applied to a whole line of "a" characters, whereas the latter takes an
+appreciable time with strings longer than about 20 characters.
+.P
+In many cases, the solution to this kind of performance issue is to use an
+atomic group or a possessive quantifier. This can often reduce memory
+requirements as well. As another example, consider this pattern:
+.sp
+ ([^<]|<(?!inet))+
+.sp
+It matches from wherever it starts until it encounters "
+.\"
+"The match context"
+.\"
+in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation.
+.P
+The \fBpcre2test\fP test program has a modifier called "find_limits" which, if
+applied to a subject line, causes it to find the smallest limits that allow a
+pattern to match. This is done by repeatedly matching with different limits.
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 06 December 2022
+Copyright (c) 1997-2022 University of Cambridge.
+.fi
diff --git a/doc/pcre2posix.3 b/doc/pcre2posix.3
new file mode 100644
index 0000000..e788bd4
--- /dev/null
+++ b/doc/pcre2posix.3
@@ -0,0 +1,348 @@
+.TH PCRE2POSIX 3 "27 November 2024" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH "SYNOPSIS"
+.rs
+.sp
+.B #include
+.PP
+.nf
+.B int pcre2_regcomp(regex_t *\fIpreg\fP, const char *\fIpattern\fP,
+.B " int \fIcflags\fP);"
+.sp
+.B int pcre2_regexec(const regex_t *\fIpreg\fP, const char *\fIstring\fP,
+.B " size_t \fInmatch\fP, regmatch_t \fIpmatch\fP[], int \fIeflags\fP);"
+.sp
+.B "size_t pcre2_regerror(int \fIerrcode\fP, const regex_t *\fIpreg\fP,"
+.B " char *\fIerrbuf\fP, size_t \fIerrbuf_size\fP);"
+.sp
+.B void pcre2_regfree(regex_t *\fIpreg\fP);
+.fi
+.
+.SH DESCRIPTION
+.rs
+.sp
+This set of functions provides a POSIX-style API for the PCRE2 regular
+expression 8-bit library. There are no POSIX-style wrappers for PCRE2's 16-bit
+and 32-bit libraries. See the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation for a description of PCRE2's native API, which contains much
+additional functionality.
+.P
+\fBIMPORTANT NOTE\fP: The functions described here are NOT thread-safe, and
+should not be used in multi-threaded applications. They are also limited to
+processing subjects that are not bigger than 2GB. Use the native API instead.
+.P
+These functions are wrapper functions that ultimately call the PCRE2 native
+API. Their prototypes are defined in the \fBpcre2posix.h\fP header file, and
+they all have unique names starting with \fBpcre2_\fP. However, the
+\fBpcre2posix.h\fP header also contains macro definitions that convert the
+standard POSIX names such \fBregcomp()\fP into \fBpcre2_regcomp()\fP etc. This
+means that a program can use the usual POSIX names without running the risk of
+accidentally linking with POSIX functions from a different library.
+.P
+On Unix-like systems the PCRE2 POSIX library is called \fBlibpcre2-posix\fP, so
+can be accessed by adding \fB-lpcre2-posix\fP to the command for linking an
+application. Because the POSIX functions call the native ones, it is also
+necessary to add \fB-lpcre2-8\fP.
+.P
+On Windows systems, if you are linking to a DLL version of the library, it is
+recommended that \fBPCRE2POSIX_SHARED\fP is defined before including the
+\fBpcre2posix.h\fP header, as it will allow for a more efficient way to
+invoke the functions by adding the \fB__declspec(dllimport)\fP decorator.
+.P
+Although they were not defined as prototypes in \fBpcre2posix.h\fP, releases
+10.33 to 10.36 of the library contained functions with the POSIX names
+\fBregcomp()\fP etc. These simply passed their arguments to the PCRE2
+functions. These functions were provided for backwards compatibility with
+earlier versions of PCRE2, which had only POSIX names. However, this has proved
+troublesome in situations where a program links with several libraries, some of
+which use PCRE2's POSIX interface while others use the real POSIX functions.
+For this reason, the POSIX names have been removed since release 10.37.
+.P
+Calling the header file \fBpcre2posix.h\fP avoids any conflict with other POSIX
+libraries. It can, of course, be renamed or aliased as \fBregex.h\fP, which is
+the "correct" name, if there is no clash. It provides two structure types,
+\fIregex_t\fP for compiled internal forms, and \fIregmatch_t\fP for returning
+captured substrings. It also defines some constants whose names start with
+"REG_"; these are used for setting options and identifying error codes.
+.
+.
+.SH "USING THE POSIX FUNCTIONS"
+.rs
+.sp
+Note that these functions are just POSIX-style wrappers for PCRE2's native API.
+They do not give POSIX regular expression behaviour, and they are not
+thread-safe or even POSIX compatible.
+.P
+Those POSIX option bits that can reasonably be mapped to PCRE2 native options
+have been implemented. In addition, the option REG_EXTENDED is defined with the
+value zero. This has no effect, but since programs that are written to the
+POSIX interface often use it, this makes it easier to slot in PCRE2 as a
+replacement library. Other POSIX options are not even defined.
+.P
+There are also some options that are not defined by POSIX. These have been
+added at the request of users who want to make use of certain PCRE2-specific
+features via the POSIX calling interface or to add BSD or GNU functionality.
+.P
+When PCRE2 is called via these functions, it is only the API that is POSIX-like
+in style. The syntax and semantics of the regular expressions themselves are
+still those of Perl, subject to the setting of various PCRE2 options, as
+described below. "POSIX-like in style" means that the API approximates to the
+POSIX definition; it is not fully POSIX-compatible, and in multi-unit encoding
+domains it is probably even less compatible.
+.P
+The descriptions below use the actual names of the functions, but, as described
+above, the standard POSIX names (without the \fBpcre2_\fP prefix) may also be
+used.
+.
+.
+.SH "COMPILING A PATTERN"
+.rs
+.sp
+The function \fBpcre2_regcomp()\fP is called to compile a pattern into an
+internal form. By default, the pattern is a C string terminated by a binary
+zero (but see REG_PEND below). The \fIpreg\fP argument is a pointer to a
+\fBregex_t\fP structure that is used as a base for storing information about
+the compiled regular expression. It is also used for input when REG_PEND is
+set. The \fBregex_t\fP structure used by \fBpcre2_regcomp()\fP is defined in
+\fBpcre2posix.h\fP and is not the same as the structure used by other libraries
+that provide POSIX-style matching.
+.P
+The argument \fIcflags\fP is either zero, or contains one or more of the bits
+defined by the following macros:
+.sp
+ REG_DOTALL
+.sp
+The PCRE2_DOTALL option is set when the regular expression is passed for
+compilation to the native function. Note that REG_DOTALL is not part of the
+POSIX standard.
+.sp
+ REG_ICASE
+.sp
+The PCRE2_CASELESS option is set when the regular expression is passed for
+compilation to the native function.
+.sp
+ REG_NEWLINE
+.sp
+The PCRE2_MULTILINE option is set when the regular expression is passed for
+compilation to the native function. Note that this does \fInot\fP mimic the
+defined POSIX behaviour for REG_NEWLINE (see the following section).
+.sp
+ REG_NOSPEC
+.sp
+The PCRE2_LITERAL option is set when the regular expression is passed for
+compilation to the native function. This disables all meta characters in the
+pattern, causing it to be treated as a literal string. The only other options
+that are allowed with REG_NOSPEC are REG_ICASE, REG_NOSUB, REG_PEND, and
+REG_UTF. Note that REG_NOSPEC is not part of the POSIX standard.
+.sp
+ REG_NOSUB
+.sp
+When a pattern that is compiled with this flag is passed to
+\fBpcre2_regexec()\fP for matching, the \fInmatch\fP and \fIpmatch\fP arguments
+are ignored, and no captured strings are returned. Versions of the PCRE2 library
+prior to 10.22 used to set the PCRE2_NO_AUTO_CAPTURE compile option, but this
+no longer happens because it disables the use of backreferences.
+.sp
+ REG_PEND
+.sp
+If this option is set, the \fBreg_endp\fP field in the \fIpreg\fP structure
+(which has the type const char *) must be set to point to the character beyond
+the end of the pattern before calling \fBpcre2_regcomp()\fP. The pattern itself
+may now contain binary zeros, which are treated as data characters. Without
+REG_PEND, a binary zero terminates the pattern and the \fBre_endp\fP field is
+ignored. This is a GNU extension to the POSIX standard and should be used with
+caution in software intended to be portable to other systems.
+.sp
+ REG_UCP
+.sp
+The PCRE2_UCP option is set when the regular expression is passed for
+compilation to the native function. This causes PCRE2 to use Unicode properties
+when matching \ed, \ew, etc., instead of just recognizing ASCII values. Note
+that REG_UCP is not part of the POSIX standard.
+.sp
+ REG_UNGREEDY
+.sp
+The PCRE2_UNGREEDY option is set when the regular expression is passed for
+compilation to the native function. Note that REG_UNGREEDY is not part of the
+POSIX standard.
+.sp
+ REG_UTF
+.sp
+The PCRE2_UTF option is set when the regular expression is passed for
+compilation to the native function. This causes the pattern itself and all data
+strings used for matching it to be treated as UTF-8 strings. Note that REG_UTF
+is not part of the POSIX standard.
+.P
+In the absence of these flags, no options are passed to the native function.
+This means that the regex is compiled with PCRE2 default semantics. In
+particular, the way it handles newline characters in the subject string is the
+Perl way, not the POSIX way. Note that setting PCRE2_MULTILINE has only
+\fIsome\fP of the effects specified for REG_NEWLINE. It does not affect the way
+newlines are matched by the dot metacharacter (they are not) or by a negative
+class such as [^a] (they are).
+.P
+The yield of \fBpcre2_regcomp()\fP is zero on success, and non-zero otherwise.
+The \fIpreg\fP structure is filled in on success, and one other member of the
+structure (as well as \fIre_endp\fP) is public: \fIre_nsub\fP contains the
+number of capturing subpatterns in the regular expression. Various error codes
+are defined in the header file.
+.P
+NOTE: If the yield of \fBpcre2_regcomp()\fP is non-zero, you must not attempt
+to use the contents of the \fIpreg\fP structure. If, for example, you pass it
+to \fBpcre2_regexec()\fP, the result is undefined and your program is likely to
+crash.
+.
+.
+.SH "MATCHING NEWLINE CHARACTERS"
+.rs
+.sp
+This area is not simple, because POSIX and Perl take different views of things.
+It is not possible to get PCRE2 to obey POSIX semantics, but then PCRE2 was
+never intended to be a POSIX engine. The following table lists the different
+possibilities for matching newline characters in Perl and PCRE2:
+.sp
+ Default Change with
+.sp
+ . matches newline no PCRE2_DOTALL
+ newline matches [^a] yes not changeable
+ $ matches \en at end yes PCRE2_DOLLAR_ENDONLY
+ $ matches \en in middle no PCRE2_MULTILINE
+ ^ matches \en in middle no PCRE2_MULTILINE
+.sp
+This is the equivalent table for a POSIX-compatible pattern matcher:
+.sp
+ Default Change with
+.sp
+ . matches newline yes REG_NEWLINE
+ newline matches [^a] yes REG_NEWLINE
+ $ matches \en at end no REG_NEWLINE
+ $ matches \en in middle no REG_NEWLINE
+ ^ matches \en in middle no REG_NEWLINE
+.sp
+This behaviour is not what happens when PCRE2 is called via its POSIX
+API. By default, PCRE2's behaviour is the same as Perl's, except that there is
+no equivalent for PCRE2_DOLLAR_ENDONLY in Perl. In both PCRE2 and Perl, there
+is no way to stop newline from matching [^a].
+.P
+Default POSIX newline handling can be obtained by setting PCRE2_DOTALL and
+PCRE2_DOLLAR_ENDONLY when calling \fBpcre2_compile()\fP directly, but there is
+no way to make PCRE2 behave exactly as for the REG_NEWLINE action. When using
+the POSIX API, passing REG_NEWLINE to PCRE2's \fBpcre2_regcomp()\fP function
+causes PCRE2_MULTILINE to be passed to \fBpcre2_compile()\fP, and REG_DOTALL
+passes PCRE2_DOTALL. There is no way to pass PCRE2_DOLLAR_ENDONLY.
+.
+.
+.SH "MATCHING A PATTERN"
+.rs
+.sp
+The function \fBpcre2_regexec()\fP is called to match a compiled pattern
+\fIpreg\fP against a given \fIstring\fP, which is by default terminated by a
+zero byte (but see REG_STARTEND below), subject to the options in \fIeflags\fP.
+These can be:
+.sp
+ REG_NOTBOL
+.sp
+The PCRE2_NOTBOL option is set when calling the underlying PCRE2 matching
+function.
+.sp
+ REG_NOTEMPTY
+.sp
+The PCRE2_NOTEMPTY option is set when calling the underlying PCRE2 matching
+function. Note that REG_NOTEMPTY is not part of the POSIX standard. However,
+setting this option can give more POSIX-like behaviour in some situations.
+.sp
+ REG_NOTEOL
+.sp
+The PCRE2_NOTEOL option is set when calling the underlying PCRE2 matching
+function.
+.sp
+ REG_STARTEND
+.sp
+When this option is set, the subject string starts at \fIstring\fP +
+\fIpmatch[0].rm_so\fP and ends at \fIstring\fP + \fIpmatch[0].rm_eo\fP, which
+should point to the first character beyond the string. There may be binary
+zeros within the subject string, and indeed, using REG_STARTEND is the only
+way to pass a subject string that contains a binary zero.
+.P
+Whatever the value of \fIpmatch[0].rm_so\fP, the offsets of the matched string
+and any captured substrings are still given relative to the start of
+\fIstring\fP itself. (Before PCRE2 release 10.30 these were given relative to
+\fIstring\fP + \fIpmatch[0].rm_so\fP, but this differs from other
+implementations.)
+.P
+This is a BSD extension, compatible with but not specified by IEEE Standard
+1003.2 (POSIX.2), and should be used with caution in software intended to be
+portable to other systems. Note that a non-zero \fIrm_so\fP does not imply
+REG_NOTBOL; REG_STARTEND affects only the location and length of the string,
+not how it is matched. Setting REG_STARTEND and passing \fIpmatch\fP as NULL
+are mutually exclusive; the error REG_INVARG is returned.
+.P
+If the pattern was compiled with the REG_NOSUB flag, no data about any matched
+strings is returned. The \fInmatch\fP and \fIpmatch\fP arguments of
+\fBpcre2_regexec()\fP are ignored (except possibly as input for REG_STARTEND).
+.P
+The value of \fInmatch\fP may be zero, and the value \fIpmatch\fP may be NULL
+(unless REG_STARTEND is set); in both these cases no data about any matched
+strings is returned.
+.P
+Otherwise, the portion of the string that was matched, and also any captured
+substrings, are returned via the \fIpmatch\fP argument, which points to an
+array of \fInmatch\fP structures of type \fIregmatch_t\fP, containing the
+members \fIrm_so\fP and \fIrm_eo\fP. These contain the byte offset to the first
+character of each substring and the offset to the first character after the end
+of each substring, respectively. The 0th element of the vector relates to the
+entire portion of \fIstring\fP that was matched; subsequent elements relate to
+the capturing subpatterns of the regular expression. Unused entries in the
+array have both structure members set to -1.
+.P
+\fIregmatch_t\fP as well as the \fIregoff_t\fP typedef it uses are defined in
+\fBpcre2posix.h\fP and are not warranted to have the same size or layout as other
+similarly named types from other libraries that provide POSIX-style matching.
+.P
+A successful match yields a zero return; various error codes are defined in the
+header file, of which REG_NOMATCH is the "expected" failure code.
+.
+.
+.SH "ERROR MESSAGES"
+.rs
+.sp
+The \fBpcre2_regerror()\fP function maps a non-zero errorcode from either
+\fBpcre2_regcomp()\fP or \fBpcre2_regexec()\fP to a printable message. If
+\fIpreg\fP is not NULL, the error should have arisen from the use of that
+structure. A message terminated by a binary zero is placed in \fIerrbuf\fP. If
+the buffer is too short, only the first \fIerrbuf_size\fP - 1 characters of the
+error message are used. The yield of the function is the size of buffer needed
+to hold the whole message, including the terminating zero. This value is
+greater than \fIerrbuf_size\fP if the message was truncated.
+.
+.
+.SH MEMORY USAGE
+.rs
+.sp
+Compiling a regular expression causes memory to be allocated and associated
+with the \fIpreg\fP structure. The function \fBpcre2_regfree()\fP frees all
+such memory, after which \fIpreg\fP may no longer be used as a compiled
+expression.
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 27 November 2024
+Copyright (c) 1997-2024 University of Cambridge.
+.fi
diff --git a/doc/pcre2sample.3 b/doc/pcre2sample.3
new file mode 100644
index 0000000..f931df2
--- /dev/null
+++ b/doc/pcre2sample.3
@@ -0,0 +1,100 @@
+.TH PCRE2SAMPLE 3 "28 February 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH "PCRE2 SAMPLE PROGRAM"
+.rs
+.sp
+A simple, complete demonstration program to get you started with using PCRE2 is
+supplied in the file \fIpcre2demo.c\fP in the \fBsrc\fP directory in the PCRE2
+distribution. A listing of this program is given in the
+.\" HREF
+\fBpcre2demo\fP
+.\"
+documentation. If you do not have a copy of the PCRE2 distribution, you can
+save this listing to recreate the contents of \fIpcre2demo.c\fP.
+.P
+The demonstration program compiles the regular expression that is its
+first argument, and matches it against the subject string in its second
+argument. No PCRE2 options are set, and default character tables are used. If
+matching succeeds, the program outputs the portion of the subject that matched,
+together with the contents of any captured substrings.
+.P
+If the -g option is given on the command line, the program then goes on to
+check for further matches of the same regular expression in the same subject
+string. The logic is a little bit tricky because of the possibility of matching
+an empty string. Comments in the code explain what is going on.
+.P
+The code in \fBpcre2demo.c\fP is an 8-bit program that uses the PCRE2 8-bit
+library. It handles strings and characters that are stored in 8-bit code units.
+By default, one character corresponds to one code unit, but if the pattern
+starts with "(*UTF)", both it and the subject are treated as UTF-8 strings,
+where characters may occupy multiple code units.
+.P
+If PCRE2 is installed in the standard include and library directories for your
+operating system, you should be able to compile the demonstration program using
+a command like this:
+.sp
+ cc -o pcre2demo pcre2demo.c -lpcre2-8
+.sp
+If PCRE2 is installed elsewhere, you may need to add additional options to the
+command line. For example, on a Unix-like system that has PCRE2 installed in
+\fI/usr/local\fP, you can compile the demonstration program using a command
+like this:
+.sp
+.\" JOINSH
+ cc -o pcre2demo -I/usr/local/include pcre2demo.c \e
+ -L/usr/local/lib -lpcre2-8
+.sp
+Once you have built the demonstration program, you can run simple tests like
+this:
+.sp
+ ./pcre2demo 'cat|dog' 'the cat sat on the mat'
+ ./pcre2demo -g 'cat|dog' 'the dog sat on the cat'
+ ./pcre2demo -i 'cat' 'the dog sat on the CAT'
+.sp
+Note that there is a much more comprehensive test program, called
+.\" HREF
+\fBpcre2test\fP,
+.\"
+which supports many more facilities for testing regular expressions using all
+three PCRE2 libraries (8-bit, 16-bit, and 32-bit, though not all three need be
+installed). The
+.\" HREF
+\fBpcre2demo\fP
+.\"
+program is provided as a relatively simple coding example.
+.P
+If you try to run
+.\" HREF
+\fBpcre2demo\fP
+.\"
+when PCRE2 is not installed in the standard library directory, you may get an
+error like this on some operating systems (e.g. Solaris):
+.sp
+ ld.so.1: pcre2demo: fatal: libpcre2-8.so.0: open failed: No such file or directory
+.sp
+This is caused by the way shared library support works on those systems. You
+need to add
+.sp
+ -R/usr/local/lib
+.sp
+(for example) to the compile command to get round this problem.
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 28 February 2025
+Copyright (c) 1997-2016 University of Cambridge.
+.fi
diff --git a/doc/pcre2serialize.3 b/doc/pcre2serialize.3
new file mode 100644
index 0000000..46e75a7
--- /dev/null
+++ b/doc/pcre2serialize.3
@@ -0,0 +1,198 @@
+.TH PCRE2SERIALIZE 3 "19 January 2024" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH "SAVING AND RE-USING PRECOMPILED PCRE2 PATTERNS"
+.rs
+.sp
+.nf
+.B int32_t pcre2_serialize_decode(pcre2_code **\fIcodes\fP,
+.B " int32_t \fInumber_of_codes\fP, const uint8_t *\fIbytes\fP,"
+.B " pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B int32_t pcre2_serialize_encode(const pcre2_code **\fIcodes\fP,
+.B " int32_t \fInumber_of_codes\fP, uint8_t **\fIserialized_bytes\fP,"
+.B " PCRE2_SIZE *\fIserialized_size\fP, pcre2_general_context *\fIgcontext\fP);"
+.sp
+.B void pcre2_serialize_free(uint8_t *\fIbytes\fP);
+.sp
+.B int32_t pcre2_serialize_get_number_of_codes(const uint8_t *\fIbytes\fP);
+.fi
+.sp
+If you are running an application that uses a large number of regular
+expression patterns, it may be useful to store them in a precompiled form
+instead of having to compile them every time the application is run. However,
+if you are using the just-in-time optimization feature, it is not possible to
+save and reload the JIT data, because it is position-dependent. The host on
+which the patterns are reloaded must be running the same version of PCRE2, with
+the same code unit width, and must also have the same endianness, pointer width
+and PCRE2_SIZE type. For example, patterns compiled on a 32-bit system using
+PCRE2's 16-bit library cannot be reloaded on a 64-bit system, nor can they be
+reloaded using the 8-bit library.
+.P
+Note that "serialization" in PCRE2 does not convert compiled patterns to an
+abstract format like Java or .NET serialization. The serialized output is
+really just a bytecode dump, which is why it can only be reloaded in the same
+environment as the one that created it. Hence the restrictions mentioned above.
+Applications that are not statically linked with a fixed version of PCRE2 must
+be prepared to recompile patterns from their sources, in order to be immune to
+PCRE2 upgrades.
+.
+.
+.SH "SECURITY CONCERNS"
+.rs
+.sp
+The facility for saving and restoring compiled patterns is intended for use
+within individual applications. As such, the data supplied to
+\fBpcre2_serialize_decode()\fP is expected to be trusted data, not data from
+arbitrary external sources. There is only some simple consistency checking, not
+complete validation of what is being re-loaded. Corrupted data may cause
+undefined results. For example, if the length field of a pattern in the
+serialized data is corrupted, the deserializing code may read beyond the end of
+the byte stream that is passed to it.
+.
+.
+.SH "SAVING COMPILED PATTERNS"
+.rs
+.sp
+Before compiled patterns can be saved they must be serialized, which in PCRE2
+means converting the pattern to a stream of bytes. A single byte stream may
+contain any number of compiled patterns, but they must all use the same
+character tables. A single copy of the tables is included in the byte stream
+(its size is 1088 bytes). For more details of character tables, see the
+.\" HTML
+.\"
+section on locale support
+.\"
+in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation.
+.P
+The function \fBpcre2_serialize_encode()\fP creates a serialized byte stream
+from a list of compiled patterns. Its first two arguments specify the list,
+being a pointer to a vector of pointers to compiled patterns, and the length of
+the vector. The third and fourth arguments point to variables which are set to
+point to the created byte stream and its length, respectively. The final
+argument is a pointer to a general context, which can be used to specify custom
+memory management functions. If this argument is NULL, \fBmalloc()\fP is used
+to obtain memory for the byte stream. The yield of the function is the number
+of serialized patterns, or one of the following negative error codes:
+.sp
+ PCRE2_ERROR_BADDATA the number of patterns is zero or less
+ PCRE2_ERROR_BADMAGIC mismatch of id bytes in one of the patterns
+ PCRE2_ERROR_NOMEMORY memory allocation failed
+ PCRE2_ERROR_MIXEDTABLES the patterns do not all use the same tables
+ PCRE2_ERROR_NULL the 1st, 3rd, or 4th argument is NULL
+.sp
+PCRE2_ERROR_BADMAGIC means either that a pattern's code has been corrupted, or
+that a slot in the vector does not point to a compiled pattern.
+.P
+Once a set of patterns has been serialized you can save the data in any
+appropriate manner. Here is sample code that compiles two patterns and writes
+them to a file. It assumes that the variable \fIfd\fP refers to a file that is
+open for output. The error checking that should be present in a real
+application has been omitted for simplicity.
+.sp
+ int errorcode;
+ uint8_t *bytes;
+ PCRE2_SIZE erroroffset;
+ PCRE2_SIZE bytescount;
+ pcre2_code *list_of_codes[2];
+ list_of_codes[0] = pcre2_compile("first pattern",
+ PCRE2_ZERO_TERMINATED, 0, &errorcode, &erroroffset, NULL);
+ list_of_codes[1] = pcre2_compile("second pattern",
+ PCRE2_ZERO_TERMINATED, 0, &errorcode, &erroroffset, NULL);
+ errorcode = pcre2_serialize_encode(list_of_codes, 2, &bytes,
+ &bytescount, NULL);
+ errorcode = fwrite(bytes, 1, bytescount, fd);
+.sp
+Note that the serialized data is binary data that may contain any of the 256
+possible byte values. On systems that make a distinction between binary and
+non-binary data, be sure that the file is opened for binary output.
+.P
+Serializing a set of patterns leaves the original data untouched, so they can
+still be used for matching. Their memory must eventually be freed in the usual
+way by calling \fBpcre2_code_free()\fP. When you have finished with the byte
+stream, it too must be freed by calling \fBpcre2_serialize_free()\fP. If this
+function is called with a NULL argument, it returns immediately without doing
+anything.
+.
+.
+.SH "RE-USING PRECOMPILED PATTERNS"
+.rs
+.sp
+In order to re-use a set of saved patterns you must first make the serialized
+byte stream available in main memory (for example, by reading from a file). The
+management of this memory block is up to the application. You can use the
+\fBpcre2_serialize_get_number_of_codes()\fP function to find out how many
+compiled patterns are in the serialized data without actually decoding the
+patterns:
+.sp
+ uint8_t *bytes = ;
+ int32_t number_of_codes = pcre2_serialize_get_number_of_codes(bytes);
+.sp
+The \fBpcre2_serialize_decode()\fP function reads a byte stream and recreates
+the compiled patterns in new memory blocks, setting pointers to them in a
+vector. The first two arguments are a pointer to a suitable vector and its
+length, and the third argument points to a byte stream. The final argument is a
+pointer to a general context, which can be used to specify custom memory
+management functions for the decoded patterns. If this argument is NULL,
+\fBmalloc()\fP and \fBfree()\fP are used. After deserialization, the byte
+stream is no longer needed and can be discarded.
+.sp
+ pcre2_code *list_of_codes[2];
+ uint8_t *bytes = ;
+ int32_t number_of_codes =
+ pcre2_serialize_decode(list_of_codes, 2, bytes, NULL);
+.sp
+If the vector is not large enough for all the patterns in the byte stream, it
+is filled with those that fit, and the remainder are ignored. The yield of the
+function is the number of decoded patterns, or one of the following negative
+error codes:
+.sp
+ PCRE2_ERROR_BADDATA second argument is zero or less
+ PCRE2_ERROR_BADMAGIC mismatch of id bytes in the data
+ PCRE2_ERROR_BADMODE mismatch of code unit size or PCRE2 version
+ PCRE2_ERROR_BADSERIALIZEDDATA other sanity check failure
+ PCRE2_ERROR_MEMORY memory allocation failed
+ PCRE2_ERROR_NULL first or third argument is NULL
+.sp
+PCRE2_ERROR_BADMAGIC may mean that the data is corrupt, or that it was compiled
+on a system with different endianness.
+.P
+Decoded patterns can be used for matching in the usual way, and must be freed
+by calling \fBpcre2_code_free()\fP. However, be aware that there is a potential
+race issue if you are using multiple patterns that were decoded from a single
+byte stream in a multithreaded application. A single copy of the character
+tables is used by all the decoded patterns and a reference count is used to
+arrange for its memory to be automatically freed when the last pattern is
+freed, but there is no locking on this reference count. Therefore, if you want
+to call \fBpcre2_code_free()\fP for these patterns in different threads, you
+must arrange your own locking, and ensure that \fBpcre2_code_free()\fP cannot
+be called by two threads at the same time.
+.P
+If a pattern was processed by \fBpcre2_jit_compile()\fP before being
+serialized, the JIT data is discarded and so is no longer available after a
+save/restore cycle. You can, however, process a restored pattern with
+\fBpcre2_jit_compile()\fP if you wish.
+.
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 19 January 2024
+Copyright (c) 1997-2018 University of Cambridge.
+.fi
diff --git a/doc/pcre2syntax.3 b/doc/pcre2syntax.3
new file mode 100644
index 0000000..c3a68bd
--- /dev/null
+++ b/doc/pcre2syntax.3
@@ -0,0 +1,762 @@
+.TH PCRE2SYNTAX 3 "14 October 2025" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH "PCRE2 REGULAR EXPRESSION SYNTAX SUMMARY"
+.rs
+.sp
+The full syntax and semantics of the regular expression patterns that are
+supported by PCRE2 are described in the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+documentation. This document contains a quick-reference summary of the pattern
+syntax followed by the syntax of replacement strings in substitution function.
+The full description of the latter is in the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation.
+.
+.SH "QUOTING"
+.rs
+.sp
+ \ex where x is non-alphanumeric is a literal x
+ \eQ...\eE treat enclosed characters as literal
+.sp
+Note that white space inside \eQ...\eE is always treated as literal, even if
+PCRE2_EXTENDED is set, causing most other white space to be ignored. Note also
+that PCRE2's handling of \eQ...\eE has some differences from Perl's. See the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+documentation for details.
+.
+.
+.SH "BRACED ITEMS"
+.rs
+.sp
+With one exception, wherever brace characters { and } are required to enclose
+data for constructions such as \eg{2} or \ek{name}, space and/or horizontal tab
+characters that follow { or precede } are allowed and are ignored. In the case
+of quantifiers, they may also appear before or after the comma. The exception
+is \eu{...} which is not Perl-compatible and is recognized only when
+PCRE2_EXTRA_ALT_BSUX is set. This is an ECMAScript compatibility feature, and
+follows ECMAScript's behaviour.
+.
+.
+.SH "ESCAPED CHARACTERS"
+.rs
+.sp
+This table applies to ASCII and Unicode environments. An unrecognized escape
+sequence causes an error.
+.sp
+ \ea alarm, that is, the BEL character (hex 07)
+ \ecx "control-x", where x is a non-control ASCII character
+ \ee escape (hex 1B)
+ \ef form feed (hex 0C)
+ \en newline (hex 0A)
+ \er carriage return (hex 0D)
+ \et tab (hex 09)
+ \e0dd character with octal code 0dd
+ \eddd character with octal code ddd, or backreference
+ \eo{ddd..} character with octal code ddd..
+ \eN{U+hh..} character with Unicode code point hh.. (Unicode mode only)
+ \exhh character with hex code hh
+ \ex{hh..} character with hex code hh..
+.sp
+\eN{U+hh..} is synonymous with \ex{hh..} but is not supported in environments
+that use EBCDIC code (mainly IBM mainframes). Note that \eN not followed by an
+opening curly bracket has a different meaning (see below).
+.P
+If PCRE2_ALT_BSUX or PCRE2_EXTRA_ALT_BSUX is set ("ALT_BSUX mode"), the
+following are also recognized:
+.sp
+ \eU the character "U"
+ \euhhhh character with hex code hhhh
+ \eu{hh..} character with hex code hh.. but only for EXTRA_ALT_BSUX
+.sp
+When \ex is not followed by {, one or two hexadecimal digits are read,
+but in ALT_BSUX mode \ex must be followed by two hexadecimal digits to be
+recognized as a hexadecimal escape; otherwise it matches a literal "x".
+Likewise, if \eu (in ALT_BSUX mode) is not followed by four hexadecimal digits
+or (in EXTRA_ALT_BSUX mode) a sequence of hex digits in curly brackets, it
+matches a literal "u".
+.P
+Note that \e0dd is always an octal code. The treatment of backslash followed by
+a non-zero digit is complicated; for details see the section
+.\" HTML
+.\"
+"Non-printing characters"
+.\"
+in the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+documentation, where details of escape processing in EBCDIC environments are
+also given.
+.
+.
+.SH "CHARACTER TYPES"
+.rs
+.sp
+ . any character except newline;
+ in dotall mode, any character whatsoever
+ \eC one code unit, even in UTF mode (best avoided)
+ \ed a decimal digit
+ \eD a character that is not a decimal digit
+ \eh a horizontal white space character
+ \eH a character that is not a horizontal white space character
+ \eN a character that is not a newline
+ \ep{\fIxx\fP} a character with the \fIxx\fP property
+ \eP{\fIxx\fP} a character without the \fIxx\fP property
+ \eR a newline sequence
+ \es a white space character
+ \eS a character that is not a white space character
+ \ev a vertical white space character
+ \eV a character that is not a vertical white space character
+ \ew a "word" character
+ \eW a "non-word" character
+ \eX a Unicode extended grapheme cluster
+.sp
+\eC is dangerous because it may leave the current matching point in the middle
+of a UTF-8 or UTF-16 character. The application can lock out the use of \eC by
+setting the PCRE2_NEVER_BACKSLASH_C option. It is also possible to build PCRE2
+with the use of \eC permanently disabled.
+.P
+By default, \ed, \es, and \ew match only ASCII characters, even in UTF-8 mode
+or in the 16-bit and 32-bit libraries. However, if locale-specific matching is
+happening, \es and \ew may also match characters with code points in the range
+128-255. If the PCRE2_UCP option is set, the behaviour of these escape
+sequences is changed to use Unicode properties and they match many more
+characters, but there are some option settings that can restrict individual
+sequences to matching only ASCII characters.
+.P
+Property descriptions in \ep and \eP are matched caselessly; hyphens,
+underscores, and ASCII white space characters are ignored, in accordance with
+Unicode's "loose matching" rules. For example, \ep{Bidi_Class=al} is the same
+as \ep{ bidi class = AL }.
+.
+.
+.SH "GENERAL CATEGORY PROPERTIES FOR \ep and \eP"
+.rs
+.sp
+ C Other
+ Cc Control
+ Cf Format
+ Cn Unassigned
+ Co Private use
+ Cs Surrogate
+.sp
+ L Letter
+ Lc Cased letter, the union of Ll, Lu, and Lt
+ L& Synonym of Lc
+ Ll Lower case letter
+ Lm Modifier letter
+ Lo Other letter
+ Lt Title case letter
+ Lu Upper case letter
+.sp
+ M Mark
+ Mc Spacing mark
+ Me Enclosing mark
+ Mn Non-spacing mark
+.sp
+ N Number
+ Nd Decimal number
+ Nl Letter number
+ No Other number
+.sp
+ P Punctuation
+ Pc Connector punctuation
+ Pd Dash punctuation
+ Pe Close punctuation
+ Pf Final punctuation
+ Pi Initial punctuation
+ Po Other punctuation
+ Ps Open punctuation
+.sp
+ S Symbol
+ Sc Currency symbol
+ Sk Modifier symbol
+ Sm Mathematical symbol
+ So Other symbol
+.sp
+ Z Separator
+ Zl Line separator
+ Zp Paragraph separator
+ Zs Space separator
+.sp
+From release 10.45, when caseless matching is set, Ll, Lu, and Lt are all
+equivalent to Lc.
+.
+.
+.SH "PCRE2 SPECIAL CATEGORY PROPERTIES FOR \ep and \eP"
+.rs
+.sp
+ Xan Alphanumeric: union of properties L and N
+ Xps POSIX space: property Z or tab, NL, VT, FF, CR
+ Xsp Perl space: property Z or tab, NL, VT, FF, CR
+ Xuc Universally-named character: one that can be
+ represented by a Universal Character Name
+ Xwd Perl word: property Xan or underscore
+.sp
+Perl and POSIX space are now the same. Perl added VT to its space character set
+at release 5.18.
+.
+.
+.SH "BINARY PROPERTIES FOR \ep AND \eP"
+.rs
+.sp
+Unicode defines a number of binary properties, that is, properties whose only
+values are true or false. You can obtain a list of those that are recognized by
+\ep and \eP, along with their abbreviations, by running this command:
+.sp
+ pcre2test -LP
+.
+.
+.
+.SH "SCRIPT MATCHING WITH \ep AND \eP"
+.rs
+.sp
+Many script names and their 4-letter abbreviations are recognized in
+\ep{sc:...} or \ep{scx:...} items, or on their own with \ep (and also \eP of
+course). You can obtain a list of these scripts by running this command:
+.sp
+ pcre2test -LS
+.
+.
+.
+.SH "THE BIDI_CLASS PROPERTY FOR \ep AND \eP"
+.rs
+.sp
+ \ep{Bidi_Class:} matches a character with the given class
+ \ep{BC:} matches a character with the given class
+.sp
+The recognized classes are:
+.sp
+ AL Arabic letter
+ AN Arabic number
+ B paragraph separator
+ BN boundary neutral
+ CS common separator
+ EN European number
+ ES European separator
+ ET European terminator
+ FSI first strong isolate
+ L left-to-right
+ LRE left-to-right embedding
+ LRI left-to-right isolate
+ LRO left-to-right override
+ NSM non-spacing mark
+ ON other neutral
+ PDF pop directional format
+ PDI pop directional isolate
+ R right-to-left
+ RLE right-to-left embedding
+ RLI right-to-left isolate
+ RLO right-to-left override
+ S segment separator
+ WS white space
+.
+.
+.SH "CHARACTER CLASSES"
+.rs
+.sp
+ [...] positive character class
+ [^...] negative character class
+ [x-y] range (can be used for hex characters)
+ [[:xxx:]] positive POSIX named set
+ [[:^xxx:]] negative POSIX named set
+.sp
+ alnum alphanumeric
+ alpha alphabetic
+ ascii 0-127
+ blank space or tab
+ cntrl control character
+ digit decimal digit
+ graph printing, excluding space
+ lower lower case letter
+ print printing, including space
+ punct printing, excluding alphanumeric
+ space white space
+ upper upper case letter
+ word same as \ew
+ xdigit hexadecimal digit
+.sp
+In PCRE2, POSIX character set names recognize only ASCII characters by default,
+but some of them use Unicode properties if PCRE2_UCP is set. You can use
+\eQ...\eE inside a character class.
+.P
+When PCRE2_ALT_EXTENDED_CLASS is set, UTS#18 extended character classes may be
+used, allowing nested character classes, combined using set operators.
+.sp
+ [x&&[^y]] UTS#18 extended character class
+.sp
+ x||y set union (OR)
+ x&&y set intersection (AND)
+ x--y set difference (AND NOT)
+ x~~y set symmetric difference (XOR)
+.sp
+.
+.
+.SH "PERL EXTENDED CHARACTER CLASSES"
+.rs
+.sp
+ (?[...]) Perl extended character class
+ (?[\ep{Thai} & \ep{Nd}]) operators; white space ignored
+ (?[(x - y) & z]) parentheses for grouping
+.sp
+ (?[ [^3] & \ep{Nd} ]) [...] is a nested ordinary class
+ (?[ [:alpha:] - [z] ]) POSIX set is allowed outside [...]
+ (?[ \ed - [3] ]) backslash-escaped set is allowed outside [...]
+ (?[ !\en & [:ascii:] ]) backslash-escaped character is allowed outside [...]
+ all other characters or ranges must be enclosed in [...]
+.sp
+ x|y, x+y set union (OR)
+ x&y set intersection (AND)
+ x-y set difference (AND NOT)
+ x^y set symmetric difference (XOR)
+ !x set complement (NOT)
+.sp
+Inside a Perl extended character class, [...] switches mode to be interpreted
+as an ordinary character class. Outside of a nested [...], the only items
+permitted are backslash-escapes, POSIX sets, operators, and parentheses. Inside
+a nested ordinary class, ^ has its usual meaning (inverts the class when used
+as the first character); outside of a nested class, ^ is the XOR operator.
+.
+.
+.SH "QUANTIFIERS"
+.rs
+.sp
+ ? 0 or 1, greedy
+ ?+ 0 or 1, possessive
+ ?? 0 or 1, lazy
+ * 0 or more, greedy
+ *+ 0 or more, possessive
+ *? 0 or more, lazy
+ + 1 or more, greedy
+ ++ 1 or more, possessive
+ +? 1 or more, lazy
+ {n} exactly n
+ {n,m} at least n, no more than m, greedy
+ {n,m}+ at least n, no more than m, possessive
+ {n,m}? at least n, no more than m, lazy
+ {n,} n or more, greedy
+ {n,}+ n or more, possessive
+ {n,}? n or more, lazy
+ {,m} zero up to m, greedy
+ {,m}+ zero up to m, possessive
+ {,m}? zero up to m, lazy
+.
+.
+.SH "ANCHORS AND SIMPLE ASSERTIONS"
+.rs
+.sp
+ \eb word boundary
+ \eB not a word boundary
+ ^ start of subject
+ also after an internal newline in multiline mode
+ (after any newline if PCRE2_ALT_CIRCUMFLEX is set)
+ \eA start of subject
+ $ end of subject
+ also before newline at end of subject
+ also before internal newline in multiline mode
+ \eZ end of subject
+ also before newline at end of subject
+ \ez end of subject
+ \eG first matching position in subject
+.
+.
+.SH "REPORTED MATCH POINT SETTING"
+.rs
+.sp
+ \eK set reported start of match
+.sp
+From release 10.38 \eK is not permitted by default in lookaround assertions,
+for compatibility with Perl. However, if the PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK
+option is set, the previous behaviour is re-enabled. When this option is set,
+\eK is honoured in positive assertions, but ignored in negative ones.
+.
+.
+.SH "ALTERNATION"
+.rs
+.sp
+ expr|expr|expr...
+.
+.
+.SH "CAPTURING"
+.rs
+.sp
+ (...) capture group
+ (?...) named capture group (Perl)
+ (?'name'...) named capture group (Perl)
+ (?P...) named capture group (Python)
+ (?:...) non-capture group
+ (?|...) non-capture group; reset group numbers for
+ capture groups in each alternative
+.sp
+In non-UTF modes, names may contain underscores and ASCII letters and digits;
+in UTF modes, any Unicode letters and Unicode decimal digits are permitted. In
+both cases, a name must not start with a digit.
+.
+.
+.SH "ATOMIC GROUPS"
+.rs
+.sp
+ (?>...) atomic non-capture group
+ (*atomic:...) atomic non-capture group
+.
+.
+.SH "COMMENT"
+.rs
+.sp
+ (?#....) comment (not nestable)
+.
+.
+.SH "OPTION SETTING"
+.rs
+Changes of these options within a group are automatically cancelled at the end
+of the group.
+.sp
+ (?a) all ASCII options
+ (?aD) restrict \ed to ASCII in UCP mode
+ (?aS) restrict \es to ASCII in UCP mode
+ (?aW) restrict \ew to ASCII in UCP mode
+ (?aP) restrict all POSIX classes to ASCII in UCP mode
+ (?aT) restrict POSIX digit classes to ASCII in UCP mode
+ (?i) caseless
+ (?J) allow duplicate named groups
+ (?m) multiline
+ (?n) no auto capture
+ (?r) restrict caseless to either ASCII or non-ASCII
+ (?s) single line (dotall)
+ (?U) default ungreedy (lazy)
+ (?x) ignore white space except in classes or \eQ...\eE
+ (?xx) as (?x) but also ignore space and tab in classes
+ (?-...) unset the given option(s)
+ (?^) unset imnrsx options
+.sp
+(?aP) implies (?aT) as well, though this has no additional effect. However, it
+means that (?-aP) also implies (?-aT) and disables all ASCII restrictions for
+POSIX classes.
+.P
+Unsetting x or xx unsets both. Several options may be set at once, and a
+mixture of setting and unsetting such as (?i-x) is allowed, but there may be
+only one hyphen. Setting (but no unsetting) is allowed after (?^ for example
+(?^in). An option setting may appear at the start of a non-capture group, for
+example (?i:...).
+.P
+The following are recognized only at the very start of a pattern or after one
+of the newline or \eR sequences or options with similar syntax. More than one
+of them may appear. For the first three, d is a decimal number.
+.sp
+ (*LIMIT_DEPTH=d) set the backtracking limit to d
+ (*LIMIT_HEAP=d) set the heap size limit to d * 1024 bytes
+ (*LIMIT_MATCH=d) set the match limit to d
+ (*CASELESS_RESTRICT) set PCRE2_EXTRA_CASELESS_RESTRICT when matching
+ (*NOTEMPTY) set PCRE2_NOTEMPTY when matching
+ (*NOTEMPTY_ATSTART) set PCRE2_NOTEMPTY_ATSTART when matching
+ (*NO_AUTO_POSSESS) no auto-possessification (PCRE2_NO_AUTO_POSSESS)
+ (*NO_DOTSTAR_ANCHOR) no .* anchoring (PCRE2_NO_DOTSTAR_ANCHOR)
+ (*NO_JIT) disable JIT optimization
+ (*NO_START_OPT) no start-match optimization (PCRE2_NO_START_OPTIMIZE)
+ (*TURKISH_CASING) set PCRE2_EXTRA_TURKISH_CASING when matching
+ (*UTF) set appropriate UTF mode for the library in use
+ (*UCP) set PCRE2_UCP (use Unicode properties for \ed etc)
+.sp
+Note that LIMIT_DEPTH, LIMIT_HEAP, and LIMIT_MATCH can only reduce the value of
+the limits set by the caller of \fBpcre2_match()\fP or \fBpcre2_dfa_match()\fP,
+not increase them. LIMIT_RECURSION is an obsolete synonym for LIMIT_DEPTH. The
+application can lock out the use of (*UTF) and (*UCP) by setting the
+PCRE2_NEVER_UTF or PCRE2_NEVER_UCP options, respectively, at compile time.
+.
+.
+.SH "NEWLINE CONVENTION"
+.rs
+.sp
+These are recognized only at the very start of the pattern or after option
+settings with a similar syntax.
+.sp
+ (*CR) carriage return only
+ (*LF) linefeed only
+ (*CRLF) carriage return followed by linefeed
+ (*ANYCRLF) all three of the above
+ (*ANY) any Unicode newline sequence
+ (*NUL) the NUL character (binary zero)
+.
+.
+.SH "WHAT \eR MATCHES"
+.rs
+.sp
+These are recognized only at the very start of the pattern or after option
+setting with a similar syntax.
+.sp
+ (*BSR_ANYCRLF) CR, LF, or CRLF
+ (*BSR_UNICODE) any Unicode newline sequence
+.
+.
+.SH "LOOKAHEAD AND LOOKBEHIND ASSERTIONS"
+.rs
+.sp
+ (?=...) )
+ (*pla:...) ) positive lookahead
+ (*positive_lookahead:...) )
+.sp
+ (?!...) )
+ (*nla:...) ) negative lookahead
+ (*negative_lookahead:...) )
+.sp
+ (?<=...) )
+ (*plb:...) ) positive lookbehind
+ (*positive_lookbehind:...) )
+.sp
+ (? name
+ 'name' name
+.
+.
+.SH "SCRIPT RUNS"
+.rs
+.sp
+ (*script_run:...) ) script run, can be backtracked into
+ (*sr:...) )
+.sp
+ (*atomic_script_run:...) ) atomic script run
+ (*asr:...) )
+.
+.
+.SH "BACKREFERENCES"
+.rs
+.sp
+ \en reference by number (can be ambiguous)
+ \egn reference by number
+ \eg{n} reference by number
+ \eg+n relative reference by number (PCRE2 extension)
+ \eg-n relative reference by number
+ \eg{+n} relative reference by number (PCRE2 extension)
+ \eg{-n} relative reference by number
+ \ek reference by name (Perl)
+ \ek'name' reference by name (Perl)
+ \eg{name} reference by name (Perl)
+ \ek{name} reference by name (.NET)
+ (?P=name) reference by name (Python)
+.
+.
+.SH "SUBROUTINE REFERENCES (POSSIBLY RECURSIVE)"
+.rs
+.sp
+ (?R) recurse whole pattern
+ (?n) call subroutine by absolute number
+ (?+n) call subroutine by relative number
+ (?-n) call subroutine by relative number
+ (?&name) call subroutine by name (Perl)
+ (?P>name) call subroutine by name (Python)
+ \eg call subroutine by name (Oniguruma)
+ \eg'name' call subroutine by name (Oniguruma)
+ \eg call subroutine by absolute number (Oniguruma)
+ \eg'n' call subroutine by absolute number (Oniguruma)
+ \eg<+n> call subroutine by relative number (PCRE2 extension)
+ \eg'+n' call subroutine by relative number (PCRE2 extension)
+ \eg<-n> call subroutine by relative number (PCRE2 extension)
+ \eg'-n' call subroutine by relative number (PCRE2 extension)
+.sp
+The variants using parentheses (?...) may also specify a list of capture groups
+to return, which shall be retained in the calling subexpression if set during
+the recursion (this feature is not supported by Perl).
+.sp
+ (?R(grouplist)) recurse whole pattern, returning capture groups
+ (PCRE2 extension)
+ (?n(grouplist)) )
+ (?+n(grouplist)) ) call subroutine, returning capture groups
+ (?-n(grouplist)) ) (PCRE2 extension)
+ (?&name(grouplist)) )
+ (?P>name(grouplist)) )
+.sp
+The comma-separated list "grouplist" uses the same syntax as
+(*scan_substring:(grouplist)...), and may identify groups in any of the
+following ways:
+.sp
+ n absolute reference
+ +n relative reference
+ -n relative reference
+ name
+ 'name' name
+.
+.
+.SH "CONDITIONAL PATTERNS"
+.rs
+.sp
+ (?(condition)yes-pattern)
+ (?(condition)yes-pattern|no-pattern)
+.sp
+ (?(n) absolute reference condition
+ (?(+n) relative reference condition (PCRE2 extension)
+ (?(-n) relative reference condition (PCRE2 extension)
+ (?() named reference condition (Perl)
+ (?('name') named reference condition (Perl)
+ (?(name) named reference condition (PCRE2, deprecated)
+ (?(R) overall recursion condition
+ (?(Rn) specific numbered group recursion condition
+ (?(R&name) specific named group recursion condition
+ (?(DEFINE) define groups for reference
+ (?(VERSION[>]=n[.m]) test PCRE2 version
+ (?(assert) assertion condition
+.sp
+Note the ambiguity of (?(R) and (?(Rn) which might be named reference
+conditions or recursion tests. Such a condition is interpreted as a reference
+condition if the relevant named group exists.
+.sp
+The parts within brackets for the VERSION conditional syntax could be ommited.
+The fractional part of the version number defaults to 0 in that case.
+.
+.
+.SH "BACKTRACKING CONTROL"
+.rs
+.sp
+All backtracking control verbs may be in the form (*VERB:NAME). For (*MARK) the
+name is mandatory, for the others it is optional. (*SKIP) changes its behaviour
+if :NAME is present. The others just set a name for passing back to the caller,
+but this is not a name that (*SKIP) can see. The following act immediately they
+are reached:
+.sp
+ (*ACCEPT) force successful match
+ (*FAIL) force backtrack; synonym (*F)
+ (*MARK:NAME) set name to be passed back; synonym (*:NAME)
+.sp
+The following act only when a subsequent match failure causes a backtrack to
+reach them. They all force a match failure, but they differ in what happens
+afterwards. Those that advance the start-of-match point do so only if the
+pattern is not anchored.
+.sp
+ (*COMMIT) overall failure, no advance of starting point
+ (*PRUNE) advance to next starting character
+ (*SKIP) advance to current matching position
+ (*SKIP:NAME) advance to position corresponding to an earlier
+ (*MARK:NAME); if not found, the (*SKIP) is ignored
+ (*THEN) local failure, backtrack to next alternation
+.sp
+The effect of one of these verbs in a group called as a subroutine is confined
+to the subroutine call.
+.
+.
+.SH "CALLOUTS"
+.rs
+.sp
+ (?C) callout (assumed number 0)
+ (?Cn) callout with numerical data n
+ (?C"text") callout with string data
+.sp
+The allowed string delimiters are ` ' " ^ % # $ (which are the same for the
+start and the end), and the starting delimiter { matched with the ending
+delimiter }. To encode the ending delimiter within the string, double it.
+.
+.
+.SH "REPLACEMENT STRINGS"
+.rs
+.sp
+If the PCRE2_SUBSTITUTE_LITERAL option is set, a replacement string for
+\fBpcre2_substitute()\fP is not interpreted. Otherwise, by default, the only
+special character is the dollar character in one of the following forms:
+.sp
+ $$ insert a dollar character
+ $n or ${n} insert the contents of group \fIn\fP
+ $ insert the contents of named group
+ $0 or $& insert the entire matched substring
+ $` insert the substring that precedes the match
+ $' insert the substring that follows the match
+ $_ insert the entire input string
+ $+ insert the highest-numbered capture group which matched
+ $*MARK or ${*MARK} insert a control verb name
+.sp
+For ${n}, n can be a name or a number. If PCRE2_SUBSTITUTE_EXTENDED is set,
+there is additional interpretation:
+.P
+1. Backslash is an escape character, and the forms described in "ESCAPED
+CHARACTERS" above are recognized. Also:
+.sp
+ \eQ...\eE can be used to suppress interpretation
+ \el force the next character to lower case
+ \eu force the next character to upper case
+ \eL force subsequent characters to lower case
+ \eU force subsequent characters to upper case
+ \eu\eL force next character to upper case, then all lower
+ \el\eU force next character to lower case, then all upper
+ \eE end \eL or \eU case forcing
+ \eb backspace character (note: as in character class in pattern)
+ \ev vertical tab character (note: not the same as in a pattern)
+.sp
+2. The Python form \eg, where the angle brackets are part of the syntax and
+\fIn\fP is either a group name or a number, is recognized as an alternative way
+of inserting the contents of a group, for example \eg<3>.
+.P
+3. Capture substitution supports the following additional forms:
+.sp
+ ${n:-string} default for unset group
+ ${n:+string1:string2} values for set/unset group
+.sp
+The substitution strings themselves are expanded. Backslash can be used to
+escape colons and closing curly brackets.
+.
+.
+.SH "SEE ALSO"
+.rs
+.sp
+\fBpcre2pattern\fP(3), \fBpcre2api\fP(3), \fBpcre2callout\fP(3),
+\fBpcre2matching\fP(3), \fBpcre2\fP(3).
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 14 October 2025
+Copyright (c) 1997-2024 University of Cambridge.
+.fi
diff --git a/doc/pcre2test.1 b/doc/pcre2test.1
new file mode 100644
index 0000000..405578d
--- /dev/null
+++ b/doc/pcre2test.1
@@ -0,0 +1,2282 @@
+.TH PCRE2TEST 1 "22 August 2026" "PCRE2 10.48"
+.SH NAME
+pcre2test - a program for testing Perl-compatible regular expressions.
+.SH SYNOPSIS
+.rs
+.sp
+.B pcre2test "[options] [input file [output file]]"
+.sp
+\fBpcre2test\fP is a test program for the PCRE2 regular expression libraries,
+but it can also be used for experimenting with regular expressions. This
+document describes the features of the test program; for details of the regular
+expressions themselves, see the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+documentation. For details of the PCRE2 library function calls and their
+options, see the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation.
+.P
+The input for \fBpcre2test\fP is a sequence of regular expression patterns and
+subject strings to be matched. There are also command lines for setting
+defaults and controlling some special actions. The output shows the result of
+each match attempt. Modifiers on external or internal command lines, the
+patterns, and the subject lines specify PCRE2 function options, control how the
+subject is processed, and what output is produced.
+.P
+There are many obscure modifiers, some of which are specifically designed for
+use in conjunction with the test script and data files that are distributed as
+part of PCRE2. All the modifiers are documented here, some without much
+justification, but many of them are unlikely to be of use except when testing
+the libraries.
+.
+.
+.SH "PCRE2's 8-BIT, 16-BIT AND 32-BIT LIBRARIES"
+.rs
+.sp
+Different versions of the PCRE2 library can be built to support character
+strings that are encoded in 8-bit, 16-bit, or 32-bit code units. One, two, or
+all three of these libraries may be simultaneously installed. The
+\fBpcre2test\fP program can be used to test all the libraries. However, its own
+input and output are always in 8-bit format. When testing the 16-bit or 32-bit
+libraries, patterns and subject strings are converted to 16-bit or 32-bit
+format before being passed to the library functions. Results are converted back
+to 8-bit code units for output.
+.P
+In the rest of this document, the names of library functions and structures
+are given in generic form, for example, \fBpcre2_compile()\fP. The actual
+names used in the libraries have a suffix _8, _16, or _32, as appropriate.
+.
+.
+.\" HTML
+.SH "INPUT ENCODING"
+.rs
+.sp
+Input to \fBpcre2test\fP is processed line by line, either by calling the C
+library's \fBfgets()\fP function, or via the \fBlibreadline\fP or \fBlibedit\fP
+library. In some Windows environments character 26 (hex 1A) causes an immediate
+end of file, and no further data is read, so this character should be avoided
+unless you really want that action.
+.P
+The input is processed using C's string functions, so must not contain binary
+zeros, even though in Unix-like environments, \fBfgets()\fP treats any bytes
+other than newline as data characters. An error is generated if a binary zero
+is encountered. By default subject lines are processed for backslash escapes,
+which makes it possible to include any data value in strings that are passed to
+the library for matching. For patterns, there is a facility for specifying some
+or all of the 8-bit input characters as hexadecimal pairs, which makes it
+possible to include binary zeros.
+.
+.
+.SS "Input for the 16-bit and 32-bit libraries"
+.rs
+.sp
+When testing the 16-bit or 32-bit libraries, there is a need to be able to
+generate character code points greater than 255 in the strings that are passed
+to the library. For subject lines and some patterns, backslash escapes can be
+used. In addition, when the \fButf\fP modifier (see
+.\" HTML
+.\"
+"Setting compilation options"
+.\"
+below) is set, the pattern and any following subject lines are interpreted as
+UTF-8 strings and translated to UTF-16 or UTF-32 as appropriate.
+.P
+For non-UTF testing of wide characters, the \fButf8_input\fP modifier can be
+used. This is mutually exclusive with \fButf\fP, and is allowed only in 16-bit
+or 32-bit mode. It causes the pattern and following subject lines to be treated
+as UTF-8 according to the original definition (RFC 2279), which allows for
+character values up to 0x7fffffff. Each character is placed in one 16-bit or
+32-bit code unit (in the 16-bit case, values greater than 0xffff cause an error
+to occur).
+.P
+UTF-8 (in its original definition) is not capable of encoding values greater
+than 0x7fffffff, but such values can be handled by the 32-bit library. When
+testing this library in non-UTF mode with \fButf8_input\fP set, if any
+character is preceded by the byte 0xff (which is an invalid byte in UTF-8)
+0x80000000 is added to the character's value. For subject strings, using an
+escape sequence is preferable.
+.
+.
+.SH "COMMAND LINE OPTIONS"
+.rs
+.TP 10
+\fB-8\fP
+If the 8-bit library has been built, this option causes it to be used (this is
+the default). If the 8-bit library has not been built, this option causes an
+error.
+.TP 10
+\fB-16\fP
+If the 16-bit library has been built, this option causes it to be used. If the
+8-bit library has not been built, this is the default. If the 16-bit library
+has not been built, this option causes an error.
+.TP 10
+\fB-32\fP
+If the 32-bit library has been built, this option causes it to be used. If no
+other library has been built, this is the default. If the 32-bit library has
+not been built, this option causes an error.
+.TP 10
+\fB-ac\fP
+Behave as if each pattern has the \fBauto_callout\fP modifier, that is, insert
+automatic callouts into every pattern that is compiled.
+.TP 10
+\fB-AC\fP
+As for \fB-ac\fP, but in addition behave as if each subject line has the
+\fBcallout_extra\fP modifier, that is, show additional information from
+callouts.
+.TP 10
+\fB-b\fP
+Behave as if each pattern has the \fBfullbincode\fP modifier; the full
+internal binary form of the pattern is output after compilation.
+.TP 10
+\fB-C\fP
+Output the version number of the PCRE2 library, and all available information
+about the optional features that are included, and then exit with zero exit
+code. All other options are ignored. If both -C and -LM are present, whichever
+is first is recognized.
+.TP 10
+\fB-C\fP \fIoption\fP
+Output information about a specific build-time option, then exit. This
+functionality is intended for use in scripts such as \fBRunTest\fP. The
+following options output the value and set the exit code as indicated:
+.sp
+ linksize the configured internal link size (2, 3, or 4)
+ exit code is set to the link size
+ newline the default newline setting:
+ CR, LF, CRLF, ANYCRLF, ANY, or NUL
+ exit code is always 0
+ bsr the default setting for what \eR matches:
+ ANYCRLF or ANY
+ exit code is always 0
+.sp
+The following options output 1 for true or 0 for false, and set the exit code
+to the same value:
+.sp
+ backslash-C \eC is supported (not locked out)
+ ebcdic compiled for an EBCDIC environment
+ ebcdic-io if PCRE2 is compiled for EBCDIC, whether pcre2test's input and
+ output is EBCDIC or ASCII
+ ebcdic-nl25 if PCRE2 is compiled for EBCDIC, whether NL (= LF) is 0x25
+ (otherwise it is 0x15, the default)
+ jit just-in-time support is available
+ pcre2-16 the 16-bit library was built
+ pcre2-32 the 32-bit library was built
+ pcre2-8 the 8-bit library was built
+ unicode Unicode support is available
+.sp
+Note that the availability of JIT support in the library does not guarantee
+that it can actually be used because in some environments it is unable to
+allocate executable memory. The option "jitusable" gives more detailed
+information. It returns one of the following values:
+.sp
+ 0 JIT is available and usable
+ 1 JIT is available but cannot allocate executable memory
+ 2 JIT is not available
+ 3 Unexpected return from test call to \fBpcre2_jit_compile()\fP
+.sp
+If an unknown option is given, an error message is output; the exit code is 0.
+.TP 10
+\fB--colo[u]r[=]\fP
+With \fBauto\fP, the output is coloured if the output is to a terminal. Force or
+suppress output of ANSI colour escapes with \fBalways\fP (or no specifier
+provided) and \fBnever\fP respectively. If no colour option is provided, the
+default is \fBauto\fP, unless the NO_COLOR environment variable is defined and
+non-empty.
+.TP 10
+\fB-d\fP
+Behave as if each pattern has the \fBdebug\fP modifier; the internal
+form and information about the compiled pattern is output after compilation;
+\fB-d\fP is equivalent to \fB-b -i\fP.
+.TP 10
+\fB-dfa\fP
+Behave as if each subject line has the \fBdfa\fP modifier; matching is done
+using the \fBpcre2_dfa_match()\fP function instead of the default
+\fBpcre2_match()\fP.
+.TP 10
+\fB-E\fP
+Run in "preprocess only" mode (similar to "gcc -E"). The "#if ... #endif"
+commands are processed, and all other lines are printed verbatim.
+.TP 10
+\fB-error\fP \fInumber[,number,...]\fP
+Call \fBpcre2_get_error_message()\fP for each of the error numbers in the
+comma-separated list, display the resulting messages on the standard output,
+then exit with zero exit code. The numbers may be positive or negative. This is
+a convenience facility for PCRE2 maintainers.
+.TP 10
+\fB-help\fP
+Output a brief summary these options and then exit.
+.TP 10
+\fB-i\fP
+Behave as if each pattern has the \fBinfo\fP modifier; information about the
+compiled pattern is given after compilation.
+.TP 10
+\fB-jit\fP
+Behave as if each pattern line has the \fBjit\fP modifier; after successful
+compilation, each pattern is passed to the just-in-time compiler, if available.
+.TP 10
+\fB-jitfast\fP
+Behave as if each pattern line has the \fBjitfast\fP modifier; after
+successful compilation, each pattern is passed to the just-in-time compiler, if
+available, and each subject line is passed directly to the JIT matcher via its
+"fast path".
+.TP 10
+\fB-jitverify\fP
+Behave as if each pattern line has the \fBjitverify\fP modifier; after
+successful compilation, each pattern is passed to the just-in-time compiler, if
+available, and the use of JIT for matching is verified.
+.TP 10
+\fB-LM\fP
+List modifiers: write a list of available pattern and subject modifiers to the
+standard output, then exit with zero exit code. All other options are ignored.
+If both -C and any -Lx options are present, whichever is first is recognized.
+.TP 10
+\fB-LP\fP
+List properties: write a list of recognized Unicode properties to the standard
+output, then exit with zero exit code. All other options are ignored. If both
+-C and any -Lx options are present, whichever is first is recognized.
+.TP 10
+\fB-LS\fP
+List scripts: write a list of recognized Unicode script names to the standard
+output, then exit with zero exit code. All other options are ignored. If both
+-C and any -Lx options are present, whichever is first is recognized.
+.TP 10
+\fB-malloc\fP
+Exercise malloc() failures, by first counting the number of calls made to malloc
+during pattern compilation and matching, then re-running the compilation and
+matching that many times, exercising a failure of each malloc() call.
+.TP 10
+\fB-pattern\fP \fImodifier-list\fP
+Behave as if each pattern line contains the given modifiers.
+.TP 10
+\fB-q\fP
+Do not output the version number of \fBpcre2test\fP at the start of execution.
+.TP 10
+\fB-S\fP \fIsize\fP
+On Unix-like systems, set the size of the run-time stack to \fIsize\fP
+mebibytes (units of 1024*1024 bytes).
+.TP 10
+\fB-subject\fP \fImodifier-list\fP
+Behave as if each subject line contains the given modifiers.
+.TP 10
+\fB-t\fP
+Run each compile and match many times with a timer, and output the resulting
+times per compile or match. When JIT is used, separate times are given for the
+initial compile and the JIT compile. You can control the number of iterations
+that are used for timing by following \fB-t\fP with a number (as a separate
+item on the command line). For example, "-t 1000" iterates 1000 times. The
+default is to iterate 500,000 times.
+.TP 10
+\fB-tm\fP
+This is like \fB-t\fP except that it times only the matching phase, not the
+compile phase.
+.TP 10
+\fB-T\fP \fB-TM\fP
+These behave like \fB-t\fP and \fB-tm\fP, but in addition, at the end of a run,
+the total times for all compiles and matches are output.
+.TP 10
+\fB-unittest\fP
+Run a fixed set of additional tests of the PCRE2 API which are not driven by
+the test input files, and then exit.
+.TP 10
+\fB-version\fP
+Output the PCRE2 version number and then exit.
+.
+.
+.SH "DESCRIPTION"
+.rs
+.sp
+If \fBpcre2test\fP is given two filename arguments, it reads from the first and
+writes to the second. If the first name is "-", input is taken from the
+standard input. If \fBpcre2test\fP is given only one argument, it reads from
+that file and writes to stdout. Otherwise, it reads from stdin and writes to
+stdout.
+.P
+When \fBpcre2test\fP is built, a configuration option can specify that it
+should be linked with the \fBlibreadline\fP or \fBlibedit\fP library. When this
+is done, if the input is from a terminal, it is read using the \fBreadline()\fP
+function. This provides line-editing and history facilities. The output from
+the \fB-help\fP option states whether or not \fBreadline()\fP will be used.
+.P
+The program handles any number of tests, each of which consists of a set of
+input lines. Each set starts with a regular expression pattern, followed by any
+number of subject lines to be matched against that pattern. In between sets of
+test data, command lines that begin with # may appear. This file format, with
+some restrictions, can also be processed by the \fBperltest.sh\fP script that
+is distributed with PCRE2 as a means of checking that the behaviour of PCRE2
+and Perl is the same. For a specification of \fBperltest.sh\fP, see the
+comments near its beginning. See also the #perltest command below.
+.P
+When the input is a terminal, \fBpcre2test\fP prompts for each line of input,
+using "re>" to prompt for regular expression patterns, and "data>" to prompt
+for subject lines. Command lines starting with # can be entered only in
+response to the "re>" prompt.
+.P
+Each subject line is matched separately and independently. If you want to do
+multi-line matches, you have to use the \en escape sequence (or \er or \er\en,
+etc., depending on the newline setting) in a single line of input to encode the
+newline sequences. There is no limit on the length of subject lines; the input
+buffer is automatically extended if it is too small. There are replication
+features that makes it possible to generate long repetitive pattern or subject
+lines without having to supply them explicitly.
+.P
+An empty line or the end of the file signals the end of the subject lines for a
+test, at which point a new pattern or command line is expected if there is
+still input to be read.
+.
+.
+.SH "COMMAND LINES"
+.rs
+.sp
+In between sets of test data, a line that begins with # is interpreted as a
+command line. If the first character is followed by white space or an
+exclamation mark, the line is treated as a comment, and ignored. Otherwise, the
+following commands are recognized:
+.sp
+ #forbid_utf
+.sp
+Subsequent patterns automatically have the PCRE2_NEVER_UTF and PCRE2_NEVER_UCP
+options set, which locks out the use of the PCRE2_UTF and PCRE2_UCP options and
+the use of (*UTF) and (*UCP) at the start of patterns. This command also forces
+an error if a subsequent pattern contains any occurrences of \eP, \ep, or \eX,
+which are still supported when PCRE2_UTF is not set, but which require Unicode
+property support to be included in the library.
+.P
+This is a trigger guard that is used in test files to ensure that UTF or
+Unicode property tests are not accidentally added to files that are used when
+Unicode support is not included in the library. Setting PCRE2_NEVER_UTF and
+PCRE2_NEVER_UCP as a default can also be obtained by the use of \fB#pattern\fP;
+the difference is that \fB#forbid_utf\fP cannot be unset, and the automatic
+options are not displayed in pattern information, to avoid cluttering up test
+output.
+.sp
+ #load
+.sp
+This command is used to load a set of precompiled patterns from a file, as
+described in the section entitled "Saving and restoring compiled patterns"
+.\" HTML
+.\"
+below.
+.\"
+.sp
+ #loadtables
+.sp
+This command is used to load a set of binary character tables that can be
+accessed by the tables=3 qualifier. Such tables can be created by the
+\fBpcre2_dftables\fP program with the -b option.
+.sp
+ #newline_default []
+.sp
+When PCRE2 is built, a default newline convention can be specified. This
+determines which characters and/or character pairs are recognized as indicating
+a newline in a pattern or subject string. The default can be overridden when a
+pattern is compiled. The standard test files contain tests of various newline
+conventions, but the majority of the tests expect a single linefeed to be
+recognized as a newline by default. Without special action the tests would fail
+when PCRE2 is compiled with either CR or CRLF as the default newline.
+.P
+The #newline_default command specifies a list of newline types that are
+acceptable as the default. The types must be one of CR, LF, CRLF, ANYCRLF,
+ANY, or NUL (in upper or lower case), for example:
+.sp
+ #newline_default LF Any anyCRLF
+.sp
+If the default newline is in the list, this command has no effect. Otherwise,
+except when testing the POSIX API, a \fBnewline\fP modifier that specifies the
+first newline convention in the list (LF in the above example) is added to any
+pattern that does not already have a \fBnewline\fP modifier. If the newline
+list is empty, the feature is turned off. This command is present in a number
+of the standard test input files.
+.P
+When the POSIX API is being tested there is no way to override the default
+newline convention, though it is possible to set the newline convention from
+within the pattern. A warning is given if the \fBposix\fP or \fBposix_nosub\fP
+modifier is used when \fB#newline_default\fP would set a default for the
+non-POSIX API.
+.sp
+ #pattern
+.sp
+This command sets a default modifier list that applies to all subsequent
+patterns. Modifiers on a pattern can change these settings.
+.sp
+ #perltest
+.sp
+This line is used in test files that can also be processed by \fBperltest.sh\fP
+to confirm that Perl gives the same results as PCRE2. Subsequent tests are
+checked for the use of \fBpcre2test\fP features that are incompatible with the
+\fBperltest.sh\fP script.
+.P
+Patterns must use '/' as their delimiter, and only certain modifiers are
+supported. Comment lines, #pattern commands, and #subject commands that set or
+unset "mark" are recognized and acted on. The #perltest, #forbid_utf, and
+#newline_default commands, which are needed in the relevant pcre2test files,
+are silently ignored. All other command lines are ignored, but give a warning
+message. The \fB#perltest\fP command helps detect tests that are accidentally
+put in the wrong file or use the wrong delimiter. For more details of the
+\fBperltest.sh\fP script see the comments it contains.
+.sp
+ #pop []
+ #popcopy []
+.sp
+These commands are used to manipulate the stack of compiled patterns, as
+described in the section entitled "Saving and restoring compiled patterns"
+.\" HTML
+.\"
+below.
+.\"
+.sp
+ #save
+.sp
+This command is used to save a set of compiled patterns to a file, as described
+in the section entitled "Saving and restoring compiled patterns"
+.\" HTML
+.\"
+below.
+.\"
+.sp
+ #subject
+.sp
+This command sets a default modifier list that applies to all subsequent
+subject lines. Modifiers on a subject line can change these settings.
+.sp
+ #if CONDITION
+ ...
+ #endif
+.sp
+If CONDITION is true, then the command is printed, and its contents are
+processed as normal, including printing the commandlines to the output. If
+CONDITION is false, then all lines between the "#if" and "#endif" are skipped
+and not printed. The CONDITION can be any of the conditions which are tested by
+the "-C" commandline option and which set pcre2test's exit code to a boolean
+value. The CONDITION may also be preceded by "!".
+.
+.
+.SH "MODIFIER SYNTAX"
+.rs
+.sp
+Modifier lists are used with both pattern and subject lines. Items in a list
+are separated by commas followed by optional white space. Trailing white space
+in a modifier list is ignored. Some modifiers may be given for both patterns
+and subject lines, whereas others are valid only for one or the other. Each
+modifier has a long name, for example "anchored", and some of them must be
+followed by an equals sign and a value, for example, "offset=12". Values cannot
+contain comma characters, but may contain spaces. Modifiers that do not take
+values may be preceded by a minus sign to turn off a previous setting.
+.P
+A few of the more common modifiers can also be specified as single letters, for
+example "i" for "caseless". In documentation, following the Perl convention,
+these are written with a slash ("the /i modifier") for clarity. Abbreviated
+modifiers must all be concatenated in the first item of a modifier list. If the
+first item is not recognized as a long modifier name, it is interpreted as a
+sequence of these abbreviations. For example:
+.sp
+ /abc/ig,newline=cr,jit=3
+.sp
+This is a pattern line whose modifier list starts with two one-letter modifiers
+(/i and /g). The lower-case abbreviated modifiers are the same as used in Perl.
+.
+.
+.SH "PATTERN SYNTAX"
+.rs
+.sp
+A pattern line must start with one of the following characters (common symbols,
+excluding pattern meta-characters):
+.sp
+ / ! " ' ` - = _ : ; , % & @ ~
+.sp
+This is interpreted as the pattern's delimiter. A regular expression may be
+continued over several input lines, in which case the newline characters are
+included within it. It is possible to include the delimiter as a literal within
+the pattern by escaping it with a backslash, for example
+.sp
+ /abc\e/def/
+.sp
+If you do this, the escape and the delimiter form part of the pattern, but
+since the delimiters are all non-alphanumeric, the inclusion of the backslash
+does not affect the pattern's interpretation. Note, however, that this trick
+does not work within \eQ...\eE literal bracketing because the backslash will
+itself be interpreted as a literal. If the terminating delimiter is immediately
+followed by a backslash, for example,
+.sp
+ /abc/\e
+.sp
+a backslash is added to the end of the pattern. This is done to provide a way
+of testing the error condition that arises if a pattern finishes with a
+backslash, because
+.sp
+ /abc\e/
+.sp
+is interpreted as the first line of a pattern that starts with "abc/", causing
+pcre2test to read the next line as a continuation of the regular expression.
+.P
+A pattern can be followed by a modifier list (details below).
+.
+.
+.SH "SUBJECT LINE SYNTAX"
+.rs
+.sp
+Before each subject line is passed to \fBpcre2_match()\fP,
+\fBpcre2_dfa_match()\fP, or \fBpcre2_jit_match()\fP, leading and trailing white
+space is removed, and the line is scanned for backslash escapes, unless the
+\fBsubject_literal\fP modifier was set for the pattern. The following provide a
+means of encoding non-printing characters in a visible way:
+.sp
+ \ea alarm (BEL, \ex07)
+ \eb backspace (\ex08)
+ \ee escape (\ex27)
+ \ef form feed (\ex0c)
+ \en newline (\ex0a)
+ \eN{U+hh...} unicode character (any number of hex digits)
+ \er carriage return (\ex0d)
+ \et tab (\ex09)
+ \ev vertical tab (\ex0b)
+ \eddd octal number (up to 3 octal digits); represent a single
+ code point unless larger than 255 with the 8-bit library
+ \eo{dd...} octal number (any number of octal digits} representing a
+ character in UTF mode or a code point
+ \exhh hexadecimal byte (up to 2 hex digits)
+ \ex{hh...} hexadecimal number (up to 8 hex digits) representing a
+ character in UTF mode or a code point
+.sp
+Invoking \eN{U+hh...} or \ex{hh...} doesn't require the use of the \fButf\fP
+modifier on the pattern. It is always recognized. There may be any number of
+hexadecimal digits inside the braces; invalid values provoke error messages
+but when using \eN{U+hh...} with some invalid unicode characters they will
+be accepted with a warning instead.
+.P
+Note that even in UTF-8 mode, \exhh (and depending of how large, \eddd)
+describe one byte rather than one character; this makes it possible to
+construct invalid UTF-8 sequences for testing purposes. On the other hand,
+\ex{hh...} is interpreted as a UTF-8 character in UTF-8 mode, only generating
+more than one byte if the value is greater than 127. To avoid the ambiguity
+it is preferred to use \eN{U+hh...} when describing characters. When testing
+the 8-bit library not in UTF-8 mode, \ex{hh} generates one byte for values
+that could fit on it, and causes an error for greater values.
+.P
+When testing the 16-bit library, not in UTF-16 mode, all 4-digit \ex{hhhh}
+values are accepted. This makes it possible to construct invalid UTF-16
+sequences for testing purposes.
+.P
+When testing the 32-bit library, not in UTF-32 mode, all 4 to 8-digit \ex{...}
+values are accepted. This makes it possible to construct invalid UTF-32
+sequences for testing purposes.
+.P
+There is a special backslash sequence that specifies replication of one or more
+characters:
+.sp
+ \e[]{}
+.sp
+This makes it possible to test long strings without having to provide them as
+part of the file. For example:
+.sp
+ \e[abc]{4}
+.sp
+is converted to "abcabcabcabc". This feature does not support nesting. To
+include a closing square bracket in the characters, code it as \ex5D.
+.P
+A backslash followed by an equals sign marks the end of the subject string and
+the start of a modifier list. For example:
+.sp
+ abc\e=notbol,notempty
+.sp
+If the subject string is empty and \e= is followed by white space, the line is
+treated as a comment line, and is not used for matching. For example:
+.sp
+ \e= This is a comment.
+ abc\e= This is an invalid modifier list.
+.sp
+A backslash followed by any other non-alphanumeric character just escapes that
+character. A backslash followed by anything else causes an error. However, if
+the very last character in the line is a backslash (and there is no modifier
+list), it is ignored. This gives a way of passing an empty line as data, since
+a real empty line terminates the data input.
+.P
+If the \fBsubject_literal\fP modifier is set for a pattern, all subject lines
+that follow are treated as literals, with no special treatment of backslashes.
+No replication is possible, and any subject modifiers must be set as defaults
+by a \fB#subject\fP command.
+.
+.
+.SH "PATTERN MODIFIERS"
+.rs
+.sp
+There are several types of modifier that can appear in pattern lines. Except
+where noted below, they may also be used in \fB#pattern\fP commands. A
+pattern's modifier list can add to or override default modifiers that were set
+by a previous \fB#pattern\fP command.
+.
+.
+.\" HTML
+.SS "Setting compilation options"
+.rs
+.sp
+The following modifiers set options for \fBpcre2_compile()\fP. Most of them set
+bits in the options argument of that function, but those whose names start with
+PCRE2_EXTRA are additional options that are set in the compile context.
+Some of these options have single-letter abbreviations. There is special
+handling for /x: if a second x is present, PCRE2_EXTENDED is converted into
+PCRE2_EXTENDED_MORE as in Perl. A third appearance adds PCRE2_EXTENDED as well,
+though this makes no difference to the way \fBpcre2_compile()\fP behaves. See
+.\" HREF
+\fBpcre2api\fP
+.\"
+for a description of the effects of these options.
+.sp
+ allow_empty_class set PCRE2_ALLOW_EMPTY_CLASS
+ allow_lookaround_bsk set PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK
+ allow_surrogate_escapes set PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES
+ alt_bsux set PCRE2_ALT_BSUX
+ alt_circumflex set PCRE2_ALT_CIRCUMFLEX
+ alt_extended_class set PCRE2_ALT_EXTENDED_CLASS
+ alt_verbnames set PCRE2_ALT_VERBNAMES
+ anchored set PCRE2_ANCHORED
+ /a ascii_all set all ASCII options
+ ascii_bsd set PCRE2_EXTRA_ASCII_BSD
+ ascii_bss set PCRE2_EXTRA_ASCII_BSS
+ ascii_bsw set PCRE2_EXTRA_ASCII_BSW
+ ascii_digit set PCRE2_EXTRA_ASCII_DIGIT
+ ascii_posix set PCRE2_EXTRA_ASCII_POSIX
+ auto_callout set PCRE2_AUTO_CALLOUT
+ bad_escape_is_literal set PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL
+ /i caseless set PCRE2_CASELESS
+ /r caseless_restrict set PCRE2_EXTRA_CASELESS_RESTRICT
+ dollar_endonly set PCRE2_DOLLAR_ENDONLY
+ /s dotall set PCRE2_DOTALL
+ dupnames set PCRE2_DUPNAMES
+ endanchored set PCRE2_ENDANCHORED
+ escaped_cr_is_lf set PCRE2_EXTRA_ESCAPED_CR_IS_LF
+ /x extended set PCRE2_EXTENDED
+ /xx extended_more set PCRE2_EXTENDED_MORE
+ extra_alt_bsux set PCRE2_EXTRA_ALT_BSUX
+ firstline set PCRE2_FIRSTLINE
+ literal set PCRE2_LITERAL
+ match_line set PCRE2_EXTRA_MATCH_LINE
+ match_invalid_utf set PCRE2_MATCH_INVALID_UTF
+ match_unset_backref set PCRE2_MATCH_UNSET_BACKREF
+ match_word set PCRE2_EXTRA_MATCH_WORD
+ /m multiline set PCRE2_MULTILINE
+ never_backslash_c set PCRE2_NEVER_BACKSLASH_C
+ never_callout set PCRE2_EXTRA_NEVER_CALLOUT
+ never_ucp set PCRE2_NEVER_UCP
+ never_utf set PCRE2_NEVER_UTF
+ /n no_auto_capture set PCRE2_NO_AUTO_CAPTURE
+ no_auto_possess set PCRE2_NO_AUTO_POSSESS
+ no_bs0 set PCRE2_EXTRA_NO_BS0
+ no_dotstar_anchor set PCRE2_NO_DOTSTAR_ANCHOR
+ no_start_optimize set PCRE2_NO_START_OPTIMIZE
+ no_utf_check set PCRE2_NO_UTF_CHECK
+ python_octal set PCRE2_EXTRA_PYTHON_OCTAL
+ turkish_casing set PCRE2_EXTRA_TURKISH_CASING
+ ucp set PCRE2_UCP
+ ungreedy set PCRE2_UNGREEDY
+ use_offset_limit set PCRE2_USE_OFFSET_LIMIT
+ utf set PCRE2_UTF
+.sp
+As well as turning on the PCRE2_UTF option, the \fButf\fP modifier causes all
+non-printing characters in output strings to be printed using the \ex{hh...}
+notation. Otherwise, those less than 0x100 are output in hex without the curly
+brackets. Setting \fButf\fP in 16-bit or 32-bit mode also causes pattern and
+subject strings to be translated to UTF-16 or UTF-32, respectively, before
+being passed to library functions.
+.sp
+The following modifiers enable or disable performance optimizations by
+calling \fBpcre2_set_optimize()\fP before invoking the regex compiler.
+.sp
+ optimization_full enable all optional optimizations
+ optimization_none disable all optional optimizations
+ auto_possess auto-possessify variable quantifiers
+ auto_possess_off don't auto-possessify variable quantifiers
+ dotstar_anchor anchor patterns starting with .*
+ dotstar_anchor_off don't anchor patterns starting with .*
+ start_optimize enable pre-scan of subject string
+ start_optimize_off disable pre-scan of subject string
+.sp
+See the
+.\" HREF
+\fBpcre2_set_optimize\fP
+.\"
+documentation for details on these optimizations.
+.
+.
+.\" HTML
+.SS "Setting compilation controls"
+.rs
+.sp
+The following modifiers affect the compilation process or request information
+about the pattern. There are single-letter abbreviations for some that are
+heavily used in the test files.
+.sp
+ /B bincode show binary code without lengths
+ bsr=[anycrlf|unicode] specify \eR handling
+ callout_info show callout information
+ convert= request foreign pattern conversion
+ convert_glob_escape=c set glob escape character
+ convert_glob_separator=c set glob separator character
+ convert_length set convert buffer length
+ debug same as info,fullbincode
+ expand expand repetition syntax in pattern
+ framesize show matching frame size
+ fullbincode show binary code with lengths
+ /I info show info about compiled pattern
+ hex unquoted characters are hexadecimal
+ jit[=] use JIT
+ jitfast use JIT fast path
+ jitverify verify JIT use
+ locale= use this locale
+ max_pattern_compiled ) set maximum compiled pattern
+ _length= ) length (bytes)
+ max_pattern_length= set maximum pattern length (code units)
+ max_varlookbehind= set maximum variable lookbehind length
+ memory show memory used
+ newline= set newline type
+ null_context compile with a NULL context
+ null_pattern pass pattern as NULL
+ parens_nest_limit= set maximum parentheses depth
+ posix use the POSIX API
+ posix_nosub use the POSIX API with REG_NOSUB
+ push push compiled pattern onto the stack
+ pushcopy push a copy onto the stack
+ pushtablescopy push a copy with tables onto the stack
+ stackguard= test the stackguard feature
+ subject_literal treat all subject lines as literal
+ tables=[0|1|2|3] select internal tables
+ use_length do not zero-terminate the pattern
+ utf8_input treat input as UTF-8
+.sp
+The effects of these modifiers are described in the following sections.
+.
+.
+.SS "Newline and \eR handling"
+.rs
+.sp
+The \fBbsr\fP modifier specifies what \eR in a pattern should match. If it is
+set to "anycrlf", \eR matches CR, LF, or CRLF only. If it is set to "unicode",
+\eR matches any Unicode newline sequence. The default can be specified when
+PCRE2 is built; if it is not, the default is set to Unicode.
+.P
+The \fBnewline\fP modifier specifies which characters are to be interpreted as
+newlines, both in the pattern and in subject lines. The type must be one of CR,
+LF, CRLF, ANYCRLF, ANY, or NUL (in upper or lower case).
+.
+.
+.SS "Information about a pattern"
+.rs
+.sp
+The \fBdebug\fP modifier is a shorthand for \fBinfo,fullbincode\fP, requesting
+all available information.
+.P
+The \fBbincode\fP modifier causes a representation of the compiled code to be
+output after compilation. This information does not contain length and offset
+values, which ensures that the same output is generated for different internal
+link sizes and different code unit widths. By using \fBbincode\fP, the same
+regression tests can be used in different environments.
+.P
+The \fBfullbincode\fP modifier, by contrast, \fIdoes\fP include length and
+offset values. This is used in a few special tests that run only for specific
+code unit widths and link sizes, and is also useful for one-off tests.
+.P
+The \fBinfo\fP modifier requests information about the compiled pattern
+(whether it is anchored, has a fixed first character, and so on). The
+information is obtained from the \fBpcre2_pattern_info()\fP function. Here are
+some typical examples:
+.sp
+ re> /(?i)(^a|^b)/m,info
+ Capture group count = 1
+ Compile options: multiline
+ Overall options: caseless multiline
+ First code unit at start or follows newline
+ Subject length lower bound = 1
+.sp
+ re> /(?i)abc/info
+ Capture group count = 0
+ Compile options:
+ Overall options: caseless
+ First code unit = 'a' (caseless)
+ Last code unit = 'c' (caseless)
+ Subject length lower bound = 3
+.sp
+"Compile options" are those specified by modifiers; "overall options" have
+added options that are taken or deduced from the pattern. If both sets of
+options are the same, just a single "options" line is output; if there are no
+options, the line is omitted. "First code unit" is where any match must start;
+if there is more than one they are listed as "starting code units". "Last code
+unit" is the last literal code unit that must be present in any match. This is
+not necessarily the last character. These lines are omitted if no starting or
+ending code units are recorded. The subject length line is omitted when
+\fBno_start_optimize\fP is set because the minimum length is not calculated
+when it can never be used.
+.P
+The \fBframesize\fP modifier shows the size, in bytes, of each storage frame
+used by \fBpcre2_match()\fP for handling backtracking. The size depends on the
+number of capturing parentheses in the pattern. A vector of these frames is
+used at matching time; its overall size is shown when the \fBheapframes_size\fP
+subject modifier is set.
+.P
+The \fBcallout_info\fP modifier requests information about all the callouts in
+the pattern. A list of them is output at the end of any other information that
+is requested. For each callout, either its number or string is given, followed
+by the item that follows it in the pattern.
+.
+.
+.SS "Passing a NULL context"
+.rs
+.sp
+Normally, \fBpcre2test\fP passes a context block to \fBpcre2_compile()\fP. If
+the \fBnull_context\fP modifier is set, however, NULL is passed. This is for
+testing that \fBpcre2_compile()\fP behaves correctly in this case (it uses
+default values).
+.
+.
+.SS "Passing a NULL pattern"
+.rs
+.sp
+The \fBnull_pattern\fP modifier is for testing the behaviour of
+\fBpcre2_compile()\fP when the pattern argument is NULL. The length value
+passed is the default PCRE2_ZERO_TERMINATED unless \fBuse_length\fP is set.
+Any length other than zero causes an error.
+.
+.
+.SS "Specifying pattern characters in hexadecimal"
+.rs
+.sp
+The \fBhex\fP modifier specifies that the characters of the pattern, except for
+substrings enclosed in single or double quotes, are to be interpreted as pairs
+of hexadecimal digits. This feature is provided as a way of creating patterns
+that contain binary zeros and other non-printing characters. White space is
+permitted between pairs of digits. For example, this pattern contains three
+characters:
+.sp
+ /ab 32 59/hex
+.sp
+Parts of such a pattern are taken literally if quoted. This pattern contains
+nine characters, only two of which are specified in hexadecimal:
+.sp
+ /ab "literal" 32/hex
+.sp
+Either single or double quotes may be used. There is no way of including
+the delimiter within a substring. The \fBhex\fP and \fBexpand\fP modifiers are
+mutually exclusive.
+.
+.
+.SS "Specifying the pattern's length"
+.rs
+.sp
+By default, patterns are passed to the compiling functions as zero-terminated
+strings but can be passed by length instead of being zero-terminated. The
+\fBuse_length\fP modifier causes this to happen. Using a length happens
+automatically (whether or not \fBuse_length\fP is set) when \fBhex\fP is set,
+because patterns specified in hexadecimal may contain binary zeros.
+.P
+If \fBhex\fP or \fBuse_length\fP is used with the POSIX wrapper API (see
+.\" HTML
+.\"
+"Using the POSIX wrapper API"
+.\"
+below), the REG_PEND extension is used to pass the pattern's length.
+.
+.
+.SS "Specifying a maximum for variable lookbehinds"
+.rs
+.sp
+Variable lookbehind assertions are supported only if, for each one, there is a
+maximum length (in characters) that it can match. There is a limit on this,
+whose default can be set at build time, with an ultimate default of 255. The
+\fBmax_varlookbehind\fP modifier uses the \fBpcre2_set_max_varlookbehind()\fP
+function to change the limit. Lookbehinds whose branches each match a fixed
+length are limited to 65535 characters per branch.
+.
+.
+.SS "Specifying wide characters in 16-bit and 32-bit modes"
+.rs
+.sp
+In 16-bit and 32-bit modes, all input is automatically treated as UTF-8 and
+translated to UTF-16 or UTF-32 when the \fButf\fP modifier is set. For testing
+the 16-bit and 32-bit libraries in non-UTF mode, the \fButf8_input\fP modifier
+can be used. It is mutually exclusive with \fButf\fP. Input lines are
+interpreted as UTF-8 as a means of specifying wide characters. More details are
+given in
+.\" HTML
+.\"
+"Input encoding"
+.\"
+above.
+.
+.
+.SS "Generating long repetitive patterns"
+.rs
+.sp
+Some tests use long patterns that are very repetitive. Instead of creating a
+very long input line for such a pattern, you can use a special repetition
+feature, similar to the one described for subject lines above. If the
+\fBexpand\fP modifier is present on a pattern, parts of the pattern that have
+the form
+.sp
+ \e[]{}
+.sp
+are expanded before the pattern is passed to \fBpcre2_compile()\fP. For
+example, \e[AB]{6000} is expanded to "ABAB..." 6000 times. This construction
+cannot be nested. An initial "\e[" sequence is recognized only if "]{" followed
+by decimal digits and "}" is found later in the pattern. If not, the characters
+remain in the pattern unaltered. The \fBexpand\fP and \fBhex\fP modifiers are
+mutually exclusive.
+.P
+If part of an expanded pattern looks like an expansion, but is really part of
+the actual pattern, unwanted expansion can be avoided by giving two values in
+the quantifier. For example, \e[AB]{6000,6000} is not recognized as an
+expansion item.
+.P
+If the \fBinfo\fP modifier is set on an expanded pattern, the result of the
+expansion is included in the information that is output.
+.
+.
+.SS "JIT compilation"
+.rs
+.sp
+Just-in-time (JIT) compiling is a heavyweight optimization that can greatly
+speed up pattern matching. See the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+documentation for details. JIT compiling happens, optionally, after a pattern
+has been successfully compiled into an internal form. The JIT compiler converts
+this to optimized machine code. It needs to know whether the match-time options
+PCRE2_PARTIAL_HARD and PCRE2_PARTIAL_SOFT are going to be used, because
+different code is generated for the different cases. See the \fBpartial\fP
+modifier in "Subject Modifiers"
+.\" HTML
+.\"
+below
+.\"
+for details of how these options are specified for each match attempt.
+.P
+JIT compilation is requested by the \fBjit\fP pattern modifier, which may
+optionally be followed by an equals sign and a number in the range 0 to 7.
+The three bits that make up the number specify which of the three JIT operating
+modes are to be compiled:
+.sp
+ 1 compile JIT code for non-partial matching
+ 2 compile JIT code for soft partial matching
+ 4 compile JIT code for hard partial matching
+.sp
+The possible values for the \fBjit\fP modifier are therefore:
+.sp
+ 0 disable JIT
+ 1 normal matching only
+ 2 soft partial matching only
+ 3 normal and soft partial matching
+ 4 hard partial matching only
+ 6 soft and hard partial matching only
+ 7 all three modes
+.sp
+If no number is given, 7 is assumed. The phrase "partial matching" means a call
+to \fBpcre2_match()\fP with either the PCRE2_PARTIAL_SOFT or the
+PCRE2_PARTIAL_HARD option set. Note that such a call may return a complete
+match; the options enable the possibility of a partial match, but do not
+require it. Note also that if you request JIT compilation only for partial
+matching (for example, jit=2) but do not set the \fBpartial\fP modifier on a
+subject line, that match will not use JIT code because none was compiled for
+non-partial matching.
+.P
+If JIT compilation is successful, the compiled JIT code will automatically be
+used when an appropriate type of match is run, except when incompatible
+run-time options are specified. For more details, see the
+.\" HREF
+\fBpcre2jit\fP
+.\"
+documentation. See also the \fBjitstack\fP modifier below for a way of
+setting the size of the JIT stack.
+.P
+If the \fBjitfast\fP modifier is specified, matching is done using the JIT
+"fast path" interface, \fBpcre2_jit_match()\fP, which skips some of the sanity
+checks that are done by \fBpcre2_match()\fP, and of course does not work when
+JIT is not supported. If \fBjitfast\fP is specified without \fBjit\fP, jit=7 is
+assumed.
+.P
+If the \fBjitverify\fP modifier is specified, information about the compiled
+pattern shows whether JIT compilation was or was not successful. If
+\fBjitverify\fP is specified without \fBjit\fP, jit=7 is assumed. If JIT
+compilation is successful when \fBjitverify\fP is set, the text "(JIT)" is
+added to the first output line after a match or non match when JIT-compiled
+code was actually used in the match.
+.
+.
+.SS "Setting a locale"
+.rs
+.sp
+The \fBlocale\fP modifier must specify the name of a locale, for example:
+.sp
+ /pattern/locale=fr_FR
+.sp
+The given locale is set, \fBpcre2_maketables()\fP is called to build a set of
+character tables for the locale, and this is then passed to
+\fBpcre2_compile()\fP when compiling the regular expression. The same tables
+are used when matching the following subject lines. The \fBlocale\fP modifier
+applies only to the pattern on which it appears, but can be given in a
+\fB#pattern\fP command if a default is needed. Setting a locale and alternate
+character tables are mutually exclusive.
+.
+.
+.SS "Showing pattern memory"
+.rs
+.sp
+The \fBmemory\fP modifier causes the size in bytes of the memory used to hold
+the compiled pattern to be output. This does not include the size of the
+\fBpcre2_code\fP block; it is just the actual compiled data. If the pattern is
+subsequently passed to the JIT compiler, the size of the JIT compiled code is
+also output. Here is an example:
+.sp
+ re> /a(b)c/jit,memory
+ Memory allocation (code space): 21
+ Memory allocation (JIT code): 1910
+.sp
+.
+.
+.SS "Limiting nested parentheses"
+.rs
+.sp
+The \fBparens_nest_limit\fP modifier sets a limit on the depth of nested
+parentheses in a pattern. Breaching the limit causes a compilation error.
+The default for the library is set when PCRE2 is built, but \fBpcre2test\fP
+sets its own default of 220, which is required for running the standard test
+suite.
+.
+.
+.SS "Limiting the pattern length"
+.rs
+.sp
+The \fBmax_pattern_length\fP modifier sets a limit, in code units, to the
+length of pattern that \fBpcre2_compile()\fP will accept. Breaching the limit
+causes a compilation error. The default is the largest number a PCRE2_SIZE
+variable can hold (essentially unlimited).
+.
+.
+.SS "Limiting the size of a compiled pattern"
+.rs
+.sp
+The \fBmax_pattern_compiled_length\fP modifier sets a limit, in bytes, to the
+amount of memory used by a compiled pattern. Breaching the limit causes a
+compilation error. The default is the largest number a PCRE2_SIZE variable can
+hold (essentially unlimited).
+.
+.
+.\" HTML
+.SS "Using the POSIX wrapper API"
+.rs
+.sp
+The \fBposix\fP and \fBposix_nosub\fP modifiers cause \fBpcre2test\fP to call
+PCRE2 via the POSIX wrapper API rather than its native API. When
+\fBposix_nosub\fP is used, the POSIX option REG_NOSUB is passed to
+\fBregcomp()\fP. The POSIX wrapper supports only the 8-bit library. Note that
+it does not imply POSIX matching semantics; for more detail see the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+documentation. The following pattern modifiers set options for the
+\fBregcomp()\fP function:
+.sp
+ caseless REG_ICASE
+ multiline REG_NEWLINE
+ dotall REG_DOTALL )
+ ungreedy REG_UNGREEDY ) These options are not part of
+ ucp REG_UCP ) the POSIX standard
+ utf REG_UTF8 )
+.sp
+The \fBregerror_buffsize\fP modifier specifies a size for the error buffer that
+is passed to \fBregerror()\fP in the event of a compilation error. For example:
+.sp
+ /abc/posix,regerror_buffsize=20
+.sp
+This provides a means of testing the behaviour of \fBregerror()\fP when the
+buffer is too small for the error message. If this modifier has not been set, a
+large buffer is used.
+.P
+The \fBaftertext\fP and \fBallaftertext\fP subject modifiers work as described
+below. All other modifiers are either ignored, with a warning message, or cause
+an error.
+.P
+The pattern is passed to \fBregcomp()\fP as a zero-terminated string by
+default, but if the \fBuse_length\fP or \fBhex\fP modifiers are set, the
+REG_PEND extension is used to pass it by length.
+.
+.
+.SS "Testing the stack guard feature"
+.rs
+.sp
+The \fBstackguard\fP modifier is used to test the use of
+\fBpcre2_set_compile_recursion_guard()\fP, a function that is provided to
+enable stack availability to be checked during compilation (see the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation for details). If the number specified by the modifier is greater
+than zero, \fBpcre2_set_compile_recursion_guard()\fP is called to set up
+callback from \fBpcre2_compile()\fP to a local function. The argument it
+receives is the current nesting parenthesis depth; if this is greater than the
+value given by the modifier, non-zero is returned, causing the compilation to
+be aborted.
+.
+.
+.SS "Using alternative character tables"
+.rs
+.sp
+The value specified for the \fBtables\fP modifier must be one of the digits 0,
+1, 2, or 3. It causes a specific set of built-in character tables to be passed
+to \fBpcre2_compile()\fP. This is used in the PCRE2 tests to check behaviour
+with different character tables. The digit specifies the tables as follows:
+.sp
+ 0 do not pass any special character tables
+ 1 the default ASCII tables, as distributed in
+ pcre2_chartables.c.dist
+ 2 a set of tables defining ISO 8859 characters
+ 3 a set of tables loaded by the #loadtables command
+.sp
+In tables 2, some characters whose codes are greater than 128 are identified as
+letters, digits, spaces, etc. Tables 3 can be used only after a
+\fB#loadtables\fP command has loaded them from a binary file. Setting alternate
+character tables and a locale are mutually exclusive.
+.
+.
+.SS "Setting certain match controls"
+.rs
+.sp
+The following modifiers are really subject modifiers, and are described under
+"Subject Modifiers" below. However, they may be included in a pattern's
+modifier list, in which case they are applied to every subject line that is
+processed with that pattern. These modifiers do not affect the compilation
+process.
+.sp
+ aftertext show text after match
+ allaftertext show text after captures
+ allcaptures show all captures
+ allvector show the entire ovector
+ allusedtext show all consulted text
+ altglobal alternative global matching
+ /g global global matching
+ heapframes_size show match data heapframes size
+ jitstack= set size of JIT stack
+ mark show mark values
+ null_substitute_match_data substitute with NULL match data
+ replace= specify a replacement string
+ startchar show starting character when relevant
+ substitute_callout use substitution callouts
+ substitute_case_callout use substitution case callouts
+ substitute_extended use PCRE2_SUBSTITUTE_EXTENDED
+ substitute_literal use PCRE2_SUBSTITUTE_LITERAL
+ substitute_matched use PCRE2_SUBSTITUTE_MATCHED
+ substitute_overflow_length use PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_replacement_only use PCRE2_SUBSTITUTE_REPLACEMENT_ONLY
+ substitute_skip= skip substitution
+ substitute_stop= skip substitution and following
+ substitute_unknown_unset use PCRE2_SUBSTITUTE_UNKNOWN_UNSET
+ substitute_unset_empty use PCRE2_SUBSTITUTE_UNSET_EMPTY
+.sp
+These modifiers may not appear in a \fB#pattern\fP command. If you want them as
+defaults, set them in a \fB#subject\fP command.
+.
+.
+.SS "Specifying literal subject lines"
+.rs
+.sp
+If the \fBsubject_literal\fP modifier is present on a pattern, all the subject
+lines that it matches are taken as literal strings, with no interpretation of
+backslashes. It is not possible to set subject modifiers on such lines, but any
+that are set as defaults by a \fB#subject\fP command are recognized.
+.
+.
+.SS "Saving a compiled pattern"
+.rs
+.sp
+When a pattern with the \fBpush\fP modifier is successfully compiled, it is
+pushed onto a stack of compiled patterns, and \fBpcre2test\fP expects the next
+line to contain a new pattern (or a command) instead of a subject line. This
+facility is used when saving compiled patterns to a file, as described in the
+section entitled "Saving and restoring compiled patterns"
+.\" HTML
+.\"
+below.
+.\"
+If \fBpushcopy\fP is used instead of \fBpush\fP, a copy of the compiled
+pattern is stacked, leaving the original as current, ready to match the
+following input lines. This provides a way of testing the
+\fBpcre2_code_copy()\fP function.
+.\"
+The \fBpush\fP and \fBpushcopy \fP modifiers are incompatible with compilation
+modifiers such as \fBglobal\fP that act at match time. Any that are specified
+are ignored (for the stacked copy), with a warning message, except for
+\fBreplace\fP, which causes an error. Note that \fBjitverify\fP, which is
+allowed, does not carry through to any subsequent matching that uses a stacked
+pattern.
+.
+.
+.SS "Testing foreign pattern conversion"
+.rs
+.sp
+The experimental foreign pattern conversion functions in PCRE2 can be tested by
+setting the \fBconvert\fP modifier. Its argument is a colon-separated list of
+options, which set the equivalent option for the \fBpcre2_pattern_convert()\fP
+function:
+.sp
+ glob PCRE2_CONVERT_GLOB
+ glob_no_starstar PCRE2_CONVERT_GLOB_NO_STARSTAR
+ glob_no_wild_separator PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR
+ posix_basic PCRE2_CONVERT_POSIX_BASIC
+ posix_extended PCRE2_CONVERT_POSIX_EXTENDED
+ unset Unset all options
+.sp
+The "unset" value is useful for turning off a default that has been set by a
+\fB#pattern\fP command. When one of these options is set, the input pattern is
+passed to \fBpcre2_pattern_convert()\fP. If the conversion is successful, the
+result is reflected in the output and then passed to \fBpcre2_compile()\fP. The
+normal \fButf\fP and \fBno_utf_check\fP options, if set, cause the
+PCRE2_CONVERT_UTF and PCRE2_CONVERT_NO_UTF_CHECK options to be passed to
+\fBpcre2_pattern_convert()\fP.
+.P
+By default, the conversion function is allowed to allocate a buffer for its
+output. However, if the \fBconvert_length\fP modifier is set to a value greater
+than zero, \fBpcre2test\fP passes a buffer of the given length. This makes it
+possible to test the length check.
+.P
+The \fBconvert_glob_escape\fP and \fBconvert_glob_separator\fP modifiers can be
+used to specify the escape and separator characters for glob processing,
+overriding the defaults, which are operating-system dependent.
+.
+.
+.\" HTML
+.SH "SUBJECT MODIFIERS"
+.rs
+.sp
+The modifiers that can appear in subject lines and the \fB#subject\fP
+command are of two types.
+.
+.
+.SS "Setting match options"
+.rs
+.sp
+The following modifiers set options for \fBpcre2_match()\fP or
+\fBpcre2_dfa_match()\fP. See
+.\" HREF
+\fBpcre2api\fP
+.\"
+for a description of their effects.
+.sp
+ anchored set PCRE2_ANCHORED
+ copy_matched_subject set PCRE2_COPY_MATCHED_SUBJECT
+ endanchored set PCRE2_ENDANCHORED
+ dfa_restart set PCRE2_DFA_RESTART
+ dfa_shortest set PCRE2_DFA_SHORTEST
+ disable_recurseloop_check set PCRE2_DISABLE_RECURSELOOP_CHECK
+ no_jit set PCRE2_NO_JIT
+ no_utf_check set PCRE2_NO_UTF_CHECK
+ notbol set PCRE2_NOTBOL
+ notempty set PCRE2_NOTEMPTY
+ notempty_atstart set PCRE2_NOTEMPTY_ATSTART
+ noteol set PCRE2_NOTEOL
+ partial_hard (or ph) set PCRE2_PARTIAL_HARD
+ partial_soft (or ps) set PCRE2_PARTIAL_SOFT
+.sp
+The partial matching modifiers are provided with abbreviations because they
+appear frequently in tests.
+.P
+If the \fBposix\fP or \fBposix_nosub\fP modifier was present on the pattern,
+causing the POSIX wrapper API to be used, the only option-setting modifiers
+that have any effect are \fBnotbol\fP, \fBnotempty\fP, and \fBnoteol\fP,
+causing REG_NOTBOL, REG_NOTEMPTY, and REG_NOTEOL, respectively, to be passed to
+\fBregexec()\fP. The other modifiers are ignored, with a warning message.
+.P
+There is one additional modifier that can be used with the POSIX wrapper. It is
+ignored (with a warning) if used for non-POSIX matching.
+.sp
+ posix_startend=[:]
+.sp
+This causes the subject string to be passed to \fBregexec()\fP using the
+REG_STARTEND option, which uses offsets to specify which part of the string is
+searched. If only one number is given, the end offset is passed as the end of
+the subject string. For more detail of REG_STARTEND, see the
+.\" HREF
+\fBpcre2posix\fP
+.\"
+documentation. If the subject string contains binary zeros (coded as escapes
+such as \ex{00} because \fBpcre2test\fP does not support actual binary zeros in
+its input), you must use \fBposix_startend\fP to specify its length.
+.
+.
+.SS "Setting match controls"
+.rs
+.sp
+The following modifiers affect the matching process or request additional
+information. Some of them may also be specified on a pattern line (see above),
+in which case they apply to every subject line that is matched against that
+pattern, but can be overridden by modifiers on the subject.
+.sp
+ aftertext show text after match
+ allaftertext show text after captures
+ allcaptures show all captures
+ allusedtext show all consulted text (non-JIT only)
+ allvector show the entire ovector
+ altglobal alternative global matching
+ callout_capture show captures at callout time
+ callout_data= set a value to pass via callouts
+ callout_error=[:] control callout error
+ callout_extra show extra callout information
+ callout_fail=[:] control callout failure
+ callout_no_where do not show position of a callout
+ callout_none do not supply a callout function
+ copy= copy captured substring
+ depth_limit= set a depth limit
+ dfa use \fBpcre2_dfa_match()\fP
+ find_limits find heap, match and depth limits
+ find_limits_noheap find match and depth limits
+ get= extract captured substring
+ getall extract all captured substrings
+ /g global global matching
+ heapframes_size show match data heapframes size
+ heap_limit= set a limit on heap memory (Kbytes)
+ jitstack= set size of JIT stack
+ mark show mark values
+ match_limit= set a match limit
+ memory show heap memory usage
+ null_context match with a NULL context
+ null_replacement substitute with NULL replacement
+ null_subject match with NULL subject
+ null_substitute_match_data substitute with NULL match data
+ offset= set starting offset
+ offset_limit= set offset limit
+ ovector= set size of output vector
+ recursion_limit= obsolete synonym for depth_limit
+ replace= specify a replacement string
+ startchar show startchar when relevant
+ startoffset= same as offset=
+ substitute_callout use substitution callouts
+ substitute_case_callout use substitution case callouts
+ substitute_extended use PCRE2_SUBSTITUTE_EXTENDED
+ substitute_literal use PCRE2_SUBSTITUTE_LITERAL
+ substitute_matched use PCRE2_SUBSTITUTE_MATCHED
+ substitute_overflow_length use PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_replacement_only use PCRE2_SUBSTITUTE_REPLACEMENT_ONLY
+ substitute_skip= skip substitution number n
+ substitute_stop= skip substitution number n and greater
+ substitute_subject= specify a different subject for substitution
+ substitute_unknown_unset use PCRE2_SUBSTITUTE_UNKNOWN_UNSET
+ substitute_unset_empty use PCRE2_SUBSTITUTE_UNSET_EMPTY
+ zero_terminate pass the subject as zero-terminated
+.sp
+The effects of these modifiers are described in the following sections. When
+matching via the POSIX wrapper API, the \fBaftertext\fP, \fBallaftertext\fP,
+and \fBovector\fP subject modifiers work as described below. All other
+modifiers are either ignored, with a warning message, or cause an error.
+.
+.
+.SS "Showing more text"
+.rs
+.sp
+The \fBaftertext\fP modifier requests that as well as outputting the part of
+the subject string that matched the entire pattern, \fBpcre2test\fP should in
+addition output the remainder of the subject string. This is useful for tests
+where the subject contains multiple copies of the same substring. The
+\fBallaftertext\fP modifier requests the same action for captured substrings as
+well as the main matched substring. In each case the remainder is output on the
+following line with a plus character following the capture number.
+.P
+The \fBallusedtext\fP modifier requests that all the text that was consulted
+during a successful pattern match by the interpreter should be shown, for both
+full and partial matches. This feature is not supported for JIT matching, and
+if requested with JIT it is ignored (with a warning message). Setting this
+modifier affects the output if there is a lookbehind at the start of a match,
+or, for a complete match, a lookahead at the end, or if \eK is used in the
+pattern. Characters that precede or follow the start and end of the actual
+match are indicated in the output by '<' or '>' characters underneath them.
+Here is an example:
+.sp
+ re> /(?<=pqr)abc(?=xyz)/
+ data> 123pqrabcxyz456\e=allusedtext
+ 0: pqrabcxyz
+ <<< >>>
+ data> 123pqrabcxy\e=ph,allusedtext
+ Partial match: pqrabcxy
+ <<<
+.sp
+The first, complete match shows that the matched string is "abc", with the
+preceding and following strings "pqr" and "xyz" having been consulted during
+the match (when processing the assertions). The partial match can indicate only
+the preceding string.
+.P
+The \fBstartchar\fP modifier requests that the starting character for the match
+be indicated, if it is different to the start of the matched string. The only
+time when this occurs is when \eK has been processed as part of the match. In
+this situation, the output for the matched string is displayed from the
+starting character instead of from the match point, with circumflex characters
+under the earlier characters. For example:
+.sp
+ re> /abc\eKxyz/
+ data> abcxyz\e=startchar
+ 0: abcxyz
+ ^^^
+.sp
+Unlike \fBallusedtext\fP, the \fBstartchar\fP modifier can be used with JIT.
+However, these two modifiers are mutually exclusive.
+.
+.
+.SS "Showing the value of all capture groups"
+.rs
+.sp
+The \fBallcaptures\fP modifier requests that the values of all potential
+captured parentheses be output after a match. By default, only those up to the
+highest one actually used in the match are output (corresponding to the return
+code from \fBpcre2_match()\fP). Groups that did not take part in the match
+are output as "". This modifier is not relevant for DFA matching (which
+does no capturing) and does not apply when \fBreplace\fP is specified; it is
+ignored, with a warning message, if present.
+.
+.
+.SS "Showing the entire ovector, for all outcomes"
+.rs
+.sp
+The \fBallvector\fP modifier requests that the entire ovector be shown,
+whatever the outcome of the match. Compare \fBallcaptures\fP, which shows only
+up to the maximum number of capture groups for the pattern, and then only for a
+successful complete non-DFA match. This modifier, which acts after any match
+result, and also for DFA matching, provides a means of checking that there are
+no unexpected modifications to ovector fields. Before each match attempt, the
+ovector is filled with a special value, and if this is found in both elements
+of a capturing pair, "" is output. After a successful match, this
+applies to all groups after the maximum capture group for the pattern. In other
+cases it applies to the entire ovector. After a partial match, the first two
+elements are the only ones that should be set. After a DFA match, the amount of
+ovector that is used depends on the number of matches that were found.
+.
+.
+.SS "Testing pattern callouts"
+.rs
+.sp
+A callout function is supplied when \fBpcre2test\fP calls the library matching
+functions, unless \fBcallout_none\fP is specified. Its behaviour can be
+controlled by various modifiers listed above whose names begin with
+\fBcallout_\fP. Details are given in the section entitled "Callouts"
+.\" HTML
+.\"
+below.
+.\"
+Testing callouts from \fBpcre2_substitute()\fP is described separately in
+"Testing the substitution function"
+.\" HTML
+.\"
+below.
+.\"
+.
+.
+.SS "Finding all matches in a string"
+.rs
+.sp
+Searching for all possible matches within a subject can be requested by the
+\fBglobal\fP or \fBaltglobal\fP modifier. After finding a match, the matching
+function is called again to search the remainder of the subject. The difference
+between \fBglobal\fP and \fBaltglobal\fP is that the former uses the
+\fIstart_offset\fP argument to \fBpcre2_match()\fP or \fBpcre2_dfa_match()\fP
+to start searching at a new point within the entire string (which is what Perl
+does), whereas the latter passes over a shortened subject. This makes a
+difference to the matching process if the pattern begins with a lookbehind
+assertion (including \eb or \eB).
+.P
+If an empty string is matched, the next match is done with the
+PCRE2_NOTEMPTY_ATSTART flag set, in order to search for another, non-empty,
+match at the same point in the subject. This imitates the way Perl handles such
+cases when using the \fB/g\fP modifier or the \fBsplit()\fP function.
+.
+.
+.SS "Testing substring extraction functions"
+.rs
+.sp
+The \fBcopy\fP and \fBget\fP modifiers can be used to test the
+\fBpcre2_substring_copy_xxx()\fP and \fBpcre2_substring_get_xxx()\fP functions.
+They can be given more than once, and each can specify a capture group name or
+number, for example:
+.sp
+ abcd\e=copy=1,copy=3,get=G1
+.sp
+If the \fB#subject\fP command is used to set default copy and/or get lists,
+these can be unset by specifying a negative number to cancel all numbered
+groups and an empty name to cancel all named groups.
+.P
+The \fBgetall\fP modifier tests \fBpcre2_substring_list_get()\fP, which
+extracts all captured substrings.
+.P
+If the subject line is successfully matched, the substrings extracted by the
+convenience functions are output with C, G, or L after the string number
+instead of a colon. This is in addition to the normal full list. The string
+length (that is, the return from the extraction function) is given in
+parentheses after each substring, followed by the name when the extraction was
+by name.
+.
+.
+.\" HTML
+.SS "Testing the substitution function"
+.rs
+.sp
+If the \fBreplace\fP modifier is set, the \fBpcre2_substitute()\fP function is
+called instead of one of the matching functions (or after one call of
+\fBpcre2_match()\fP in the case of PCRE2_SUBSTITUTE_MATCHED). Note that
+replacement strings cannot contain commas, because a comma signifies the end of
+a modifier. This is not thought to be an issue in a test program.
+.P
+Specifying a completely empty replacement string disables this modifier.
+However, it is possible to specify an empty replacement by providing a buffer
+length, as described below, for an otherwise empty replacement.
+.P
+Unlike subject strings, \fBpcre2test\fP does not process replacement strings
+for escape sequences. In UTF mode, a replacement string is checked to see if it
+is a valid UTF-8 string. If so, it is correctly converted to a UTF string of
+the appropriate code unit width. If it is not a valid UTF-8 string, the
+individual code units are copied directly. This provides a means of passing an
+invalid UTF-8 string for testing purposes.
+.P
+The following modifiers set options (in additional to the normal match options)
+for \fBpcre2_substitute()\fP:
+.sp
+ global PCRE2_SUBSTITUTE_GLOBAL
+ substitute_extended PCRE2_SUBSTITUTE_EXTENDED
+ substitute_literal PCRE2_SUBSTITUTE_LITERAL
+ substitute_matched PCRE2_SUBSTITUTE_MATCHED
+ substitute_overflow_length PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_replacement_only PCRE2_SUBSTITUTE_REPLACEMENT_ONLY
+ substitute_unknown_unset PCRE2_SUBSTITUTE_UNKNOWN_UNSET
+ substitute_unset_empty PCRE2_SUBSTITUTE_UNSET_EMPTY
+.sp
+See the
+.\" HREF
+\fBpcre2api\fP
+.\"
+documentation for details of these options.
+.P
+After a successful substitution, the modified string is output, preceded by the
+number of replacements. This may be zero if there were no matches. Here is a
+simple example of a substitution test:
+.sp
+ /abc/replace=xxx
+ =abc=abc=
+ 1: =xxx=abc=
+ =abc=abc=\e=global
+ 2: =xxx=xxx=
+.sp
+Subject and replacement strings should be kept relatively short (fewer than 256
+characters) for substitution tests, as fixed-size buffers are used. To make it
+easy to test for buffer overflow, if the replacement string starts with a
+number in square brackets, that number is passed to \fBpcre2_substitute()\fP as
+the size of the output buffer, with the replacement string starting at the next
+character. Here is an example that tests the edge case:
+.sp
+ /abc/
+ 123abc123\e=replace=[10]XYZ
+ 1: 123XYZ123
+ 123abc123\e=replace=[9]XYZ
+ Failed: error -48: no more memory
+.sp
+The default action of \fBpcre2_substitute()\fP is to return
+PCRE2_ERROR_NOMEMORY when the output buffer is too small. However, if the
+PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option is set (by using the
+\fBsubstitute_overflow_length\fP modifier), \fBpcre2_substitute()\fP continues
+to go through the motions of matching and substituting (but not doing any
+callouts), in order to compute the size of buffer that is required. When this
+happens, \fBpcre2test\fP shows the required buffer length (which includes space
+for the trailing zero) as part of the error message. For example:
+.sp
+ /abc/substitute_overflow_length
+ 123abc123\e=replace=[9]XYZ
+ Failed: error -48: no more memory: 10 code units are needed
+.sp
+A replacement string is ignored with POSIX and DFA matching. Specifying partial
+matching provokes an error return ("bad option value") from
+\fBpcre2_substitute()\fP.
+.sp
+The \fBsubstitute_subject\fP modifier may be used to test the use of the PCRE2
+API, in which a client calls \fBpcre2_match()\fP followed by \fBpcre2_substitute()\fP
+with PCRE2_SUBSTITUTE_MATCHED, but the client performs an unexpected and
+unsupported modification of the subject buffer in-place, in between the match
+and substitution.
+.
+.
+.SS "Testing substitute callouts"
+.rs
+.sp
+If the \fBsubstitute_callout\fP modifier is set, a substitution callout
+function is set up. The \fBnull_context\fP modifier must not be set, because
+the address of the callout function is passed in a match context. When the
+callout function is called (after each substitution), details of the input
+and output strings are output. For example:
+.sp
+ /abc/g,replace=<$0>,substitute_callout
+ abcdefabcpqr
+ 1(1) Old 0 3 "abc" New 0 5 ""
+ 2(1) Old 6 9 "abc" New 8 13 ""
+ 2: defpqr
+.sp
+The first number on each callout line is the count of matches. The
+parenthesized number is the number of pairs that are set in the ovector (that
+is, one more than the number of capturing groups that were set). Then are
+listed the offsets of the old substring, its contents, and the same for the
+replacement.
+.P
+By default, the substitution callout function returns zero, which accepts the
+replacement and causes matching to continue if /g was used. Two further
+modifiers can be used to test other return values. If \fBsubstitute_skip\fP is
+set to a value greater than zero the callout function returns +1 for the match
+of that number, and similarly \fBsubstitute_stop\fP returns -1. These cause the
+replacement to be rejected, and -1 causes no further matching to take place. If
+either of them are set, \fBsubstitute_callout\fP is assumed. For example:
+.sp
+ /abc/g,replace=<$0>,substitute_skip=1
+ abcdefabcpqr
+ 1(1) Old 0 3 "abc" New 0 5 " SKIPPED"
+ 2(1) Old 6 9 "abc" New 6 11 ""
+ 2: abcdefpqr
+ abcdefabcpqr\e=substitute_stop=1
+ 1(1) Old 0 3 "abc" New 0 5 " STOPPED"
+ 1: abcdefabcpqr
+.sp
+If both are set for the same number, stop takes precedence. Only a single skip
+or stop is supported, which is sufficient for testing that the feature works.
+.
+.
+.SS "Testing substitute case callouts"
+.rs
+.sp
+If the \fBsubstitute_case_callout\fP modifier is set, a substitution
+case callout function is set up. The callout function is called for each
+substituted chunk which is to be case-transformed.
+.P
+The callout function passed is a fixed function with implementation for certain
+behaviours: inputs which shrink when case-transformed; inputs which grow; inputs
+with distinct upper/lower/titlecase forms. The characters which are not
+special-cased for testing purposes are left unmodified, as if they are caseless
+characters.
+.
+.
+.SS "Setting the JIT stack size"
+.rs
+.sp
+The \fBjitstack\fP modifier provides a way of setting the maximum stack size
+that is used by the just-in-time optimization code. It is ignored if JIT
+optimization is not being used. The value is a number of kibibytes (units of
+1024 bytes). Setting zero reverts to the default of 32KiB. Providing a stack
+that is larger than the default is necessary only for very complicated
+patterns. If \fBjitstack\fP is set non-zero on a subject line it overrides any
+value that was set on the pattern.
+.
+.
+.SS "Setting heap, match, and depth limits"
+.rs
+.sp
+The \fBheap_limit\fP, \fBmatch_limit\fP, and \fBdepth_limit\fP modifiers set
+the appropriate limits in the match context. These values are ignored when the
+\fBfind_limits\fP or \fBfind_limits_noheap\fP modifier is specified.
+.
+.
+.SS "Finding minimum limits"
+.rs
+.sp
+If the \fBfind_limits\fP modifier is present on a subject line, \fBpcre2test\fP
+calls the relevant matching function several times, setting different values in
+the match context via \fBpcre2_set_heap_limit()\fP,
+\fBpcre2_set_match_limit()\fP, or \fBpcre2_set_depth_limit()\fP until it finds
+the smallest value for each parameter that allows the match to complete without
+a "limit exceeded" error. The match itself may succeed or fail. An alternative
+modifier, \fBfind_limits_noheap\fP, omits the heap limit. This is used in the
+standard tests, because the minimum heap limit varies between systems. If JIT
+is being used, only the match limit is relevant, and the other two are
+automatically omitted.
+.P
+When using this modifier, the pattern should not contain any limit settings
+such as (*LIMIT_MATCH=...) within it. If such a setting is present and is
+lower than the minimum matching value, the minimum value cannot be found
+because \fBpcre2_set_match_limit()\fP etc. are only able to reduce the value of
+an in-pattern limit; they cannot increase it.
+.P
+For non-DFA matching, the minimum \fIdepth_limit\fP number is a measure of how
+much nested backtracking happens (that is, how deeply the pattern's tree is
+searched). In the case of DFA matching, \fIdepth_limit\fP controls the depth of
+recursive calls of the internal function that is used for handling pattern
+recursion, lookaround assertions, and atomic groups.
+.P
+For non-DFA matching, the \fImatch_limit\fP number is a measure of the amount
+of backtracking that takes place, and learning the minimum value can be
+instructive. For most simple matches, the number is quite small, but for
+patterns with very large numbers of matching possibilities, it can become large
+very quickly with increasing length of subject string. In the case of DFA
+matching, \fImatch_limit\fP controls the total number of calls, both recursive
+and non-recursive, to the internal matching function, thus controlling the
+overall amount of computing resource that is used.
+.P
+For both kinds of matching, the \fIheap_limit\fP number, which is in kibibytes
+(units of 1024 bytes), limits the amount of heap memory used for matching.
+.
+.
+.SS "Showing MARK names"
+.rs
+.sp
+.P
+The \fBmark\fP modifier causes the names from backtracking control verbs that
+are returned from calls to \fBpcre2_match()\fP to be displayed. If a mark is
+returned for a match, non-match, or partial match, \fBpcre2test\fP shows it.
+For a match, it is on a line by itself, tagged with "MK:". Otherwise, it
+is added to the non-match message.
+.
+.
+.SS "Showing memory usage"
+.rs
+.sp
+The \fBmemory\fP modifier causes \fBpcre2test\fP to log the sizes of all heap
+memory allocation and freeing calls that occur during a call to
+\fBpcre2_match()\fP or \fBpcre2_dfa_match()\fP. In the latter case, heap memory
+is used only when a match requires more internal workspace that the default
+allocation on the stack, so in many cases there will be no output. No heap
+memory is allocated during matching with JIT. For this modifier to work, the
+\fBnull_context\fP modifier must not be set on both the pattern and the
+subject, though it can be set on one or the other.
+.
+.
+.SS "Showing the heap frame overall vector size"
+.rs
+.sp
+The \fBheapframes_size\fP modifier is relevant for matches using
+\fBpcre2_match()\fP without JIT. After a match has run (whether successful or
+not) the size, in bytes, of the allocated heap frames vector that is left
+attached to the match data block is shown. If the matching action involved
+several calls to \fBpcre2_match()\fP (for example, global matching or for
+timing) only the final value is shown.
+.P
+This modifier is ignored, with a warning, for POSIX or DFA matching. JIT
+matching does not use the heap frames vector, so the size is always zero,
+unless there was a previous non-JIT match. Note that specifing a size of zero
+for the output vector (see below) causes \fBpcre2test\fP to free its match data
+block (and associated heap frames vector) and allocate a new one.
+.
+.
+.SS "Setting a starting offset"
+.rs
+.sp
+The \fBoffset\fP modifier sets an offset in the subject string at which
+matching starts. Its value is a number of code units, not characters.
+.
+.
+.SS "Setting an offset limit"
+.rs
+.sp
+The \fBoffset_limit\fP modifier sets a limit for unanchored matches. If a match
+cannot be found starting at or before this offset in the subject, a "no match"
+return is given. The data value is a number of code units, not characters. When
+this modifier is used, the \fBuse_offset_limit\fP modifier must have been set
+for the pattern; if not, an error is generated.
+.
+.
+.SS "Setting the size of the output vector"
+.rs
+.sp
+The \fBovector\fP modifier applies only to the subject line in which it
+appears, though of course it can also be used to set a default in a
+\fB#subject\fP command. It specifies the number of pairs of offsets that are
+available for storing matching information. The default is 15.
+.P
+A value of zero is useful when testing the POSIX API because it causes
+\fBregexec()\fP to be called with a NULL capture vector. When not testing the
+POSIX API, a value of zero is used to cause
+\fBpcre2_match_data_create_from_pattern()\fP to be called, in order to create a
+new match block of exactly the right size for the pattern. (It is not possible
+to create a match block with a zero-length ovector; there is always at least
+one pair of offsets.) The old match data block is freed.
+.
+.
+.SS "Passing the subject as zero-terminated"
+.rs
+.sp
+By default, the subject string is passed to a native API matching function with
+its correct length. In order to test the facility for passing a zero-terminated
+string, the \fBzero_terminate\fP modifier is provided. It causes the length to
+be passed as PCRE2_ZERO_TERMINATED. When matching via the POSIX interface,
+this modifier is ignored, with a warning.
+.P
+When testing \fBpcre2_substitute()\fP, this modifier also has the effect of
+passing the replacement string as zero-terminated.
+.
+.
+.SS "Passing a NULL context, subject, or replacement"
+.rs
+.sp
+Normally, \fBpcre2test\fP passes a context block to \fBpcre2_match()\fP,
+\fBpcre2_dfa_match()\fP, \fBpcre2_jit_match()\fP or \fBpcre2_substitute()\fP.
+If the \fBnull_context\fP modifier is set, however, NULL is passed. This is for
+testing that the matching and substitution functions behave correctly in this
+case (they use default values). This modifier cannot be used with the
+\fBfind_limits\fP, \fBfind_limits_noheap\fP, or \fBsubstitute_callout\fP
+modifiers.
+.P
+Similarly, for testing purposes, if the \fBnull_subject\fP or
+\fBnull_replacement\fP modifier is set, the subject or replacement string
+pointers are passed as NULL, respectively, to the relevant functions.
+.
+.
+.SH "THE ALTERNATIVE MATCHING FUNCTION"
+.rs
+.sp
+By default, \fBpcre2test\fP uses the standard PCRE2 matching function,
+\fBpcre2_match()\fP to match each subject line. PCRE2 also supports an
+alternative matching function, \fBpcre2_dfa_match()\fP, which operates in a
+different way, and has some restrictions. The differences between the two
+functions are described in the
+.\" HREF
+\fBpcre2matching\fP
+.\"
+documentation.
+.P
+If the \fBdfa\fP modifier is set, the alternative matching function is used.
+This function finds all possible matches at a given point in the subject. If,
+however, the \fBdfa_shortest\fP modifier is set, processing stops after the
+first match is found. This is always the shortest possible match.
+.
+.
+.SH "DEFAULT OUTPUT FROM pcre2test"
+.rs
+.sp
+This section describes the output when the normal matching function,
+\fBpcre2_match()\fP, is being used.
+.P
+When a match succeeds, \fBpcre2test\fP outputs the list of captured substrings,
+starting with number 0 for the string that matched the whole pattern.
+Otherwise, it outputs "No match" when the return is PCRE2_ERROR_NOMATCH, or
+"Partial match:" followed by the partially matching substring when the
+return is PCRE2_ERROR_PARTIAL. (Note that this is the
+entire substring that was inspected during the partial match; it may include
+characters before the actual match start if a lookbehind assertion, \eK, \eb,
+or \eB was involved.)
+.P
+For any other return, \fBpcre2test\fP outputs the PCRE2 negative error number
+and a short descriptive phrase. If the error is a failed UTF string check, the
+code unit offset of the start of the failing character is also output. Here is
+an example of an interactive \fBpcre2test\fP run.
+.sp
+ $ pcre2test
+ PCRE2 version 10.22 2016-07-29
+.sp
+ re> /^abc(\ed+)/
+ data> abc123
+ 0: abc123
+ 1: 123
+ data> xyz
+ No match
+.sp
+Unset capturing substrings that are not followed by one that is set are not
+shown by \fBpcre2test\fP unless the \fBallcaptures\fP modifier is specified. In
+the following example, there are two capturing substrings, but when the first
+data line is matched, the second, unset substring is not shown. An "internal"
+unset substring is shown as "", as for the second data line.
+.sp
+ re> /(a)|(b)/
+ data> a
+ 0: a
+ 1: a
+ data> b
+ 0: b
+ 1:
+ 2: b
+.sp
+If the strings contain any non-printing characters, they are output as \exhh
+escapes if the value is less than 256 and UTF mode is not set. Otherwise they
+are output as \ex{hh...} escapes. See below for the definition of non-printing
+characters. If the \fBaftertext\fP modifier is set, the output for substring 0
+is followed by the rest of the subject string, identified by "0+" like this:
+.sp
+ re> /cat/aftertext
+ data> cataract
+ 0: cat
+ 0+ aract
+.sp
+If global matching is requested, the results of successive matching attempts
+are output in sequence, like this:
+.sp
+ re> /\eBi(\ew\ew)/g
+ data> Mississippi
+ 0: iss
+ 1: ss
+ 0: iss
+ 1: ss
+ 0: ipp
+ 1: pp
+.sp
+"No match" is output only if the first match attempt fails. Here is an example
+of a failure message (the offset 4 that is specified by the \fBoffset\fP
+modifier is past the end of the subject string):
+.sp
+ re> /xyz/
+ data> xyz\e=offset=4
+ Error -24 (bad offset value)
+.P
+Note that whereas patterns can be continued over several lines (a plain ">"
+prompt is used for continuations), subject lines may not. However newlines can
+be included in a subject by means of the \en escape (or \er, \er\en, etc.,
+depending on the newline sequence setting).
+.
+.
+.
+.SH "OUTPUT FROM THE ALTERNATIVE MATCHING FUNCTION"
+.rs
+.sp
+When the alternative matching function, \fBpcre2_dfa_match()\fP, is used, the
+output consists of a list of all the matches that start at the first point in
+the subject where there is at least one match. For example:
+.sp
+ re> /(tang|tangerine|tan)/
+ data> yellow tangerine\e=dfa
+ 0: tangerine
+ 1: tang
+ 2: tan
+.sp
+Using the normal matching function on this data finds only "tang". The
+longest matching string is always given first (and numbered zero). After a
+PCRE2_ERROR_PARTIAL return, the output is "Partial match:", followed by the
+partially matching substring. Note that this is the entire substring that was
+inspected during the partial match; it may include characters before the actual
+match start if a lookbehind assertion, \eb, or \eB was involved. (\eK is not
+supported for DFA matching.)
+.P
+If global matching is requested, the search for further matches resumes
+at the end of the longest match. For example:
+.sp
+ re> /(tang|tangerine|tan)/g
+ data> yellow tangerine and tangy sultana\e=dfa
+ 0: tangerine
+ 1: tang
+ 2: tan
+ 0: tang
+ 1: tan
+ 0: tan
+.sp
+The alternative matching function does not support substring capture, so the
+modifiers that are concerned with captured substrings are not relevant.
+.
+.
+.SH "RESTARTING AFTER A PARTIAL MATCH"
+.rs
+.sp
+When the alternative matching function has given the PCRE2_ERROR_PARTIAL
+return, indicating that the subject partially matched the pattern, you can
+restart the match with additional subject data by means of the
+\fBdfa_restart\fP modifier. For example:
+.sp
+ re> /^\ed?\ed(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\ed\ed$/
+ data> 23ja\e=ps,dfa
+ Partial match: 23ja
+ data> n05\e=dfa,dfa_restart
+ 0: n05
+.sp
+For further information about partial matching, see the
+.\" HREF
+\fBpcre2partial\fP
+.\"
+documentation.
+.
+.
+.\" HTML
+.SH CALLOUTS
+.rs
+.sp
+If the pattern contains any callout requests, \fBpcre2test\fP's callout
+function is called during matching unless \fBcallout_none\fP is specified. This
+works with both matching functions, and with JIT, though there are some
+differences in behaviour. The output for callouts with numerical arguments and
+those with string arguments is slightly different.
+.
+.
+.SS "Callouts with numerical arguments"
+.rs
+.sp
+By default, the callout function displays the callout number, the start and
+current positions in the subject text at the callout time, and the next pattern
+item to be tested. For example:
+.sp
+ --->pqrabcdef
+ 0 ^ ^ \ed
+.sp
+This output indicates that callout number 0 occurred for a match attempt
+starting at the fourth character of the subject string, when the pointer was at
+the seventh character, and when the next pattern item was \ed. Just
+one circumflex is output if the start and current positions are the same, or if
+the current position precedes the start position, which can happen if the
+callout is in a lookbehind assertion.
+.P
+Callouts numbered 255 are assumed to be automatic callouts, inserted as a
+result of the \fBauto_callout\fP pattern modifier. In this case, instead of
+showing the callout number, the offset in the pattern, preceded by a plus, is
+output. For example:
+.sp
+ re> /\ed?[A-E]\e*/auto_callout
+ data> E*
+ --->E*
+ +0 ^ \ed?
+ +3 ^ [A-E]
+ +8 ^^ \e*
+ +10 ^ ^
+ 0: E*
+.sp
+If a pattern contains (*MARK) items, an additional line is output whenever
+a change of latest mark is passed to the callout function. For example:
+.sp
+ re> /a(*MARK:X)bc/auto_callout
+ data> abc
+ --->abc
+ +0 ^ a
+ +1 ^^ (*MARK:X)
+ +10 ^^ b
+ Latest Mark: X
+ +11 ^ ^ c
+ +12 ^ ^
+ 0: abc
+.sp
+The mark changes between matching "a" and "b", but stays the same for the rest
+of the match, so nothing more is output. If, as a result of backtracking, the
+mark reverts to being unset, the text "" is output.
+.
+.
+.SS "Callouts with string arguments"
+.rs
+.sp
+The output for a callout with a string argument is similar, except that instead
+of outputting a callout number before the position indicators, the callout
+string and its offset in the pattern string are output before the reflection of
+the subject string, and the subject string is reflected for each callout. For
+example:
+.sp
+ re> /^ab(?C'first')cd(?C"second")ef/
+ data> abcdefg
+ Callout (7): 'first'
+ --->abcdefg
+ ^ ^ c
+ Callout (20): "second"
+ --->abcdefg
+ ^ ^ e
+ 0: abcdef
+.sp
+.
+.
+.SS "Callout modifiers"
+.rs
+.sp
+The callout function in \fBpcre2test\fP returns zero (carry on matching) by
+default, but you can use a \fBcallout_fail\fP modifier in a subject line to
+change this and other parameters of the callout (see below).
+.P
+If the \fBcallout_capture\fP modifier is set, the current captured groups are
+output when a callout occurs. This is useful only for non-DFA matching, as
+\fBpcre2_dfa_match()\fP does not support capturing, so no captures are ever
+shown.
+.P
+The normal callout output, showing the callout number or pattern offset (as
+described above) is suppressed if the \fBcallout_no_where\fP modifier is set.
+.P
+When using the interpretive matching function \fBpcre2_match()\fP without JIT,
+setting the \fBcallout_extra\fP modifier causes additional output from
+\fBpcre2test\fP's callout function to be generated. For the first callout in a
+match attempt at a new starting position in the subject, "New match attempt" is
+output. If there has been a backtrack since the last callout (or start of
+matching if this is the first callout), "Backtrack" is output, followed by "No
+other matching paths" if the backtrack ended the previous match attempt. For
+example:
+.sp
+ re> /(a+)b/auto_callout,no_start_optimize,no_auto_possess
+ data> aac\e=callout_extra
+ New match attempt
+ --->aac
+ +0 ^ (
+ +1 ^ a+
+ +3 ^ ^ )
+ +4 ^ ^ b
+ Backtrack
+ --->aac
+ +3 ^^ )
+ +4 ^^ b
+ Backtrack
+ No other matching paths
+ New match attempt
+ --->aac
+ +0 ^ (
+ +1 ^ a+
+ +3 ^^ )
+ +4 ^^ b
+ Backtrack
+ No other matching paths
+ New match attempt
+ --->aac
+ +0 ^ (
+ +1 ^ a+
+ Backtrack
+ No other matching paths
+ New match attempt
+ --->aac
+ +0 ^ (
+ +1 ^ a+
+ No match
+.sp
+Notice that various optimizations must be turned off if you want all possible
+matching paths to be scanned. If \fBno_start_optimize\fP is not used, there is
+an immediate "no match", without any callouts, because the starting
+optimization fails to find "b" in the subject, which it knows must be present
+for any match. If \fBno_auto_possess\fP is not used, the "a+" item is turned
+into "a++", which reduces the number of backtracks.
+.P
+The \fBcallout_extra\fP modifier has no effect if used with the DFA matching
+function, or with JIT.
+.
+.
+.SS "Return values from callouts"
+.rs
+.sp
+The default return from the callout function is zero, which allows matching to
+continue. The \fBcallout_fail\fP modifier can be given one or two numbers. If
+there is only one number, 1 is returned instead of 0 (causing matching to
+backtrack) when a callout of that number is reached. If two numbers (:)
+are given, 1 is returned when callout is reached and there have been at
+least callouts. The \fBcallout_error\fP modifier is similar, except that
+PCRE2_ERROR_CALLOUT is returned, causing the entire matching process to be
+aborted. If both these modifiers are set for the same callout number,
+\fBcallout_error\fP takes precedence. Note that callouts with string arguments
+are always given the number zero.
+.P
+The \fBcallout_data\fP modifier can be given an unsigned or a negative number.
+This is set as the "user data" that is passed to the matching function, and
+passed back when the callout function is invoked. Any value other than zero is
+used as a return from \fBpcre2test\fP's callout function.
+.P
+Inserting callouts can be helpful when using \fBpcre2test\fP to check
+complicated regular expressions. For further information about callouts, see
+the
+.\" HREF
+\fBpcre2callout\fP
+.\"
+documentation.
+.
+.
+.
+.SH "NON-PRINTING CHARACTERS"
+.rs
+.sp
+When \fBpcre2test\fP is outputting text in the compiled version of a pattern,
+bytes other than 32-126 are always treated as non-printing characters and are
+therefore shown as hex escapes.
+.P
+When \fBpcre2test\fP is outputting text that is a matched part of a subject
+string, it behaves in the same way, unless a different locale has been set for
+the pattern (using the \fBlocale\fP modifier). In this case, the
+\fBisprint()\fP function is used to distinguish printing and non-printing
+characters.
+.
+.
+.
+.\" HTML
+.SH "SAVING AND RESTORING COMPILED PATTERNS"
+.rs
+.sp
+It is possible to save compiled patterns on disc or elsewhere, and reload them
+later, subject to a number of restrictions. JIT data cannot be saved. The host
+on which the patterns are reloaded must be running the same version of PCRE2,
+with the same code unit width, and must also have the same endianness, pointer
+width and PCRE2_SIZE type. Before compiled patterns can be saved they must be
+serialized, that is, converted to a stream of bytes. A single byte stream may
+contain any number of compiled patterns, but they must all use the same
+character tables. A single copy of the tables is included in the byte stream
+(its size is 1088 bytes).
+.P
+The functions whose names begin with \fBpcre2_serialize_\fP are used
+for serializing and de-serializing. They are described in the
+.\" HREF
+\fBpcre2serialize\fP
+.\"
+documentation. In this section we describe the features of \fBpcre2test\fP that
+can be used to test these functions.
+.P
+Note that "serialization" in PCRE2 does not convert compiled patterns to an
+abstract format like Java or .NET. It just makes a reloadable byte code stream.
+Hence the restrictions on reloading mentioned above.
+.P
+In \fBpcre2test\fP, when a pattern with \fBpush\fP modifier is successfully
+compiled, it is pushed onto a stack of compiled patterns, and \fBpcre2test\fP
+expects the next line to contain a new pattern (or command) instead of a
+subject line. By contrast, the \fBpushcopy\fP modifier causes a copy of the
+compiled pattern to be stacked, leaving the original available for immediate
+matching. By using \fBpush\fP and/or \fBpushcopy\fP, a number of patterns can
+be compiled and retained. These modifiers are incompatible with \fBposix\fP,
+and control modifiers that act at match time are ignored (with a message) for
+the stacked patterns. The \fBjitverify\fP modifier applies only at compile
+time.
+.P
+The command
+.sp
+ #save
+.sp
+causes all the stacked patterns to be serialized and the result written to the
+named file. Afterwards, all the stacked patterns are freed. The command
+.sp
+ #load
+.sp
+reads the data in the file, and then arranges for it to be de-serialized, with
+the resulting compiled patterns added to the pattern stack. The pattern on the
+top of the stack can be retrieved by the #pop command, which must be followed
+by lines of subjects that are to be matched with the pattern, terminated as
+usual by an empty line or end of file. This command may be followed by a
+modifier list containing only
+.\" HTML
+.\"
+control modifiers
+.\"
+that act after a pattern has been compiled. In particular, \fBhex\fP,
+\fBposix\fP, \fBposix_nosub\fP, \fBpush\fP, and \fBpushcopy\fP are not allowed,
+nor are any
+.\" HTML
+.\"
+option-setting modifiers.
+.\"
+The JIT modifiers are, however permitted. Here is an example that saves and
+reloads two patterns.
+.sp
+ /abc/push
+ /xyz/push
+ #save tempfile
+ #load tempfile
+ #pop info
+ xyz
+.sp
+ #pop jit,bincode
+ abc
+.sp
+If \fBjitverify\fP is used with #pop, it does not automatically imply
+\fBjit\fP, which is different behaviour from when it is used on a pattern.
+.P
+The #popcopy command is analogous to the \fBpushcopy\fP modifier in that it
+makes current a copy of the topmost stack pattern, leaving the original still
+on the stack.
+.
+.
+.
+.SH "SEE ALSO"
+.rs
+.sp
+\fBpcre2\fP(3), \fBpcre2api\fP(3), \fBpcre2callout\fP(3),
+\fBpcre2jit\fP, \fBpcre2matching\fP(3), \fBpcre2partial\fP(d),
+\fBpcre2pattern\fP(3), \fBpcre2serialize\fP(3).
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 22 August 2026
+Copyright (c) 1997-2024 University of Cambridge.
+.fi
diff --git a/doc/pcre2test.txt b/doc/pcre2test.txt
new file mode 100644
index 0000000..e0e8554
--- /dev/null
+++ b/doc/pcre2test.txt
@@ -0,0 +1,2107 @@
+PCRE2TEST(1) General Commands Manual PCRE2TEST(1)
+
+
+NAME
+ pcre2test - a program for testing Perl-compatible regular expressions.
+
+
+SYNOPSIS
+
+ pcre2test [options] [input file [output file]]
+
+ pcre2test is a test program for the PCRE2 regular expression libraries,
+ but it can also be used for experimenting with regular expressions.
+ This document describes the features of the test program; for details
+ of the regular expressions themselves, see the pcre2pattern documenta-
+ tion. For details of the PCRE2 library function calls and their op-
+ tions, see the pcre2api documentation.
+
+ The input for pcre2test is a sequence of regular expression patterns
+ and subject strings to be matched. There are also command lines for
+ setting defaults and controlling some special actions. The output shows
+ the result of each match attempt. Modifiers on external or internal
+ command lines, the patterns, and the subject lines specify PCRE2 func-
+ tion options, control how the subject is processed, and what output is
+ produced.
+
+ There are many obscure modifiers, some of which are specifically de-
+ signed for use in conjunction with the test script and data files that
+ are distributed as part of PCRE2. All the modifiers are documented
+ here, some without much justification, but many of them are unlikely to
+ be of use except when testing the libraries.
+
+
+PCRE2's 8-BIT, 16-BIT AND 32-BIT LIBRARIES
+
+ Different versions of the PCRE2 library can be built to support charac-
+ ter strings that are encoded in 8-bit, 16-bit, or 32-bit code units.
+ One, two, or all three of these libraries may be simultaneously in-
+ stalled. The pcre2test program can be used to test all the libraries.
+ However, its own input and output are always in 8-bit format. When
+ testing the 16-bit or 32-bit libraries, patterns and subject strings
+ are converted to 16-bit or 32-bit format before being passed to the li-
+ brary functions. Results are converted back to 8-bit code units for
+ output.
+
+ In the rest of this document, the names of library functions and struc-
+ tures are given in generic form, for example, pcre2_compile(). The ac-
+ tual names used in the libraries have a suffix _8, _16, or _32, as ap-
+ propriate.
+
+
+INPUT ENCODING
+
+ Input to pcre2test is processed line by line, either by calling the C
+ library's fgets() function, or via the libreadline or libedit library.
+ In some Windows environments character 26 (hex 1A) causes an immediate
+ end of file, and no further data is read, so this character should be
+ avoided unless you really want that action.
+
+ The input is processed using C's string functions, so must not contain
+ binary zeros, even though in Unix-like environments, fgets() treats any
+ bytes other than newline as data characters. An error is generated if a
+ binary zero is encountered. By default subject lines are processed for
+ backslash escapes, which makes it possible to include any data value in
+ strings that are passed to the library for matching. For patterns,
+ there is a facility for specifying some or all of the 8-bit input char-
+ acters as hexadecimal pairs, which makes it possible to include binary
+ zeros.
+
+ Input for the 16-bit and 32-bit libraries
+
+ When testing the 16-bit or 32-bit libraries, there is a need to be able
+ to generate character code points greater than 255 in the strings that
+ are passed to the library. For subject lines and some patterns, back-
+ slash escapes can be used. In addition, when the utf modifier (see
+ "Setting compilation options" below) is set, the pattern and any fol-
+ lowing subject lines are interpreted as UTF-8 strings and translated to
+ UTF-16 or UTF-32 as appropriate.
+
+ For non-UTF testing of wide characters, the utf8_input modifier can be
+ used. This is mutually exclusive with utf, and is allowed only in
+ 16-bit or 32-bit mode. It causes the pattern and following subject
+ lines to be treated as UTF-8 according to the original definition (RFC
+ 2279), which allows for character values up to 0x7fffffff. Each charac-
+ ter is placed in one 16-bit or 32-bit code unit (in the 16-bit case,
+ values greater than 0xffff cause an error to occur).
+
+ UTF-8 (in its original definition) is not capable of encoding values
+ greater than 0x7fffffff, but such values can be handled by the 32-bit
+ library. When testing this library in non-UTF mode with utf8_input set,
+ if any character is preceded by the byte 0xff (which is an invalid byte
+ in UTF-8) 0x80000000 is added to the character's value. For subject
+ strings, using an escape sequence is preferable.
+
+
+COMMAND LINE OPTIONS
+
+ -8 If the 8-bit library has been built, this option causes it to
+ be used (this is the default). If the 8-bit library has not
+ been built, this option causes an error.
+
+ -16 If the 16-bit library has been built, this option causes it
+ to be used. If the 8-bit library has not been built, this is
+ the default. If the 16-bit library has not been built, this
+ option causes an error.
+
+ -32 If the 32-bit library has been built, this option causes it
+ to be used. If no other library has been built, this is the
+ default. If the 32-bit library has not been built, this op-
+ tion causes an error.
+
+ -ac Behave as if each pattern has the auto_callout modifier, that
+ is, insert automatic callouts into every pattern that is com-
+ piled.
+
+ -AC As for -ac, but in addition behave as if each subject line
+ has the callout_extra modifier, that is, show additional in-
+ formation from callouts.
+
+ -b Behave as if each pattern has the fullbincode modifier; the
+ full internal binary form of the pattern is output after com-
+ pilation.
+
+ -C Output the version number of the PCRE2 library, and all
+ available information about the optional features that are
+ included, and then exit with zero exit code. All other op-
+ tions are ignored. If both -C and -LM are present, whichever
+ is first is recognized.
+
+ -C option Output information about a specific build-time option, then
+ exit. This functionality is intended for use in scripts such
+ as RunTest. The following options output the value and set
+ the exit code as indicated:
+
+ linksize the configured internal link size (2, 3, or 4)
+ exit code is set to the link size
+ newline the default newline setting:
+ CR, LF, CRLF, ANYCRLF, ANY, or NUL
+ exit code is always 0
+ bsr the default setting for what \R matches:
+ ANYCRLF or ANY
+ exit code is always 0
+
+ The following options output 1 for true or 0 for false, and
+ set the exit code to the same value:
+
+ backslash-C \C is supported (not locked out)
+ ebcdic compiled for an EBCDIC environment
+ ebcdic-io if PCRE2 is compiled for EBCDIC, whether
+ pcre2test's input and
+ output is EBCDIC or ASCII
+ ebcdic-nl25 if PCRE2 is compiled for EBCDIC, whether NL (=
+ LF) is 0x25
+ (otherwise it is 0x15, the default)
+ jit just-in-time support is available
+ pcre2-16 the 16-bit library was built
+ pcre2-32 the 32-bit library was built
+ pcre2-8 the 8-bit library was built
+ unicode Unicode support is available
+
+ Note that the availability of JIT support in the library does
+ not guarantee that it can actually be used because in some
+ environments it is unable to allocate executable memory. The
+ option "jitusable" gives more detailed information. It re-
+ turns one of the following values:
+
+ 0 JIT is available and usable
+ 1 JIT is available but cannot allocate executable memory
+ 2 JIT is not available
+ 3 Unexpected return from test call to pcre2_jit_compile()
+
+ If an unknown option is given, an error message is output;
+ the exit code is 0.
+
+ --colo[u]r[=]
+ With auto, the output is coloured if the output is to a ter-
+ minal. Force or suppress output of ANSI colour escapes with
+ always (or no specifier provided) and never respectively. If
+ no colour option is provided, the default is auto, unless the
+ NO_COLOR environment variable is defined and non-empty.
+
+ -d Behave as if each pattern has the debug modifier; the inter-
+ nal form and information about the compiled pattern is output
+ after compilation; -d is equivalent to -b -i.
+
+ -dfa Behave as if each subject line has the dfa modifier; matching
+ is done using the pcre2_dfa_match() function instead of the
+ default pcre2_match().
+
+ -E Run in "preprocess only" mode (similar to "gcc -E"). The "#if
+ ... #endif" commands are processed, and all other lines are
+ printed verbatim.
+
+ -error number[,number,...]
+ Call pcre2_get_error_message() for each of the error numbers
+ in the comma-separated list, display the resulting messages
+ on the standard output, then exit with zero exit code. The
+ numbers may be positive or negative. This is a convenience
+ facility for PCRE2 maintainers.
+
+ -help Output a brief summary these options and then exit.
+
+ -i Behave as if each pattern has the info modifier; information
+ about the compiled pattern is given after compilation.
+
+ -jit Behave as if each pattern line has the jit modifier; after
+ successful compilation, each pattern is passed to the just-
+ in-time compiler, if available.
+
+ -jitfast Behave as if each pattern line has the jitfast modifier; af-
+ ter successful compilation, each pattern is passed to the
+ just-in-time compiler, if available, and each subject line is
+ passed directly to the JIT matcher via its "fast path".
+
+ -jitverify
+ Behave as if each pattern line has the jitverify modifier;
+ after successful compilation, each pattern is passed to the
+ just-in-time compiler, if available, and the use of JIT for
+ matching is verified.
+
+ -LM List modifiers: write a list of available pattern and subject
+ modifiers to the standard output, then exit with zero exit
+ code. All other options are ignored. If both -C and any -Lx
+ options are present, whichever is first is recognized.
+
+ -LP List properties: write a list of recognized Unicode proper-
+ ties to the standard output, then exit with zero exit code.
+ All other options are ignored. If both -C and any -Lx options
+ are present, whichever is first is recognized.
+
+ -LS List scripts: write a list of recognized Unicode script names
+ to the standard output, then exit with zero exit code. All
+ other options are ignored. If both -C and any -Lx options are
+ present, whichever is first is recognized.
+
+ -malloc Exercise malloc() failures, by first counting the number of
+ calls made to malloc during pattern compilation and matching,
+ then re-running the compilation and matching that many times,
+ exercising a failure of each malloc() call.
+
+ -pattern modifier-list
+ Behave as if each pattern line contains the given modifiers.
+
+ -q Do not output the version number of pcre2test at the start of
+ execution.
+
+ -S size On Unix-like systems, set the size of the run-time stack to
+ size mebibytes (units of 1024*1024 bytes).
+
+ -subject modifier-list
+ Behave as if each subject line contains the given modifiers.
+
+ -t Run each compile and match many times with a timer, and out-
+ put the resulting times per compile or match. When JIT is
+ used, separate times are given for the initial compile and
+ the JIT compile. You can control the number of iterations
+ that are used for timing by following -t with a number (as a
+ separate item on the command line). For example, "-t 1000"
+ iterates 1000 times. The default is to iterate 500,000 times.
+
+ -tm This is like -t except that it times only the matching phase,
+ not the compile phase.
+
+ -T -TM These behave like -t and -tm, but in addition, at the end of
+ a run, the total times for all compiles and matches are out-
+ put.
+
+ -unittest Run a fixed set of additional tests of the PCRE2 API which
+ are not driven by the test input files, and then exit.
+
+ -version Output the PCRE2 version number and then exit.
+
+
+DESCRIPTION
+
+ If pcre2test is given two filename arguments, it reads from the first
+ and writes to the second. If the first name is "-", input is taken from
+ the standard input. If pcre2test is given only one argument, it reads
+ from that file and writes to stdout. Otherwise, it reads from stdin and
+ writes to stdout.
+
+ When pcre2test is built, a configuration option can specify that it
+ should be linked with the libreadline or libedit library. When this is
+ done, if the input is from a terminal, it is read using the readline()
+ function. This provides line-editing and history facilities. The output
+ from the -help option states whether or not readline() will be used.
+
+ The program handles any number of tests, each of which consists of a
+ set of input lines. Each set starts with a regular expression pattern,
+ followed by any number of subject lines to be matched against that pat-
+ tern. In between sets of test data, command lines that begin with # may
+ appear. This file format, with some restrictions, can also be processed
+ by the perltest.sh script that is distributed with PCRE2 as a means of
+ checking that the behaviour of PCRE2 and Perl is the same. For a speci-
+ fication of perltest.sh, see the comments near its beginning. See also
+ the #perltest command below.
+
+ When the input is a terminal, pcre2test prompts for each line of input,
+ using "re>" to prompt for regular expression patterns, and "data>" to
+ prompt for subject lines. Command lines starting with # can be entered
+ only in response to the "re>" prompt.
+
+ Each subject line is matched separately and independently. If you want
+ to do multi-line matches, you have to use the \n escape sequence (or \r
+ or \r\n, etc., depending on the newline setting) in a single line of
+ input to encode the newline sequences. There is no limit on the length
+ of subject lines; the input buffer is automatically extended if it is
+ too small. There are replication features that makes it possible to
+ generate long repetitive pattern or subject lines without having to
+ supply them explicitly.
+
+ An empty line or the end of the file signals the end of the subject
+ lines for a test, at which point a new pattern or command line is ex-
+ pected if there is still input to be read.
+
+
+COMMAND LINES
+
+ In between sets of test data, a line that begins with # is interpreted
+ as a command line. If the first character is followed by white space or
+ an exclamation mark, the line is treated as a comment, and ignored.
+ Otherwise, the following commands are recognized:
+
+ #forbid_utf
+
+ Subsequent patterns automatically have the PCRE2_NEVER_UTF and
+ PCRE2_NEVER_UCP options set, which locks out the use of the PCRE2_UTF
+ and PCRE2_UCP options and the use of (*UTF) and (*UCP) at the start of
+ patterns. This command also forces an error if a subsequent pattern
+ contains any occurrences of \P, \p, or \X, which are still supported
+ when PCRE2_UTF is not set, but which require Unicode property support
+ to be included in the library.
+
+ This is a trigger guard that is used in test files to ensure that UTF
+ or Unicode property tests are not accidentally added to files that are
+ used when Unicode support is not included in the library. Setting
+ PCRE2_NEVER_UTF and PCRE2_NEVER_UCP as a default can also be obtained
+ by the use of #pattern; the difference is that #forbid_utf cannot be
+ unset, and the automatic options are not displayed in pattern informa-
+ tion, to avoid cluttering up test output.
+
+ #load
+
+ This command is used to load a set of precompiled patterns from a file,
+ as described in the section entitled "Saving and restoring compiled
+ patterns" below.
+
+ #loadtables
+
+ This command is used to load a set of binary character tables that can
+ be accessed by the tables=3 qualifier. Such tables can be created by
+ the pcre2_dftables program with the -b option.
+
+ #newline_default []
+
+ When PCRE2 is built, a default newline convention can be specified.
+ This determines which characters and/or character pairs are recognized
+ as indicating a newline in a pattern or subject string. The default can
+ be overridden when a pattern is compiled. The standard test files con-
+ tain tests of various newline conventions, but the majority of the
+ tests expect a single linefeed to be recognized as a newline by de-
+ fault. Without special action the tests would fail when PCRE2 is com-
+ piled with either CR or CRLF as the default newline.
+
+ The #newline_default command specifies a list of newline types that are
+ acceptable as the default. The types must be one of CR, LF, CRLF, ANY-
+ CRLF, ANY, or NUL (in upper or lower case), for example:
+
+ #newline_default LF Any anyCRLF
+
+ If the default newline is in the list, this command has no effect. Oth-
+ erwise, except when testing the POSIX API, a newline modifier that
+ specifies the first newline convention in the list (LF in the above ex-
+ ample) is added to any pattern that does not already have a newline
+ modifier. If the newline list is empty, the feature is turned off. This
+ command is present in a number of the standard test input files.
+
+ When the POSIX API is being tested there is no way to override the de-
+ fault newline convention, though it is possible to set the newline con-
+ vention from within the pattern. A warning is given if the posix or
+ posix_nosub modifier is used when #newline_default would set a default
+ for the non-POSIX API.
+
+ #pattern
+
+ This command sets a default modifier list that applies to all subse-
+ quent patterns. Modifiers on a pattern can change these settings.
+
+ #perltest
+
+ This line is used in test files that can also be processed by perl-
+ test.sh to confirm that Perl gives the same results as PCRE2. Subse-
+ quent tests are checked for the use of pcre2test features that are in-
+ compatible with the perltest.sh script.
+
+ Patterns must use '/' as their delimiter, and only certain modifiers
+ are supported. Comment lines, #pattern commands, and #subject commands
+ that set or unset "mark" are recognized and acted on. The #perltest,
+ #forbid_utf, and #newline_default commands, which are needed in the
+ relevant pcre2test files, are silently ignored. All other command lines
+ are ignored, but give a warning message. The #perltest command helps
+ detect tests that are accidentally put in the wrong file or use the
+ wrong delimiter. For more details of the perltest.sh script see the
+ comments it contains.
+
+ #pop []
+ #popcopy []
+
+ These commands are used to manipulate the stack of compiled patterns,
+ as described in the section entitled "Saving and restoring compiled
+ patterns" below.
+
+ #save
+
+ This command is used to save a set of compiled patterns to a file, as
+ described in the section entitled "Saving and restoring compiled pat-
+ terns" below.
+
+ #subject
+
+ This command sets a default modifier list that applies to all subse-
+ quent subject lines. Modifiers on a subject line can change these set-
+ tings.
+
+ #if CONDITION
+ ...
+ #endif
+
+ If CONDITION is true, then the command is printed, and its contents are
+ processed as normal, including printing the commandlines to the output.
+ If CONDITION is false, then all lines between the "#if" and "#endif"
+ are skipped and not printed. The CONDITION can be any of the conditions
+ which are tested by the "-C" commandline option and which set
+ pcre2test's exit code to a boolean value. The CONDITION may also be
+ preceded by "!".
+
+
+MODIFIER SYNTAX
+
+ Modifier lists are used with both pattern and subject lines. Items in a
+ list are separated by commas followed by optional white space. Trailing
+ white space in a modifier list is ignored. Some modifiers may be given
+ for both patterns and subject lines, whereas others are valid only for
+ one or the other. Each modifier has a long name, for example "an-
+ chored", and some of them must be followed by an equals sign and a
+ value, for example, "offset=12". Values cannot contain comma charac-
+ ters, but may contain spaces. Modifiers that do not take values may be
+ preceded by a minus sign to turn off a previous setting.
+
+ A few of the more common modifiers can also be specified as single let-
+ ters, for example "i" for "caseless". In documentation, following the
+ Perl convention, these are written with a slash ("the /i modifier") for
+ clarity. Abbreviated modifiers must all be concatenated in the first
+ item of a modifier list. If the first item is not recognized as a long
+ modifier name, it is interpreted as a sequence of these abbreviations.
+ For example:
+
+ /abc/ig,newline=cr,jit=3
+
+ This is a pattern line whose modifier list starts with two one-letter
+ modifiers (/i and /g). The lower-case abbreviated modifiers are the
+ same as used in Perl.
+
+
+PATTERN SYNTAX
+
+ A pattern line must start with one of the following characters (common
+ symbols, excluding pattern meta-characters):
+
+ / ! " ' ` - = _ : ; , % & @ ~
+
+ This is interpreted as the pattern's delimiter. A regular expression
+ may be continued over several input lines, in which case the newline
+ characters are included within it. It is possible to include the delim-
+ iter as a literal within the pattern by escaping it with a backslash,
+ for example
+
+ /abc\/def/
+
+ If you do this, the escape and the delimiter form part of the pattern,
+ but since the delimiters are all non-alphanumeric, the inclusion of the
+ backslash does not affect the pattern's interpretation. Note, however,
+ that this trick does not work within \Q...\E literal bracketing because
+ the backslash will itself be interpreted as a literal. If the terminat-
+ ing delimiter is immediately followed by a backslash, for example,
+
+ /abc/\
+
+ a backslash is added to the end of the pattern. This is done to provide
+ a way of testing the error condition that arises if a pattern finishes
+ with a backslash, because
+
+ /abc\/
+
+ is interpreted as the first line of a pattern that starts with "abc/",
+ causing pcre2test to read the next line as a continuation of the regu-
+ lar expression.
+
+ A pattern can be followed by a modifier list (details below).
+
+
+SUBJECT LINE SYNTAX
+
+ Before each subject line is passed to pcre2_match(), pcre2_dfa_match(),
+ or pcre2_jit_match(), leading and trailing white space is removed, and
+ the line is scanned for backslash escapes, unless the subject_literal
+ modifier was set for the pattern. The following provide a means of en-
+ coding non-printing characters in a visible way:
+
+ \a alarm (BEL, \x07)
+ \b backspace (\x08)
+ \e escape (\x27)
+ \f form feed (\x0c)
+ \n newline (\x0a)
+ \N{U+hh...} unicode character (any number of hex digits)
+ \r carriage return (\x0d)
+ \t tab (\x09)
+ \v vertical tab (\x0b)
+ \ddd octal number (up to 3 octal digits); represent a single
+ code point unless larger than 255 with the 8-bit li-
+ brary
+ \o{dd...} octal number (any number of octal digits} representing a
+ character in UTF mode or a code point
+ \xhh hexadecimal byte (up to 2 hex digits)
+ \x{hh...} hexadecimal number (up to 8 hex digits) representing a
+ character in UTF mode or a code point
+
+ Invoking \N{U+hh...} or \x{hh...} doesn't require the use of the utf
+ modifier on the pattern. It is always recognized. There may be any num-
+ ber of hexadecimal digits inside the braces; invalid values provoke er-
+ ror messages but when using \N{U+hh...} with some invalid unicode char-
+ acters they will be accepted with a warning instead.
+
+ Note that even in UTF-8 mode, \xhh (and depending of how large, \ddd)
+ describe one byte rather than one character; this makes it possible to
+ construct invalid UTF-8 sequences for testing purposes. On the other
+ hand, \x{hh...} is interpreted as a UTF-8 character in UTF-8 mode, only
+ generating more than one byte if the value is greater than 127. To
+ avoid the ambiguity it is preferred to use \N{U+hh...} when describing
+ characters. When testing the 8-bit library not in UTF-8 mode, \x{hh}
+ generates one byte for values that could fit on it, and causes an error
+ for greater values.
+
+ When testing the 16-bit library, not in UTF-16 mode, all 4-digit
+ \x{hhhh} values are accepted. This makes it possible to construct in-
+ valid UTF-16 sequences for testing purposes.
+
+ When testing the 32-bit library, not in UTF-32 mode, all 4 to 8-digit
+ \x{...} values are accepted. This makes it possible to construct in-
+ valid UTF-32 sequences for testing purposes.
+
+ There is a special backslash sequence that specifies replication of one
+ or more characters:
+
+ \[]{}
+
+ This makes it possible to test long strings without having to provide
+ them as part of the file. For example:
+
+ \[abc]{4}
+
+ is converted to "abcabcabcabc". This feature does not support nesting.
+ To include a closing square bracket in the characters, code it as \x5D.
+
+ A backslash followed by an equals sign marks the end of the subject
+ string and the start of a modifier list. For example:
+
+ abc\=notbol,notempty
+
+ If the subject string is empty and \= is followed by white space, the
+ line is treated as a comment line, and is not used for matching. For
+ example:
+
+ \= This is a comment.
+ abc\= This is an invalid modifier list.
+
+ A backslash followed by any other non-alphanumeric character just es-
+ capes that character. A backslash followed by anything else causes an
+ error. However, if the very last character in the line is a backslash
+ (and there is no modifier list), it is ignored. This gives a way of
+ passing an empty line as data, since a real empty line terminates the
+ data input.
+
+ If the subject_literal modifier is set for a pattern, all subject lines
+ that follow are treated as literals, with no special treatment of back-
+ slashes. No replication is possible, and any subject modifiers must be
+ set as defaults by a #subject command.
+
+
+PATTERN MODIFIERS
+
+ There are several types of modifier that can appear in pattern lines.
+ Except where noted below, they may also be used in #pattern commands. A
+ pattern's modifier list can add to or override default modifiers that
+ were set by a previous #pattern command.
+
+ Setting compilation options
+
+ The following modifiers set options for pcre2_compile(). Most of them
+ set bits in the options argument of that function, but those whose
+ names start with PCRE2_EXTRA are additional options that are set in the
+ compile context. Some of these options have single-letter abbrevia-
+ tions. There is special handling for /x: if a second x is present,
+ PCRE2_EXTENDED is converted into PCRE2_EXTENDED_MORE as in Perl. A
+ third appearance adds PCRE2_EXTENDED as well, though this makes no dif-
+ ference to the way pcre2_compile() behaves. See pcre2api for a descrip-
+ tion of the effects of these options.
+
+ allow_empty_class set PCRE2_ALLOW_EMPTY_CLASS
+ allow_lookaround_bsk set PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK
+ allow_surrogate_escapes set PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES
+ alt_bsux set PCRE2_ALT_BSUX
+ alt_circumflex set PCRE2_ALT_CIRCUMFLEX
+ alt_extended_class set PCRE2_ALT_EXTENDED_CLASS
+ alt_verbnames set PCRE2_ALT_VERBNAMES
+ anchored set PCRE2_ANCHORED
+ /a ascii_all set all ASCII options
+ ascii_bsd set PCRE2_EXTRA_ASCII_BSD
+ ascii_bss set PCRE2_EXTRA_ASCII_BSS
+ ascii_bsw set PCRE2_EXTRA_ASCII_BSW
+ ascii_digit set PCRE2_EXTRA_ASCII_DIGIT
+ ascii_posix set PCRE2_EXTRA_ASCII_POSIX
+ auto_callout set PCRE2_AUTO_CALLOUT
+ bad_escape_is_literal set PCRE2_EXTRA_BAD_ESCAPE_IS_LITERAL
+ /i caseless set PCRE2_CASELESS
+ /r caseless_restrict set PCRE2_EXTRA_CASELESS_RESTRICT
+ dollar_endonly set PCRE2_DOLLAR_ENDONLY
+ /s dotall set PCRE2_DOTALL
+ dupnames set PCRE2_DUPNAMES
+ endanchored set PCRE2_ENDANCHORED
+ escaped_cr_is_lf set PCRE2_EXTRA_ESCAPED_CR_IS_LF
+ /x extended set PCRE2_EXTENDED
+ /xx extended_more set PCRE2_EXTENDED_MORE
+ extra_alt_bsux set PCRE2_EXTRA_ALT_BSUX
+ firstline set PCRE2_FIRSTLINE
+ literal set PCRE2_LITERAL
+ match_line set PCRE2_EXTRA_MATCH_LINE
+ match_invalid_utf set PCRE2_MATCH_INVALID_UTF
+ match_unset_backref set PCRE2_MATCH_UNSET_BACKREF
+ match_word set PCRE2_EXTRA_MATCH_WORD
+ /m multiline set PCRE2_MULTILINE
+ never_backslash_c set PCRE2_NEVER_BACKSLASH_C
+ never_callout set PCRE2_EXTRA_NEVER_CALLOUT
+ never_ucp set PCRE2_NEVER_UCP
+ never_utf set PCRE2_NEVER_UTF
+ /n no_auto_capture set PCRE2_NO_AUTO_CAPTURE
+ no_auto_possess set PCRE2_NO_AUTO_POSSESS
+ no_bs0 set PCRE2_EXTRA_NO_BS0
+ no_dotstar_anchor set PCRE2_NO_DOTSTAR_ANCHOR
+ no_start_optimize set PCRE2_NO_START_OPTIMIZE
+ no_utf_check set PCRE2_NO_UTF_CHECK
+ python_octal set PCRE2_EXTRA_PYTHON_OCTAL
+ turkish_casing set PCRE2_EXTRA_TURKISH_CASING
+ ucp set PCRE2_UCP
+ ungreedy set PCRE2_UNGREEDY
+ use_offset_limit set PCRE2_USE_OFFSET_LIMIT
+ utf set PCRE2_UTF
+
+ As well as turning on the PCRE2_UTF option, the utf modifier causes all
+ non-printing characters in output strings to be printed using the
+ \x{hh...} notation. Otherwise, those less than 0x100 are output in hex
+ without the curly brackets. Setting utf in 16-bit or 32-bit mode also
+ causes pattern and subject strings to be translated to UTF-16 or
+ UTF-32, respectively, before being passed to library functions.
+
+ The following modifiers enable or disable performance optimizations by
+ calling pcre2_set_optimize() before invoking the regex compiler.
+
+ optimization_full enable all optional optimizations
+ optimization_none disable all optional optimizations
+ auto_possess auto-possessify variable quantifiers
+ auto_possess_off don't auto-possessify variable quantifiers
+ dotstar_anchor anchor patterns starting with .*
+ dotstar_anchor_off don't anchor patterns starting with .*
+ start_optimize enable pre-scan of subject string
+ start_optimize_off disable pre-scan of subject string
+
+ See the pcre2_set_optimize documentation for details on these optimiza-
+ tions.
+
+ Setting compilation controls
+
+ The following modifiers affect the compilation process or request in-
+ formation about the pattern. There are single-letter abbreviations for
+ some that are heavily used in the test files.
+
+ /B bincode show binary code without lengths
+ bsr=[anycrlf|unicode] specify \R handling
+ callout_info show callout information
+ convert= request foreign pattern conversion
+ convert_glob_escape=c set glob escape character
+ convert_glob_separator=c set glob separator character
+ convert_length set convert buffer length
+ debug same as info,fullbincode
+ expand expand repetition syntax in pattern
+ framesize show matching frame size
+ fullbincode show binary code with lengths
+ /I info show info about compiled pattern
+ hex unquoted characters are hexadecimal
+ jit[=] use JIT
+ jitfast use JIT fast path
+ jitverify verify JIT use
+ locale= use this locale
+ max_pattern_compiled ) set maximum compiled pattern
+ _length= ) length (bytes)
+ max_pattern_length= set maximum pattern length (code units)
+ max_varlookbehind= set maximum variable lookbehind length
+ memory show memory used
+ newline= set newline type
+ null_context compile with a NULL context
+ null_pattern pass pattern as NULL
+ parens_nest_limit= set maximum parentheses depth
+ posix use the POSIX API
+ posix_nosub use the POSIX API with REG_NOSUB
+ push push compiled pattern onto the stack
+ pushcopy push a copy onto the stack
+ pushtablescopy push a copy with tables onto the stack
+ stackguard= test the stackguard feature
+ subject_literal treat all subject lines as literal
+ tables=[0|1|2|3] select internal tables
+ use_length do not zero-terminate the pattern
+ utf8_input treat input as UTF-8
+
+ The effects of these modifiers are described in the following sections.
+
+ Newline and \R handling
+
+ The bsr modifier specifies what \R in a pattern should match. If it is
+ set to "anycrlf", \R matches CR, LF, or CRLF only. If it is set to
+ "unicode", \R matches any Unicode newline sequence. The default can be
+ specified when PCRE2 is built; if it is not, the default is set to Uni-
+ code.
+
+ The newline modifier specifies which characters are to be interpreted
+ as newlines, both in the pattern and in subject lines. The type must be
+ one of CR, LF, CRLF, ANYCRLF, ANY, or NUL (in upper or lower case).
+
+ Information about a pattern
+
+ The debug modifier is a shorthand for info,fullbincode, requesting all
+ available information.
+
+ The bincode modifier causes a representation of the compiled code to be
+ output after compilation. This information does not contain length and
+ offset values, which ensures that the same output is generated for dif-
+ ferent internal link sizes and different code unit widths. By using
+ bincode, the same regression tests can be used in different environ-
+ ments.
+
+ The fullbincode modifier, by contrast, does include length and offset
+ values. This is used in a few special tests that run only for specific
+ code unit widths and link sizes, and is also useful for one-off tests.
+
+ The info modifier requests information about the compiled pattern
+ (whether it is anchored, has a fixed first character, and so on). The
+ information is obtained from the pcre2_pattern_info() function. Here
+ are some typical examples:
+
+ re> /(?i)(^a|^b)/m,info
+ Capture group count = 1
+ Compile options: multiline
+ Overall options: caseless multiline
+ First code unit at start or follows newline
+ Subject length lower bound = 1
+
+ re> /(?i)abc/info
+ Capture group count = 0
+ Compile options:
+ Overall options: caseless
+ First code unit = 'a' (caseless)
+ Last code unit = 'c' (caseless)
+ Subject length lower bound = 3
+
+ "Compile options" are those specified by modifiers; "overall options"
+ have added options that are taken or deduced from the pattern. If both
+ sets of options are the same, just a single "options" line is output;
+ if there are no options, the line is omitted. "First code unit" is
+ where any match must start; if there is more than one they are listed
+ as "starting code units". "Last code unit" is the last literal code
+ unit that must be present in any match. This is not necessarily the
+ last character. These lines are omitted if no starting or ending code
+ units are recorded. The subject length line is omitted when
+ no_start_optimize is set because the minimum length is not calculated
+ when it can never be used.
+
+ The framesize modifier shows the size, in bytes, of each storage frame
+ used by pcre2_match() for handling backtracking. The size depends on
+ the number of capturing parentheses in the pattern. A vector of these
+ frames is used at matching time; its overall size is shown when the
+ heapframes_size subject modifier is set.
+
+ The callout_info modifier requests information about all the callouts
+ in the pattern. A list of them is output at the end of any other infor-
+ mation that is requested. For each callout, either its number or string
+ is given, followed by the item that follows it in the pattern.
+
+ Passing a NULL context
+
+ Normally, pcre2test passes a context block to pcre2_compile(). If the
+ null_context modifier is set, however, NULL is passed. This is for
+ testing that pcre2_compile() behaves correctly in this case (it uses
+ default values).
+
+ Passing a NULL pattern
+
+ The null_pattern modifier is for testing the behaviour of pcre2_com-
+ pile() when the pattern argument is NULL. The length value passed is
+ the default PCRE2_ZERO_TERMINATED unless use_length is set. Any length
+ other than zero causes an error.
+
+ Specifying pattern characters in hexadecimal
+
+ The hex modifier specifies that the characters of the pattern, except
+ for substrings enclosed in single or double quotes, are to be inter-
+ preted as pairs of hexadecimal digits. This feature is provided as a
+ way of creating patterns that contain binary zeros and other non-print-
+ ing characters. White space is permitted between pairs of digits. For
+ example, this pattern contains three characters:
+
+ /ab 32 59/hex
+
+ Parts of such a pattern are taken literally if quoted. This pattern
+ contains nine characters, only two of which are specified in hexadeci-
+ mal:
+
+ /ab "literal" 32/hex
+
+ Either single or double quotes may be used. There is no way of includ-
+ ing the delimiter within a substring. The hex and expand modifiers are
+ mutually exclusive.
+
+ Specifying the pattern's length
+
+ By default, patterns are passed to the compiling functions as zero-ter-
+ minated strings but can be passed by length instead of being zero-ter-
+ minated. The use_length modifier causes this to happen. Using a length
+ happens automatically (whether or not use_length is set) when hex is
+ set, because patterns specified in hexadecimal may contain binary ze-
+ ros.
+
+ If hex or use_length is used with the POSIX wrapper API (see "Using the
+ POSIX wrapper API" below), the REG_PEND extension is used to pass the
+ pattern's length.
+
+ Specifying a maximum for variable lookbehinds
+
+ Variable lookbehind assertions are supported only if, for each one,
+ there is a maximum length (in characters) that it can match. There is a
+ limit on this, whose default can be set at build time, with an ultimate
+ default of 255. The max_varlookbehind modifier uses the
+ pcre2_set_max_varlookbehind() function to change the limit. Lookbehinds
+ whose branches each match a fixed length are limited to 65535 charac-
+ ters per branch.
+
+ Specifying wide characters in 16-bit and 32-bit modes
+
+ In 16-bit and 32-bit modes, all input is automatically treated as UTF-8
+ and translated to UTF-16 or UTF-32 when the utf modifier is set. For
+ testing the 16-bit and 32-bit libraries in non-UTF mode, the utf8_input
+ modifier can be used. It is mutually exclusive with utf. Input lines
+ are interpreted as UTF-8 as a means of specifying wide characters. More
+ details are given in "Input encoding" above.
+
+ Generating long repetitive patterns
+
+ Some tests use long patterns that are very repetitive. Instead of cre-
+ ating a very long input line for such a pattern, you can use a special
+ repetition feature, similar to the one described for subject lines
+ above. If the expand modifier is present on a pattern, parts of the
+ pattern that have the form
+
+ \[]{}
+
+ are expanded before the pattern is passed to pcre2_compile(). For exam-
+ ple, \[AB]{6000} is expanded to "ABAB..." 6000 times. This construction
+ cannot be nested. An initial "\[" sequence is recognized only if "]{"
+ followed by decimal digits and "}" is found later in the pattern. If
+ not, the characters remain in the pattern unaltered. The expand and hex
+ modifiers are mutually exclusive.
+
+ If part of an expanded pattern looks like an expansion, but is really
+ part of the actual pattern, unwanted expansion can be avoided by giving
+ two values in the quantifier. For example, \[AB]{6000,6000} is not rec-
+ ognized as an expansion item.
+
+ If the info modifier is set on an expanded pattern, the result of the
+ expansion is included in the information that is output.
+
+ JIT compilation
+
+ Just-in-time (JIT) compiling is a heavyweight optimization that can
+ greatly speed up pattern matching. See the pcre2jit documentation for
+ details. JIT compiling happens, optionally, after a pattern has been
+ successfully compiled into an internal form. The JIT compiler converts
+ this to optimized machine code. It needs to know whether the match-time
+ options PCRE2_PARTIAL_HARD and PCRE2_PARTIAL_SOFT are going to be used,
+ because different code is generated for the different cases. See the
+ partial modifier in "Subject Modifiers" below for details of how these
+ options are specified for each match attempt.
+
+ JIT compilation is requested by the jit pattern modifier, which may op-
+ tionally be followed by an equals sign and a number in the range 0 to
+ 7. The three bits that make up the number specify which of the three
+ JIT operating modes are to be compiled:
+
+ 1 compile JIT code for non-partial matching
+ 2 compile JIT code for soft partial matching
+ 4 compile JIT code for hard partial matching
+
+ The possible values for the jit modifier are therefore:
+
+ 0 disable JIT
+ 1 normal matching only
+ 2 soft partial matching only
+ 3 normal and soft partial matching
+ 4 hard partial matching only
+ 6 soft and hard partial matching only
+ 7 all three modes
+
+ If no number is given, 7 is assumed. The phrase "partial matching"
+ means a call to pcre2_match() with either the PCRE2_PARTIAL_SOFT or the
+ PCRE2_PARTIAL_HARD option set. Note that such a call may return a com-
+ plete match; the options enable the possibility of a partial match, but
+ do not require it. Note also that if you request JIT compilation only
+ for partial matching (for example, jit=2) but do not set the partial
+ modifier on a subject line, that match will not use JIT code because
+ none was compiled for non-partial matching.
+
+ If JIT compilation is successful, the compiled JIT code will automati-
+ cally be used when an appropriate type of match is run, except when in-
+ compatible run-time options are specified. For more details, see the
+ pcre2jit documentation. See also the jitstack modifier below for a way
+ of setting the size of the JIT stack.
+
+ If the jitfast modifier is specified, matching is done using the JIT
+ "fast path" interface, pcre2_jit_match(), which skips some of the san-
+ ity checks that are done by pcre2_match(), and of course does not work
+ when JIT is not supported. If jitfast is specified without jit, jit=7
+ is assumed.
+
+ If the jitverify modifier is specified, information about the compiled
+ pattern shows whether JIT compilation was or was not successful. If
+ jitverify is specified without jit, jit=7 is assumed. If JIT compila-
+ tion is successful when jitverify is set, the text "(JIT)" is added to
+ the first output line after a match or non match when JIT-compiled code
+ was actually used in the match.
+
+ Setting a locale
+
+ The locale modifier must specify the name of a locale, for example:
+
+ /pattern/locale=fr_FR
+
+ The given locale is set, pcre2_maketables() is called to build a set of
+ character tables for the locale, and this is then passed to pcre2_com-
+ pile() when compiling the regular expression. The same tables are used
+ when matching the following subject lines. The locale modifier applies
+ only to the pattern on which it appears, but can be given in a #pattern
+ command if a default is needed. Setting a locale and alternate charac-
+ ter tables are mutually exclusive.
+
+ Showing pattern memory
+
+ The memory modifier causes the size in bytes of the memory used to hold
+ the compiled pattern to be output. This does not include the size of
+ the pcre2_code block; it is just the actual compiled data. If the pat-
+ tern is subsequently passed to the JIT compiler, the size of the JIT
+ compiled code is also output. Here is an example:
+
+ re> /a(b)c/jit,memory
+ Memory allocation (code space): 21
+ Memory allocation (JIT code): 1910
+
+
+ Limiting nested parentheses
+
+ The parens_nest_limit modifier sets a limit on the depth of nested
+ parentheses in a pattern. Breaching the limit causes a compilation er-
+ ror. The default for the library is set when PCRE2 is built, but
+ pcre2test sets its own default of 220, which is required for running
+ the standard test suite.
+
+ Limiting the pattern length
+
+ The max_pattern_length modifier sets a limit, in code units, to the
+ length of pattern that pcre2_compile() will accept. Breaching the limit
+ causes a compilation error. The default is the largest number a
+ PCRE2_SIZE variable can hold (essentially unlimited).
+
+ Limiting the size of a compiled pattern
+
+ The max_pattern_compiled_length modifier sets a limit, in bytes, to the
+ amount of memory used by a compiled pattern. Breaching the limit causes
+ a compilation error. The default is the largest number a PCRE2_SIZE
+ variable can hold (essentially unlimited).
+
+ Using the POSIX wrapper API
+
+ The posix and posix_nosub modifiers cause pcre2test to call PCRE2 via
+ the POSIX wrapper API rather than its native API. When posix_nosub is
+ used, the POSIX option REG_NOSUB is passed to regcomp(). The POSIX
+ wrapper supports only the 8-bit library. Note that it does not imply
+ POSIX matching semantics; for more detail see the pcre2posix documenta-
+ tion. The following pattern modifiers set options for the regcomp()
+ function:
+
+ caseless REG_ICASE
+ multiline REG_NEWLINE
+ dotall REG_DOTALL )
+ ungreedy REG_UNGREEDY ) These options are not part of
+ ucp REG_UCP ) the POSIX standard
+ utf REG_UTF8 )
+
+ The regerror_buffsize modifier specifies a size for the error buffer
+ that is passed to regerror() in the event of a compilation error. For
+ example:
+
+ /abc/posix,regerror_buffsize=20
+
+ This provides a means of testing the behaviour of regerror() when the
+ buffer is too small for the error message. If this modifier has not
+ been set, a large buffer is used.
+
+ The aftertext and allaftertext subject modifiers work as described be-
+ low. All other modifiers are either ignored, with a warning message, or
+ cause an error.
+
+ The pattern is passed to regcomp() as a zero-terminated string by de-
+ fault, but if the use_length or hex modifiers are set, the REG_PEND ex-
+ tension is used to pass it by length.
+
+ Testing the stack guard feature
+
+ The stackguard modifier is used to test the use of pcre2_set_com-
+ pile_recursion_guard(), a function that is provided to enable stack
+ availability to be checked during compilation (see the pcre2api docu-
+ mentation for details). If the number specified by the modifier is
+ greater than zero, pcre2_set_compile_recursion_guard() is called to set
+ up callback from pcre2_compile() to a local function. The argument it
+ receives is the current nesting parenthesis depth; if this is greater
+ than the value given by the modifier, non-zero is returned, causing the
+ compilation to be aborted.
+
+ Using alternative character tables
+
+ The value specified for the tables modifier must be one of the digits
+ 0, 1, 2, or 3. It causes a specific set of built-in character tables to
+ be passed to pcre2_compile(). This is used in the PCRE2 tests to check
+ behaviour with different character tables. The digit specifies the ta-
+ bles as follows:
+
+ 0 do not pass any special character tables
+ 1 the default ASCII tables, as distributed in
+ pcre2_chartables.c.dist
+ 2 a set of tables defining ISO 8859 characters
+ 3 a set of tables loaded by the #loadtables command
+
+ In tables 2, some characters whose codes are greater than 128 are iden-
+ tified as letters, digits, spaces, etc. Tables 3 can be used only after
+ a #loadtables command has loaded them from a binary file. Setting al-
+ ternate character tables and a locale are mutually exclusive.
+
+ Setting certain match controls
+
+ The following modifiers are really subject modifiers, and are described
+ under "Subject Modifiers" below. However, they may be included in a
+ pattern's modifier list, in which case they are applied to every sub-
+ ject line that is processed with that pattern. These modifiers do not
+ affect the compilation process.
+
+ aftertext show text after match
+ allaftertext show text after captures
+ allcaptures show all captures
+ allvector show the entire ovector
+ allusedtext show all consulted text
+ altglobal alternative global matching
+ /g global global matching
+ heapframes_size show match data heapframes size
+ jitstack= set size of JIT stack
+ mark show mark values
+ null_substitute_match_data substitute with NULL match data
+ replace= specify a replacement string
+ startchar show starting character when relevant
+ substitute_callout use substitution callouts
+ substitute_case_callout use substitution case callouts
+ substitute_extended use PCRE2_SUBSTITUTE_EXTENDED
+ substitute_literal use PCRE2_SUBSTITUTE_LITERAL
+ substitute_matched use PCRE2_SUBSTITUTE_MATCHED
+ substitute_overflow_length use PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_replacement_only use PCRE2_SUBSTITUTE_REPLACEMENT_ONLY
+ substitute_skip= skip substitution
+ substitute_stop= skip substitution and following
+ substitute_unknown_unset use PCRE2_SUBSTITUTE_UNKNOWN_UNSET
+ substitute_unset_empty use PCRE2_SUBSTITUTE_UNSET_EMPTY
+
+ These modifiers may not appear in a #pattern command. If you want them
+ as defaults, set them in a #subject command.
+
+ Specifying literal subject lines
+
+ If the subject_literal modifier is present on a pattern, all the sub-
+ ject lines that it matches are taken as literal strings, with no inter-
+ pretation of backslashes. It is not possible to set subject modifiers
+ on such lines, but any that are set as defaults by a #subject command
+ are recognized.
+
+ Saving a compiled pattern
+
+ When a pattern with the push modifier is successfully compiled, it is
+ pushed onto a stack of compiled patterns, and pcre2test expects the
+ next line to contain a new pattern (or a command) instead of a subject
+ line. This facility is used when saving compiled patterns to a file, as
+ described in the section entitled "Saving and restoring compiled pat-
+ terns" below. If pushcopy is used instead of push, a copy of the com-
+ piled pattern is stacked, leaving the original as current, ready to
+ match the following input lines. This provides a way of testing the
+ pcre2_code_copy() function. The push and pushcopy modifiers are in-
+ compatible with compilation modifiers such as global that act at match
+ time. Any that are specified are ignored (for the stacked copy), with a
+ warning message, except for replace, which causes an error. Note that
+ jitverify, which is allowed, does not carry through to any subsequent
+ matching that uses a stacked pattern.
+
+ Testing foreign pattern conversion
+
+ The experimental foreign pattern conversion functions in PCRE2 can be
+ tested by setting the convert modifier. Its argument is a colon-sepa-
+ rated list of options, which set the equivalent option for the
+ pcre2_pattern_convert() function:
+
+ glob PCRE2_CONVERT_GLOB
+ glob_no_starstar PCRE2_CONVERT_GLOB_NO_STARSTAR
+ glob_no_wild_separator PCRE2_CONVERT_GLOB_NO_WILD_SEPARATOR
+ posix_basic PCRE2_CONVERT_POSIX_BASIC
+ posix_extended PCRE2_CONVERT_POSIX_EXTENDED
+ unset Unset all options
+
+ The "unset" value is useful for turning off a default that has been set
+ by a #pattern command. When one of these options is set, the input pat-
+ tern is passed to pcre2_pattern_convert(). If the conversion is suc-
+ cessful, the result is reflected in the output and then passed to
+ pcre2_compile(). The normal utf and no_utf_check options, if set, cause
+ the PCRE2_CONVERT_UTF and PCRE2_CONVERT_NO_UTF_CHECK options to be
+ passed to pcre2_pattern_convert().
+
+ By default, the conversion function is allowed to allocate a buffer for
+ its output. However, if the convert_length modifier is set to a value
+ greater than zero, pcre2test passes a buffer of the given length. This
+ makes it possible to test the length check.
+
+ The convert_glob_escape and convert_glob_separator modifiers can be
+ used to specify the escape and separator characters for glob process-
+ ing, overriding the defaults, which are operating-system dependent.
+
+
+SUBJECT MODIFIERS
+
+ The modifiers that can appear in subject lines and the #subject command
+ are of two types.
+
+ Setting match options
+
+ The following modifiers set options for pcre2_match() or
+ pcre2_dfa_match(). See pcre2api for a description of their effects.
+
+ anchored set PCRE2_ANCHORED
+ copy_matched_subject set PCRE2_COPY_MATCHED_SUBJECT
+ endanchored set PCRE2_ENDANCHORED
+ dfa_restart set PCRE2_DFA_RESTART
+ dfa_shortest set PCRE2_DFA_SHORTEST
+ disable_recurseloop_check set PCRE2_DISABLE_RECURSELOOP_CHECK
+ no_jit set PCRE2_NO_JIT
+ no_utf_check set PCRE2_NO_UTF_CHECK
+ notbol set PCRE2_NOTBOL
+ notempty set PCRE2_NOTEMPTY
+ notempty_atstart set PCRE2_NOTEMPTY_ATSTART
+ noteol set PCRE2_NOTEOL
+ partial_hard (or ph) set PCRE2_PARTIAL_HARD
+ partial_soft (or ps) set PCRE2_PARTIAL_SOFT
+
+ The partial matching modifiers are provided with abbreviations because
+ they appear frequently in tests.
+
+ If the posix or posix_nosub modifier was present on the pattern, caus-
+ ing the POSIX wrapper API to be used, the only option-setting modifiers
+ that have any effect are notbol, notempty, and noteol, causing REG_NOT-
+ BOL, REG_NOTEMPTY, and REG_NOTEOL, respectively, to be passed to
+ regexec(). The other modifiers are ignored, with a warning message.
+
+ There is one additional modifier that can be used with the POSIX wrap-
+ per. It is ignored (with a warning) if used for non-POSIX matching.
+
+ posix_startend=[:]
+
+ This causes the subject string to be passed to regexec() using the
+ REG_STARTEND option, which uses offsets to specify which part of the
+ string is searched. If only one number is given, the end offset is
+ passed as the end of the subject string. For more detail of REG_STAR-
+ TEND, see the pcre2posix documentation. If the subject string contains
+ binary zeros (coded as escapes such as \x{00} because pcre2test does
+ not support actual binary zeros in its input), you must use posix_star-
+ tend to specify its length.
+
+ Setting match controls
+
+ The following modifiers affect the matching process or request addi-
+ tional information. Some of them may also be specified on a pattern
+ line (see above), in which case they apply to every subject line that
+ is matched against that pattern, but can be overridden by modifiers on
+ the subject.
+
+ aftertext show text after match
+ allaftertext show text after captures
+ allcaptures show all captures
+ allusedtext show all consulted text (non-JIT only)
+ allvector show the entire ovector
+ altglobal alternative global matching
+ callout_capture show captures at callout time
+ callout_data= set a value to pass via callouts
+ callout_error=[:] control callout error
+ callout_extra show extra callout information
+ callout_fail=[:] control callout failure
+ callout_no_where do not show position of a callout
+ callout_none do not supply a callout function
+ copy= copy captured substring
+ depth_limit= set a depth limit
+ dfa use pcre2_dfa_match()
+ find_limits find heap, match and depth limits
+ find_limits_noheap find match and depth limits
+ get= extract captured substring
+ getall extract all captured substrings
+ /g global global matching
+ heapframes_size show match data heapframes size
+ heap_limit= set a limit on heap memory (Kbytes)
+ jitstack= set size of JIT stack
+ mark show mark values
+ match_limit= set a match limit
+ memory show heap memory usage
+ null_context match with a NULL context
+ null_replacement substitute with NULL replacement
+ null_subject match with NULL subject
+ null_substitute_match_data substitute with NULL match data
+ offset= set starting offset
+ offset_limit= set offset limit
+ ovector= set size of output vector
+ recursion_limit= obsolete synonym for depth_limit
+ replace= specify a replacement string
+ startchar show startchar when relevant
+ startoffset= same as offset=
+ substitute_callout use substitution callouts
+ substitute_case_callout use substitution case callouts
+ substitute_extended use PCRE2_SUBSTITUTE_EXTENDED
+ substitute_literal use PCRE2_SUBSTITUTE_LITERAL
+ substitute_matched use PCRE2_SUBSTITUTE_MATCHED
+ substitute_overflow_length use PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_replacement_only use PCRE2_SUBSTITUTE_REPLACEMENT_ONLY
+ substitute_skip= skip substitution number n
+ substitute_stop= skip substitution number n and greater
+ substitute_subject= specify a different subject for sub-
+ stitution
+ substitute_unknown_unset use PCRE2_SUBSTITUTE_UNKNOWN_UNSET
+ substitute_unset_empty use PCRE2_SUBSTITUTE_UNSET_EMPTY
+ zero_terminate pass the subject as zero-terminated
+
+ The effects of these modifiers are described in the following sections.
+ When matching via the POSIX wrapper API, the aftertext, allaftertext,
+ and ovector subject modifiers work as described below. All other modi-
+ fiers are either ignored, with a warning message, or cause an error.
+
+ Showing more text
+
+ The aftertext modifier requests that as well as outputting the part of
+ the subject string that matched the entire pattern, pcre2test should in
+ addition output the remainder of the subject string. This is useful for
+ tests where the subject contains multiple copies of the same substring.
+ The allaftertext modifier requests the same action for captured sub-
+ strings as well as the main matched substring. In each case the remain-
+ der is output on the following line with a plus character following the
+ capture number.
+
+ The allusedtext modifier requests that all the text that was consulted
+ during a successful pattern match by the interpreter should be shown,
+ for both full and partial matches. This feature is not supported for
+ JIT matching, and if requested with JIT it is ignored (with a warning
+ message). Setting this modifier affects the output if there is a look-
+ behind at the start of a match, or, for a complete match, a lookahead
+ at the end, or if \K is used in the pattern. Characters that precede or
+ follow the start and end of the actual match are indicated in the out-
+ put by '<' or '>' characters underneath them. Here is an example:
+
+ re> /(?<=pqr)abc(?=xyz)/
+ data> 123pqrabcxyz456\=allusedtext
+ 0: pqrabcxyz
+ <<< >>>
+ data> 123pqrabcxy\=ph,allusedtext
+ Partial match: pqrabcxy
+ <<<
+
+ The first, complete match shows that the matched string is "abc", with
+ the preceding and following strings "pqr" and "xyz" having been con-
+ sulted during the match (when processing the assertions). The partial
+ match can indicate only the preceding string.
+
+ The startchar modifier requests that the starting character for the
+ match be indicated, if it is different to the start of the matched
+ string. The only time when this occurs is when \K has been processed as
+ part of the match. In this situation, the output for the matched string
+ is displayed from the starting character instead of from the match
+ point, with circumflex characters under the earlier characters. For ex-
+ ample:
+
+ re> /abc\Kxyz/
+ data> abcxyz\=startchar
+ 0: abcxyz
+ ^^^
+
+ Unlike allusedtext, the startchar modifier can be used with JIT. How-
+ ever, these two modifiers are mutually exclusive.
+
+ Showing the value of all capture groups
+
+ The allcaptures modifier requests that the values of all potential cap-
+ tured parentheses be output after a match. By default, only those up to
+ the highest one actually used in the match are output (corresponding to
+ the return code from pcre2_match()). Groups that did not take part in
+ the match are output as "". This modifier is not relevant for
+ DFA matching (which does no capturing) and does not apply when replace
+ is specified; it is ignored, with a warning message, if present.
+
+ Showing the entire ovector, for all outcomes
+
+ The allvector modifier requests that the entire ovector be shown, what-
+ ever the outcome of the match. Compare allcaptures, which shows only up
+ to the maximum number of capture groups for the pattern, and then only
+ for a successful complete non-DFA match. This modifier, which acts af-
+ ter any match result, and also for DFA matching, provides a means of
+ checking that there are no unexpected modifications to ovector fields.
+ Before each match attempt, the ovector is filled with a special value,
+ and if this is found in both elements of a capturing pair, "" is output. After a successful match, this applies to all
+ groups after the maximum capture group for the pattern. In other cases
+ it applies to the entire ovector. After a partial match, the first two
+ elements are the only ones that should be set. After a DFA match, the
+ amount of ovector that is used depends on the number of matches that
+ were found.
+
+ Testing pattern callouts
+
+ A callout function is supplied when pcre2test calls the library match-
+ ing functions, unless callout_none is specified. Its behaviour can be
+ controlled by various modifiers listed above whose names begin with
+ callout_. Details are given in the section entitled "Callouts" below.
+ Testing callouts from pcre2_substitute() is described separately in
+ "Testing the substitution function" below.
+
+ Finding all matches in a string
+
+ Searching for all possible matches within a subject can be requested by
+ the global or altglobal modifier. After finding a match, the matching
+ function is called again to search the remainder of the subject. The
+ difference between global and altglobal is that the former uses the
+ start_offset argument to pcre2_match() or pcre2_dfa_match() to start
+ searching at a new point within the entire string (which is what Perl
+ does), whereas the latter passes over a shortened subject. This makes a
+ difference to the matching process if the pattern begins with a lookbe-
+ hind assertion (including \b or \B).
+
+ If an empty string is matched, the next match is done with the
+ PCRE2_NOTEMPTY_ATSTART flag set, in order to search for another, non-
+ empty, match at the same point in the subject. This imitates the way
+ Perl handles such cases when using the /g modifier or the split() func-
+ tion.
+
+ Testing substring extraction functions
+
+ The copy and get modifiers can be used to test the pcre2_sub-
+ string_copy_xxx() and pcre2_substring_get_xxx() functions. They can be
+ given more than once, and each can specify a capture group name or num-
+ ber, for example:
+
+ abcd\=copy=1,copy=3,get=G1
+
+ If the #subject command is used to set default copy and/or get lists,
+ these can be unset by specifying a negative number to cancel all num-
+ bered groups and an empty name to cancel all named groups.
+
+ The getall modifier tests pcre2_substring_list_get(), which extracts
+ all captured substrings.
+
+ If the subject line is successfully matched, the substrings extracted
+ by the convenience functions are output with C, G, or L after the
+ string number instead of a colon. This is in addition to the normal
+ full list. The string length (that is, the return from the extraction
+ function) is given in parentheses after each substring, followed by the
+ name when the extraction was by name.
+
+ Testing the substitution function
+
+ If the replace modifier is set, the pcre2_substitute() function is
+ called instead of one of the matching functions (or after one call of
+ pcre2_match() in the case of PCRE2_SUBSTITUTE_MATCHED). Note that re-
+ placement strings cannot contain commas, because a comma signifies the
+ end of a modifier. This is not thought to be an issue in a test pro-
+ gram.
+
+ Specifying a completely empty replacement string disables this modi-
+ fier. However, it is possible to specify an empty replacement by pro-
+ viding a buffer length, as described below, for an otherwise empty re-
+ placement.
+
+ Unlike subject strings, pcre2test does not process replacement strings
+ for escape sequences. In UTF mode, a replacement string is checked to
+ see if it is a valid UTF-8 string. If so, it is correctly converted to
+ a UTF string of the appropriate code unit width. If it is not a valid
+ UTF-8 string, the individual code units are copied directly. This pro-
+ vides a means of passing an invalid UTF-8 string for testing purposes.
+
+ The following modifiers set options (in additional to the normal match
+ options) for pcre2_substitute():
+
+ global PCRE2_SUBSTITUTE_GLOBAL
+ substitute_extended PCRE2_SUBSTITUTE_EXTENDED
+ substitute_literal PCRE2_SUBSTITUTE_LITERAL
+ substitute_matched PCRE2_SUBSTITUTE_MATCHED
+ substitute_overflow_length PCRE2_SUBSTITUTE_OVERFLOW_LENGTH
+ substitute_replacement_only PCRE2_SUBSTITUTE_REPLACEMENT_ONLY
+ substitute_unknown_unset PCRE2_SUBSTITUTE_UNKNOWN_UNSET
+ substitute_unset_empty PCRE2_SUBSTITUTE_UNSET_EMPTY
+
+ See the pcre2api documentation for details of these options.
+
+ After a successful substitution, the modified string is output, pre-
+ ceded by the number of replacements. This may be zero if there were no
+ matches. Here is a simple example of a substitution test:
+
+ /abc/replace=xxx
+ =abc=abc=
+ 1: =xxx=abc=
+ =abc=abc=\=global
+ 2: =xxx=xxx=
+
+ Subject and replacement strings should be kept relatively short (fewer
+ than 256 characters) for substitution tests, as fixed-size buffers are
+ used. To make it easy to test for buffer overflow, if the replacement
+ string starts with a number in square brackets, that number is passed
+ to pcre2_substitute() as the size of the output buffer, with the re-
+ placement string starting at the next character. Here is an example
+ that tests the edge case:
+
+ /abc/
+ 123abc123\=replace=[10]XYZ
+ 1: 123XYZ123
+ 123abc123\=replace=[9]XYZ
+ Failed: error -48: no more memory
+
+ The default action of pcre2_substitute() is to return PCRE2_ER-
+ ROR_NOMEMORY when the output buffer is too small. However, if the
+ PCRE2_SUBSTITUTE_OVERFLOW_LENGTH option is set (by using the substi-
+ tute_overflow_length modifier), pcre2_substitute() continues to go
+ through the motions of matching and substituting (but not doing any
+ callouts), in order to compute the size of buffer that is required.
+ When this happens, pcre2test shows the required buffer length (which
+ includes space for the trailing zero) as part of the error message. For
+ example:
+
+ /abc/substitute_overflow_length
+ 123abc123\=replace=[9]XYZ
+ Failed: error -48: no more memory: 10 code units are needed
+
+ A replacement string is ignored with POSIX and DFA matching. Specifying
+ partial matching provokes an error return ("bad option value") from
+ pcre2_substitute().
+
+ The substitute_subject modifier may be used to test the use of the
+ PCRE2 API, in which a client calls pcre2_match() followed by pcre2_sub-
+ stitute() with PCRE2_SUBSTITUTE_MATCHED, but the client performs an un-
+ expected and unsupported modification of the subject buffer in-place,
+ in between the match and substitution.
+
+ Testing substitute callouts
+
+ If the substitute_callout modifier is set, a substitution callout func-
+ tion is set up. The null_context modifier must not be set, because the
+ address of the callout function is passed in a match context. When the
+ callout function is called (after each substitution), details of the
+ input and output strings are output. For example:
+
+ /abc/g,replace=<$0>,substitute_callout
+ abcdefabcpqr
+ 1(1) Old 0 3 "abc" New 0 5 ""
+ 2(1) Old 6 9 "abc" New 8 13 ""
+ 2: defpqr
+
+ The first number on each callout line is the count of matches. The
+ parenthesized number is the number of pairs that are set in the ovector
+ (that is, one more than the number of capturing groups that were set).
+ Then are listed the offsets of the old substring, its contents, and the
+ same for the replacement.
+
+ By default, the substitution callout function returns zero, which ac-
+ cepts the replacement and causes matching to continue if /g was used.
+ Two further modifiers can be used to test other return values. If sub-
+ stitute_skip is set to a value greater than zero the callout function
+ returns +1 for the match of that number, and similarly substitute_stop
+ returns -1. These cause the replacement to be rejected, and -1 causes
+ no further matching to take place. If either of them are set, substi-
+ tute_callout is assumed. For example:
+
+ /abc/g,replace=<$0>,substitute_skip=1
+ abcdefabcpqr
+ 1(1) Old 0 3 "abc" New 0 5 " SKIPPED"
+ 2(1) Old 6 9 "abc" New 6 11 ""
+ 2: abcdefpqr
+ abcdefabcpqr\=substitute_stop=1
+ 1(1) Old 0 3 "abc" New 0 5 " STOPPED"
+ 1: abcdefabcpqr
+
+ If both are set for the same number, stop takes precedence. Only a sin-
+ gle skip or stop is supported, which is sufficient for testing that the
+ feature works.
+
+ Testing substitute case callouts
+
+ If the substitute_case_callout modifier is set, a substitution case
+ callout function is set up. The callout function is called for each
+ substituted chunk which is to be case-transformed.
+
+ The callout function passed is a fixed function with implementation for
+ certain behaviours: inputs which shrink when case-transformed; inputs
+ which grow; inputs with distinct upper/lower/titlecase forms. The char-
+ acters which are not special-cased for testing purposes are left unmod-
+ ified, as if they are caseless characters.
+
+ Setting the JIT stack size
+
+ The jitstack modifier provides a way of setting the maximum stack size
+ that is used by the just-in-time optimization code. It is ignored if
+ JIT optimization is not being used. The value is a number of kibibytes
+ (units of 1024 bytes). Setting zero reverts to the default of 32KiB.
+ Providing a stack that is larger than the default is necessary only for
+ very complicated patterns. If jitstack is set non-zero on a subject
+ line it overrides any value that was set on the pattern.
+
+ Setting heap, match, and depth limits
+
+ The heap_limit, match_limit, and depth_limit modifiers set the appro-
+ priate limits in the match context. These values are ignored when the
+ find_limits or find_limits_noheap modifier is specified.
+
+ Finding minimum limits
+
+ If the find_limits modifier is present on a subject line, pcre2test
+ calls the relevant matching function several times, setting different
+ values in the match context via pcre2_set_heap_limit(),
+ pcre2_set_match_limit(), or pcre2_set_depth_limit() until it finds the
+ smallest value for each parameter that allows the match to complete
+ without a "limit exceeded" error. The match itself may succeed or fail.
+ An alternative modifier, find_limits_noheap, omits the heap limit. This
+ is used in the standard tests, because the minimum heap limit varies
+ between systems. If JIT is being used, only the match limit is rele-
+ vant, and the other two are automatically omitted.
+
+ When using this modifier, the pattern should not contain any limit set-
+ tings such as (*LIMIT_MATCH=...) within it. If such a setting is
+ present and is lower than the minimum matching value, the minimum value
+ cannot be found because pcre2_set_match_limit() etc. are only able to
+ reduce the value of an in-pattern limit; they cannot increase it.
+
+ For non-DFA matching, the minimum depth_limit number is a measure of
+ how much nested backtracking happens (that is, how deeply the pattern's
+ tree is searched). In the case of DFA matching, depth_limit controls
+ the depth of recursive calls of the internal function that is used for
+ handling pattern recursion, lookaround assertions, and atomic groups.
+
+ For non-DFA matching, the match_limit number is a measure of the amount
+ of backtracking that takes place, and learning the minimum value can be
+ instructive. For most simple matches, the number is quite small, but
+ for patterns with very large numbers of matching possibilities, it can
+ become large very quickly with increasing length of subject string. In
+ the case of DFA matching, match_limit controls the total number of
+ calls, both recursive and non-recursive, to the internal matching func-
+ tion, thus controlling the overall amount of computing resource that is
+ used.
+
+ For both kinds of matching, the heap_limit number, which is in
+ kibibytes (units of 1024 bytes), limits the amount of heap memory used
+ for matching.
+
+ Showing MARK names
+
+
+ The mark modifier causes the names from backtracking control verbs that
+ are returned from calls to pcre2_match() to be displayed. If a mark is
+ returned for a match, non-match, or partial match, pcre2test shows it.
+ For a match, it is on a line by itself, tagged with "MK:". Otherwise,
+ it is added to the non-match message.
+
+ Showing memory usage
+
+ The memory modifier causes pcre2test to log the sizes of all heap mem-
+ ory allocation and freeing calls that occur during a call to
+ pcre2_match() or pcre2_dfa_match(). In the latter case, heap memory is
+ used only when a match requires more internal workspace that the de-
+ fault allocation on the stack, so in many cases there will be no out-
+ put. No heap memory is allocated during matching with JIT. For this
+ modifier to work, the null_context modifier must not be set on both the
+ pattern and the subject, though it can be set on one or the other.
+
+ Showing the heap frame overall vector size
+
+ The heapframes_size modifier is relevant for matches using
+ pcre2_match() without JIT. After a match has run (whether successful or
+ not) the size, in bytes, of the allocated heap frames vector that is
+ left attached to the match data block is shown. If the matching action
+ involved several calls to pcre2_match() (for example, global matching
+ or for timing) only the final value is shown.
+
+ This modifier is ignored, with a warning, for POSIX or DFA matching.
+ JIT matching does not use the heap frames vector, so the size is always
+ zero, unless there was a previous non-JIT match. Note that specifing a
+ size of zero for the output vector (see below) causes pcre2test to free
+ its match data block (and associated heap frames vector) and allocate a
+ new one.
+
+ Setting a starting offset
+
+ The offset modifier sets an offset in the subject string at which
+ matching starts. Its value is a number of code units, not characters.
+
+ Setting an offset limit
+
+ The offset_limit modifier sets a limit for unanchored matches. If a
+ match cannot be found starting at or before this offset in the subject,
+ a "no match" return is given. The data value is a number of code units,
+ not characters. When this modifier is used, the use_offset_limit modi-
+ fier must have been set for the pattern; if not, an error is generated.
+
+ Setting the size of the output vector
+
+ The ovector modifier applies only to the subject line in which it ap-
+ pears, though of course it can also be used to set a default in a #sub-
+ ject command. It specifies the number of pairs of offsets that are
+ available for storing matching information. The default is 15.
+
+ A value of zero is useful when testing the POSIX API because it causes
+ regexec() to be called with a NULL capture vector. When not testing the
+ POSIX API, a value of zero is used to cause pcre2_match_data_cre-
+ ate_from_pattern() to be called, in order to create a new match block
+ of exactly the right size for the pattern. (It is not possible to cre-
+ ate a match block with a zero-length ovector; there is always at least
+ one pair of offsets.) The old match data block is freed.
+
+ Passing the subject as zero-terminated
+
+ By default, the subject string is passed to a native API matching func-
+ tion with its correct length. In order to test the facility for passing
+ a zero-terminated string, the zero_terminate modifier is provided. It
+ causes the length to be passed as PCRE2_ZERO_TERMINATED. When matching
+ via the POSIX interface, this modifier is ignored, with a warning.
+
+ When testing pcre2_substitute(), this modifier also has the effect of
+ passing the replacement string as zero-terminated.
+
+ Passing a NULL context, subject, or replacement
+
+ Normally, pcre2test passes a context block to pcre2_match(),
+ pcre2_dfa_match(), pcre2_jit_match() or pcre2_substitute(). If the
+ null_context modifier is set, however, NULL is passed. This is for
+ testing that the matching and substitution functions behave correctly
+ in this case (they use default values). This modifier cannot be used
+ with the find_limits, find_limits_noheap, or substitute_callout modi-
+ fiers.
+
+ Similarly, for testing purposes, if the null_subject or null_replace-
+ ment modifier is set, the subject or replacement string pointers are
+ passed as NULL, respectively, to the relevant functions.
+
+
+THE ALTERNATIVE MATCHING FUNCTION
+
+ By default, pcre2test uses the standard PCRE2 matching function,
+ pcre2_match() to match each subject line. PCRE2 also supports an alter-
+ native matching function, pcre2_dfa_match(), which operates in a dif-
+ ferent way, and has some restrictions. The differences between the two
+ functions are described in the pcre2matching documentation.
+
+ If the dfa modifier is set, the alternative matching function is used.
+ This function finds all possible matches at a given point in the sub-
+ ject. If, however, the dfa_shortest modifier is set, processing stops
+ after the first match is found. This is always the shortest possible
+ match.
+
+
+DEFAULT OUTPUT FROM pcre2test
+
+ This section describes the output when the normal matching function,
+ pcre2_match(), is being used.
+
+ When a match succeeds, pcre2test outputs the list of captured sub-
+ strings, starting with number 0 for the string that matched the whole
+ pattern. Otherwise, it outputs "No match" when the return is PCRE2_ER-
+ ROR_NOMATCH, or "Partial match:" followed by the partially matching
+ substring when the return is PCRE2_ERROR_PARTIAL. (Note that this is
+ the entire substring that was inspected during the partial match; it
+ may include characters before the actual match start if a lookbehind
+ assertion, \K, \b, or \B was involved.)
+
+ For any other return, pcre2test outputs the PCRE2 negative error number
+ and a short descriptive phrase. If the error is a failed UTF string
+ check, the code unit offset of the start of the failing character is
+ also output. Here is an example of an interactive pcre2test run.
+
+ $ pcre2test
+ PCRE2 version 10.22 2016-07-29
+
+ re> /^abc(\d+)/
+ data> abc123
+ 0: abc123
+ 1: 123
+ data> xyz
+ No match
+
+ Unset capturing substrings that are not followed by one that is set are
+ not shown by pcre2test unless the allcaptures modifier is specified. In
+ the following example, there are two capturing substrings, but when the
+ first data line is matched, the second, unset substring is not shown.
+ An "internal" unset substring is shown as "", as for the second
+ data line.
+
+ re> /(a)|(b)/
+ data> a
+ 0: a
+ 1: a
+ data> b
+ 0: b
+ 1:
+ 2: b
+
+ If the strings contain any non-printing characters, they are output as
+ \xhh escapes if the value is less than 256 and UTF mode is not set.
+ Otherwise they are output as \x{hh...} escapes. See below for the defi-
+ nition of non-printing characters. If the aftertext modifier is set,
+ the output for substring 0 is followed by the rest of the subject
+ string, identified by "0+" like this:
+
+ re> /cat/aftertext
+ data> cataract
+ 0: cat
+ 0+ aract
+
+ If global matching is requested, the results of successive matching at-
+ tempts are output in sequence, like this:
+
+ re> /\Bi(\w\w)/g
+ data> Mississippi
+ 0: iss
+ 1: ss
+ 0: iss
+ 1: ss
+ 0: ipp
+ 1: pp
+
+ "No match" is output only if the first match attempt fails. Here is an
+ example of a failure message (the offset 4 that is specified by the
+ offset modifier is past the end of the subject string):
+
+ re> /xyz/
+ data> xyz\=offset=4
+ Error -24 (bad offset value)
+
+ Note that whereas patterns can be continued over several lines (a plain
+ ">" prompt is used for continuations), subject lines may not. However
+ newlines can be included in a subject by means of the \n escape (or \r,
+ \r\n, etc., depending on the newline sequence setting).
+
+
+OUTPUT FROM THE ALTERNATIVE MATCHING FUNCTION
+
+ When the alternative matching function, pcre2_dfa_match(), is used, the
+ output consists of a list of all the matches that start at the first
+ point in the subject where there is at least one match. For example:
+
+ re> /(tang|tangerine|tan)/
+ data> yellow tangerine\=dfa
+ 0: tangerine
+ 1: tang
+ 2: tan
+
+ Using the normal matching function on this data finds only "tang". The
+ longest matching string is always given first (and numbered zero). Af-
+ ter a PCRE2_ERROR_PARTIAL return, the output is "Partial match:", fol-
+ lowed by the partially matching substring. Note that this is the entire
+ substring that was inspected during the partial match; it may include
+ characters before the actual match start if a lookbehind assertion, \b,
+ or \B was involved. (\K is not supported for DFA matching.)
+
+ If global matching is requested, the search for further matches resumes
+ at the end of the longest match. For example:
+
+ re> /(tang|tangerine|tan)/g
+ data> yellow tangerine and tangy sultana\=dfa
+ 0: tangerine
+ 1: tang
+ 2: tan
+ 0: tang
+ 1: tan
+ 0: tan
+
+ The alternative matching function does not support substring capture,
+ so the modifiers that are concerned with captured substrings are not
+ relevant.
+
+
+RESTARTING AFTER A PARTIAL MATCH
+
+ When the alternative matching function has given the PCRE2_ERROR_PAR-
+ TIAL return, indicating that the subject partially matched the pattern,
+ you can restart the match with additional subject data by means of the
+ dfa_restart modifier. For example:
+
+ re> /^\d?\d(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\d\d$/
+ data> 23ja\=ps,dfa
+ Partial match: 23ja
+ data> n05\=dfa,dfa_restart
+ 0: n05
+
+ For further information about partial matching, see the pcre2partial
+ documentation.
+
+
+CALLOUTS
+
+ If the pattern contains any callout requests, pcre2test's callout func-
+ tion is called during matching unless callout_none is specified. This
+ works with both matching functions, and with JIT, though there are some
+ differences in behaviour. The output for callouts with numerical argu-
+ ments and those with string arguments is slightly different.
+
+ Callouts with numerical arguments
+
+ By default, the callout function displays the callout number, the start
+ and current positions in the subject text at the callout time, and the
+ next pattern item to be tested. For example:
+
+ --->pqrabcdef
+ 0 ^ ^ \d
+
+ This output indicates that callout number 0 occurred for a match at-
+ tempt starting at the fourth character of the subject string, when the
+ pointer was at the seventh character, and when the next pattern item
+ was \d. Just one circumflex is output if the start and current posi-
+ tions are the same, or if the current position precedes the start posi-
+ tion, which can happen if the callout is in a lookbehind assertion.
+
+ Callouts numbered 255 are assumed to be automatic callouts, inserted as
+ a result of the auto_callout pattern modifier. In this case, instead of
+ showing the callout number, the offset in the pattern, preceded by a
+ plus, is output. For example:
+
+ re> /\d?[A-E]\*/auto_callout
+ data> E*
+ --->E*
+ +0 ^ \d?
+ +3 ^ [A-E]
+ +8 ^^ \*
+ +10 ^ ^
+ 0: E*
+
+ If a pattern contains (*MARK) items, an additional line is output when-
+ ever a change of latest mark is passed to the callout function. For ex-
+ ample:
+
+ re> /a(*MARK:X)bc/auto_callout
+ data> abc
+ --->abc
+ +0 ^ a
+ +1 ^^ (*MARK:X)
+ +10 ^^ b
+ Latest Mark: X
+ +11 ^ ^ c
+ +12 ^ ^
+ 0: abc
+
+ The mark changes between matching "a" and "b", but stays the same for
+ the rest of the match, so nothing more is output. If, as a result of
+ backtracking, the mark reverts to being unset, the text "" is
+ output.
+
+ Callouts with string arguments
+
+ The output for a callout with a string argument is similar, except that
+ instead of outputting a callout number before the position indicators,
+ the callout string and its offset in the pattern string are output be-
+ fore the reflection of the subject string, and the subject string is
+ reflected for each callout. For example:
+
+ re> /^ab(?C'first')cd(?C"second")ef/
+ data> abcdefg
+ Callout (7): 'first'
+ --->abcdefg
+ ^ ^ c
+ Callout (20): "second"
+ --->abcdefg
+ ^ ^ e
+ 0: abcdef
+
+
+ Callout modifiers
+
+ The callout function in pcre2test returns zero (carry on matching) by
+ default, but you can use a callout_fail modifier in a subject line to
+ change this and other parameters of the callout (see below).
+
+ If the callout_capture modifier is set, the current captured groups are
+ output when a callout occurs. This is useful only for non-DFA matching,
+ as pcre2_dfa_match() does not support capturing, so no captures are
+ ever shown.
+
+ The normal callout output, showing the callout number or pattern offset
+ (as described above) is suppressed if the callout_no_where modifier is
+ set.
+
+ When using the interpretive matching function pcre2_match() without
+ JIT, setting the callout_extra modifier causes additional output from
+ pcre2test's callout function to be generated. For the first callout in
+ a match attempt at a new starting position in the subject, "New match
+ attempt" is output. If there has been a backtrack since the last call-
+ out (or start of matching if this is the first callout), "Backtrack" is
+ output, followed by "No other matching paths" if the backtrack ended
+ the previous match attempt. For example:
+
+ re> /(a+)b/auto_callout,no_start_optimize,no_auto_possess
+ data> aac\=callout_extra
+ New match attempt
+ --->aac
+ +0 ^ (
+ +1 ^ a+
+ +3 ^ ^ )
+ +4 ^ ^ b
+ Backtrack
+ --->aac
+ +3 ^^ )
+ +4 ^^ b
+ Backtrack
+ No other matching paths
+ New match attempt
+ --->aac
+ +0 ^ (
+ +1 ^ a+
+ +3 ^^ )
+ +4 ^^ b
+ Backtrack
+ No other matching paths
+ New match attempt
+ --->aac
+ +0 ^ (
+ +1 ^ a+
+ Backtrack
+ No other matching paths
+ New match attempt
+ --->aac
+ +0 ^ (
+ +1 ^ a+
+ No match
+
+ Notice that various optimizations must be turned off if you want all
+ possible matching paths to be scanned. If no_start_optimize is not
+ used, there is an immediate "no match", without any callouts, because
+ the starting optimization fails to find "b" in the subject, which it
+ knows must be present for any match. If no_auto_possess is not used,
+ the "a+" item is turned into "a++", which reduces the number of back-
+ tracks.
+
+ The callout_extra modifier has no effect if used with the DFA matching
+ function, or with JIT.
+
+ Return values from callouts
+
+ The default return from the callout function is zero, which allows
+ matching to continue. The callout_fail modifier can be given one or two
+ numbers. If there is only one number, 1 is returned instead of 0 (caus-
+ ing matching to backtrack) when a callout of that number is reached. If
+ two numbers (:) are given, 1 is returned when callout is
+ reached and there have been at least callouts. The callout_error
+ modifier is similar, except that PCRE2_ERROR_CALLOUT is returned, caus-
+ ing the entire matching process to be aborted. If both these modifiers
+ are set for the same callout number, callout_error takes precedence.
+ Note that callouts with string arguments are always given the number
+ zero.
+
+ The callout_data modifier can be given an unsigned or a negative num-
+ ber. This is set as the "user data" that is passed to the matching
+ function, and passed back when the callout function is invoked. Any
+ value other than zero is used as a return from pcre2test's callout
+ function.
+
+ Inserting callouts can be helpful when using pcre2test to check compli-
+ cated regular expressions. For further information about callouts, see
+ the pcre2callout documentation.
+
+
+NON-PRINTING CHARACTERS
+
+ When pcre2test is outputting text in the compiled version of a pattern,
+ bytes other than 32-126 are always treated as non-printing characters
+ and are therefore shown as hex escapes.
+
+ When pcre2test is outputting text that is a matched part of a subject
+ string, it behaves in the same way, unless a different locale has been
+ set for the pattern (using the locale modifier). In this case, the is-
+ print() function is used to distinguish printing and non-printing char-
+ acters.
+
+
+SAVING AND RESTORING COMPILED PATTERNS
+
+ It is possible to save compiled patterns on disc or elsewhere, and re-
+ load them later, subject to a number of restrictions. JIT data cannot
+ be saved. The host on which the patterns are reloaded must be running
+ the same version of PCRE2, with the same code unit width, and must also
+ have the same endianness, pointer width and PCRE2_SIZE type. Before
+ compiled patterns can be saved they must be serialized, that is, con-
+ verted to a stream of bytes. A single byte stream may contain any num-
+ ber of compiled patterns, but they must all use the same character ta-
+ bles. A single copy of the tables is included in the byte stream (its
+ size is 1088 bytes).
+
+ The functions whose names begin with pcre2_serialize_ are used for se-
+ rializing and de-serializing. They are described in the pcre2serialize
+ documentation. In this section we describe the features of pcre2test
+ that can be used to test these functions.
+
+ Note that "serialization" in PCRE2 does not convert compiled patterns
+ to an abstract format like Java or .NET. It just makes a reloadable
+ byte code stream. Hence the restrictions on reloading mentioned above.
+
+ In pcre2test, when a pattern with push modifier is successfully com-
+ piled, it is pushed onto a stack of compiled patterns, and pcre2test
+ expects the next line to contain a new pattern (or command) instead of
+ a subject line. By contrast, the pushcopy modifier causes a copy of the
+ compiled pattern to be stacked, leaving the original available for im-
+ mediate matching. By using push and/or pushcopy, a number of patterns
+ can be compiled and retained. These modifiers are incompatible with
+ posix, and control modifiers that act at match time are ignored (with a
+ message) for the stacked patterns. The jitverify modifier applies only
+ at compile time.
+
+ The command
+
+ #save
+
+ causes all the stacked patterns to be serialized and the result written
+ to the named file. Afterwards, all the stacked patterns are freed. The
+ command
+
+ #load
+
+ reads the data in the file, and then arranges for it to be de-serial-
+ ized, with the resulting compiled patterns added to the pattern stack.
+ The pattern on the top of the stack can be retrieved by the #pop com-
+ mand, which must be followed by lines of subjects that are to be
+ matched with the pattern, terminated as usual by an empty line or end
+ of file. This command may be followed by a modifier list containing
+ only control modifiers that act after a pattern has been compiled. In
+ particular, hex, posix, posix_nosub, push, and pushcopy are not al-
+ lowed, nor are any option-setting modifiers. The JIT modifiers are,
+ however permitted. Here is an example that saves and reloads two pat-
+ terns.
+
+ /abc/push
+ /xyz/push
+ #save tempfile
+ #load tempfile
+ #pop info
+ xyz
+
+ #pop jit,bincode
+ abc
+
+ If jitverify is used with #pop, it does not automatically imply jit,
+ which is different behaviour from when it is used on a pattern.
+
+ The #popcopy command is analogous to the pushcopy modifier in that it
+ makes current a copy of the topmost stack pattern, leaving the original
+ still on the stack.
+
+
+SEE ALSO
+
+ pcre2(3), pcre2api(3), pcre2callout(3), pcre2jit, pcre2matching(3),
+ pcre2partial(d), pcre2pattern(3), pcre2serialize(3).
+
+
+AUTHOR
+
+ Philip Hazel
+ Retired from University Computing Service
+ Cambridge, England.
+
+
+REVISION
+
+ Last updated: 22 August 2026
+ Copyright (c) 1997-2024 University of Cambridge.
+
+
+PCRE2 10.48 22 August 2026 PCRE2TEST(1)
diff --git a/doc/pcre2unicode.3 b/doc/pcre2unicode.3
new file mode 100644
index 0000000..c6bb26e
--- /dev/null
+++ b/doc/pcre2unicode.3
@@ -0,0 +1,514 @@
+.TH PCRE2UNICODE 3 "27 November 2024" "PCRE2 10.48"
+.SH NAME
+PCRE2 - Perl-compatible regular expressions (revised API)
+.SH "UNICODE AND UTF SUPPORT"
+.rs
+.sp
+PCRE2 is normally built with Unicode support, though if you do not need it, you
+can build it without, in which case the library will be smaller. With Unicode
+support, PCRE2 has knowledge of Unicode character properties and can process
+strings of text in UTF-8, UTF-16, and UTF-32 format (depending on the code unit
+width), but this is not the default. Unless specifically requested, PCRE2
+treats each code unit in a string as one character.
+.P
+There are two ways of telling PCRE2 to switch to UTF mode, where characters may
+consist of more than one code unit and the range of values is constrained. The
+program can call
+.\" HREF
+\fBpcre2_compile()\fP
+.\"
+with the PCRE2_UTF option, or the pattern may start with the sequence (*UTF).
+However, the latter facility can be locked out by the PCRE2_NEVER_UTF option.
+That is, the programmer can prevent the supplier of the pattern from switching
+to UTF mode.
+.P
+Note that the PCRE2_MATCH_INVALID_UTF option (see
+.\" HTML
+.\"
+below)
+.\"
+forces PCRE2_UTF to be set.
+.P
+In UTF mode, both the pattern and any subject strings that are matched against
+it are treated as UTF strings instead of strings of individual one-code-unit
+characters. There are also some other changes to the way characters are
+handled, as documented below.
+.
+.
+.SH "UNICODE PROPERTY SUPPORT"
+.rs
+.sp
+When PCRE2 is built with Unicode support, the escape sequences \ep{..},
+\eP{..}, and \eX can be used. This is not dependent on the PCRE2_UTF setting.
+The Unicode properties that can be tested are a subset of those that Perl
+supports. Currently they are limited to the general category properties such as
+Lu for an upper case letter or Nd for a decimal number, the derived properties
+Any and Lc (synonym L&), the Unicode script names such as Arabic or Han,
+Bidi_Class, Bidi_Control, and a few binary properties.
+.P
+The full lists are given in the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+and
+.\" HREF
+\fBpcre2syntax\fP
+.\"
+documentation. In general, only the short names for properties are supported.
+For example, \ep{L} matches a letter. Its longer synonym, \ep{Letter}, is not
+supported. Furthermore, in Perl, many properties may optionally be prefixed by
+"Is", for compatibility with Perl 5.6. PCRE2 does not support this.
+.
+.
+.SH "WIDE CHARACTERS AND UTF MODES"
+.rs
+.sp
+Code points less than 256 can be specified in patterns by either braced or
+unbraced hexadecimal escape sequences (for example, \ex{b3} or \exb3). Larger
+values have to use braced sequences. Unbraced octal code points up to \e777 are
+also recognized; larger ones can be coded using \eo{...}.
+.P
+The escape sequence \eN{U+} is recognized as another way of
+specifying a Unicode character by code point in a UTF mode. It is not allowed
+in non-UTF mode.
+.P
+In UTF mode, repeat quantifiers apply to complete UTF characters, not to
+individual code units.
+.P
+In UTF mode, the dot metacharacter matches one UTF character instead of a
+single code unit.
+.P
+In UTF mode, capture group names are not restricted to ASCII, and may contain
+any Unicode letters and decimal digits, as well as underscore.
+.P
+The escape sequence \eC can be used to match a single code unit in UTF mode,
+but its use can lead to some strange effects because it breaks up multi-unit
+characters (see the description of \eC in the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+documentation). For this reason, there is a build-time option that disables
+support for \eC completely. There is also a less draconian compile-time option
+for locking out the use of \eC when a pattern is compiled.
+.P
+The use of \eC is not supported by the alternative matching function
+\fBpcre2_dfa_match()\fP when in UTF-8 or UTF-16 mode, that is, when a character
+may consist of more than one code unit. The use of \eC in these modes provokes
+a match-time error. Also, the JIT optimization does not support \eC in these
+modes. If JIT optimization is requested for a UTF-8 or UTF-16 pattern that
+contains \eC, it will not succeed, and so when \fBpcre2_match()\fP is called,
+the matching will be carried out by the interpretive function.
+.P
+The character escapes \eb, \eB, \ed, \eD, \es, \eS, \ew, and \eW correctly test
+characters of any code value, but, by default, the characters that PCRE2
+recognizes as digits, spaces, or word characters remain the same set as in
+non-UTF mode, all with code points less than 256. This remains true even when
+PCRE2 is built to include Unicode support, because to do otherwise would slow
+down matching in many common cases. Note that this also applies to \eb
+and \eB, because they are defined in terms of \ew and \eW. If you want
+to test for a wider sense of, say, "digit", you can use explicit Unicode
+property tests such as \ep{Nd}. Alternatively, if you set the PCRE2_UCP option,
+the way that the character escapes work is changed so that Unicode properties
+are used to determine which characters match, though there are some options
+that suppress this for individual escapes. For details see the section on
+.\" HTML
+.\"
+generic character types
+.\"
+in the
+.\" HREF
+\fBpcre2pattern\fP
+.\"
+documentation.
+.P
+Like the escapes, characters that match the POSIX named character classes are
+all low-valued characters unless the PCRE2_UCP option is set, but there is an
+option to override this.
+.P
+In contrast to the character escapes and character classes, the special
+horizontal and vertical white space escapes (\eh, \eH, \ev, and \eV) do match
+all the appropriate Unicode characters, whether or not PCRE2_UCP is set.
+.
+.
+.SH "UNICODE CASE-EQUIVALENCE"
+.rs
+.sp
+If either PCRE2_UTF or PCRE2_UCP is set, upper/lower case processing makes use
+of Unicode properties except for characters whose code points are less than 128
+and that have at most two case-equivalent values. For these, a direct table
+lookup is used for speed. A few Unicode characters such as Greek sigma have
+more than two code points that are case-equivalent, and these are treated
+specially. Setting PCRE2_UCP without PCRE2_UTF allows Unicode-style case
+processing for non-UTF character encodings such as UCS-2.
+.P
+There are two ASCII characters (S and K) that, in addition to their ASCII lower
+case equivalents, have a non-ASCII one as well (long S and Kelvin sign).
+Recognition of these non-ASCII characters as case-equivalent to their ASCII
+counterparts can be disabled by setting the PCRE2_EXTRA_CASELESS_RESTRICT
+option. When this is set, all characters in a case equivalence must either be
+ASCII or non-ASCII; there can be no mixing.
+.sp
+ Without PCRE2_EXTRA_CASELESS_RESTRICT:
+ 'k' = 'K' = U+212A (Kelvin sign)
+ 's' = 'S' = U+017F (long S)
+ With PCRE2_EXTRA_CASELESS_RESTRICT:
+ 'k' = 'K'
+ U+212A (Kelvin sign) only case-equivalent to itself
+ 's' = 'S'
+ U+017F (long S) only case-equivalent to itself
+.P
+One language family, Turkish and Azeri, has its own case-insensitivity rules,
+which can be selected by setting PCRE2_EXTRA_TURKISH_CASING. This alters the
+behaviour of the 'i', 'I', U+0130 (capital I with dot above), and U+0131
+(small dotless i) characters.
+.sp
+ Without PCRE2_EXTRA_TURKISH_CASING:
+ 'i' = 'I'
+ U+0130 (capital I with dot above) only case-equivalent to itself
+ U+0131 (small dotless i) only case-equivalent to itself
+ With PCRE2_EXTRA_TURKISH_CASING:
+ 'i' = U+0130 (capital I with dot above)
+ U+0131 (small dotless i) = 'I'
+.P
+It is not allowed to specify both PCRE2_EXTRA_CASELESS_RESTRICT and
+PCRE2_EXTRA_TURKISH_CASING together.
+.P
+From release 10.45 the Unicode letter properties Lu (upper case), Ll (lower
+case), and Lt (title case) are all treated as Lc (cased letter) when caseless
+matching is set by the PCRE2_CASELESS option or (?i) within the pattern.
+.
+.
+.\" HTML
+.SH "SCRIPT RUNS"
+.rs
+.sp
+The pattern constructs (*script_run:...) and (*atomic_script_run:...), with
+synonyms (*sr:...) and (*asr:...), verify that the string matched within the
+parentheses is a script run. In concept, a script run is a sequence of
+characters that are all from the same Unicode script. However, because some
+scripts are commonly used together, and because some diacritical and other
+marks are used with multiple scripts, it is not that simple.
+.P
+Every Unicode character has a Script property, mostly with a value
+corresponding to the name of a script, such as Latin, Greek, or Cyrillic. There
+are also three special values:
+.P
+"Unknown" is used for code points that have not been assigned, and also for the
+surrogate code points. In the PCRE2 32-bit library, characters whose code
+points are greater than the Unicode maximum (U+10FFFF), which are accessible
+only in non-UTF mode, are assigned the Unknown script.
+.P
+"Common" is used for characters that are used with many scripts. These include
+punctuation, emoji, mathematical, musical, and currency symbols, and the ASCII
+digits 0 to 9.
+.P
+"Inherited" is used for characters such as diacritical marks that modify a
+previous character. These are considered to take on the script of the character
+that they modify.
+.P
+Some Inherited characters are used with many scripts, but many of them are only
+normally used with a small number of scripts. For example, U+102E0 (Coptic
+Epact thousands mark) is used only with Arabic and Coptic. In order to make it
+possible to check this, a Unicode property called Script Extension exists. Its
+value is a list of scripts that apply to the character. For the majority of
+characters, the list contains just one script, the same one as the Script
+property. However, for characters such as U+102E0 more than one Script is
+listed. There are also some Common characters that have a single, non-Common
+script in their Script Extension list.
+.P
+The next section describes the basic rules for deciding whether a given string
+of characters is a script run. Note, however, that there are some special cases
+involving the Chinese Han script, and an additional constraint for decimal
+digits. These are covered in subsequent sections.
+.
+.
+.SS "Basic script run rules"
+.rs
+.sp
+A string that is less than two characters long is a script run. This is the
+only case in which an Unknown character can be part of a script run. Longer
+strings are checked using only the Script Extensions property, not the basic
+Script property.
+.P
+If a character's Script Extension property is the single value "Inherited", it
+is always accepted as part of a script run. This is also true for the property
+"Common", subject to the checking of decimal digits described below. All the
+remaining characters in a script run must have at least one script in common in
+their Script Extension lists. In set-theoretic terminology, the intersection of
+all the sets of scripts must not be empty.
+.P
+A simple example is an Internet name such as "google.com". The letters are all
+in the Latin script, and the dot is Common, so this string is a script run.
+However, the Cyrillic letter "o" looks exactly the same as the Latin "o"; a
+string that looks the same, but with Cyrillic "o"s is not a script run.
+.P
+More interesting examples involve characters with more than one script in their
+Script Extension. Consider the following characters:
+.sp
+ U+060C Arabic comma
+ U+06D4 Arabic full stop
+.sp
+The first has the Script Extension list Arabic, Hanifi Rohingya, Syriac, and
+Thaana; the second has just Arabic and Hanifi Rohingya. Both of them could
+appear in script runs of either Arabic or Hanifi Rohingya. The first could also
+appear in Syriac or Thaana script runs, but the second could not.
+.
+.
+.SS "The Chinese Han script"
+.rs
+.sp
+The Chinese Han script is commonly used in conjunction with other scripts for
+writing certain languages. Japanese uses the Hiragana and Katakana scripts
+together with Han; Korean uses Hangul and Han; Taiwanese Mandarin uses Bopomofo
+and Han. These three combinations are treated as special cases when checking
+script runs and are, in effect, "virtual scripts". Thus, a script run may
+contain a mixture of Hiragana, Katakana, and Han, or a mixture of Hangul and
+Han, or a mixture of Bopomofo and Han, but not, for example, a mixture of
+Hangul and Bopomofo and Han. PCRE2 (like Perl) follows Unicode's Technical
+Standard 39 ("Unicode Security Mechanisms", http://unicode.org/reports/tr39/)
+in allowing such mixtures.
+.
+.
+.SS "Decimal digits"
+.rs
+.sp
+Unicode contains many sets of 10 decimal digits in different scripts, and some
+scripts (including the Common script) contain more than one set. Some of these
+decimal digits them are visually indistinguishable from the common ASCII
+digits. In addition to the script checking described above, if a script run
+contains any decimal digits, they must all come from the same set of 10
+adjacent characters.
+.
+.
+.SH "VALIDITY OF UTF STRINGS"
+.rs
+.sp
+When the PCRE2_UTF option is set, the strings passed as patterns and subjects
+are (by default) checked for validity on entry to the relevant functions. If an
+invalid UTF string is passed, a negative error code is returned. The code unit
+offset to the offending character can be extracted from the match data block by
+calling \fBpcre2_get_startchar()\fP, which is used for this purpose after a UTF
+error.
+.P
+In some situations, you may already know that your strings are valid, and
+therefore want to skip these checks in order to improve performance, for
+example in the case of a long subject string that is being scanned repeatedly.
+If you set the PCRE2_NO_UTF_CHECK option at compile time or at match time,
+PCRE2 assumes that the pattern or subject it is given (respectively) contains
+only valid UTF code unit sequences.
+.P
+If you pass an invalid UTF string when PCRE2_NO_UTF_CHECK is set, the result
+is undefined and your program may crash or loop indefinitely or give incorrect
+results. There is, however, one mode of matching that can handle invalid UTF
+subject strings. This is enabled by passing PCRE2_MATCH_INVALID_UTF to
+\fBpcre2_compile()\fP and is discussed below in the next section. The rest of
+this section covers the case when PCRE2_MATCH_INVALID_UTF is not set.
+.P
+Passing PCRE2_NO_UTF_CHECK to \fBpcre2_compile()\fP just disables the UTF check
+for the pattern; it does not also apply to subject strings. If you want to
+disable the check for a subject string you must pass this same option to
+\fBpcre2_match()\fP or \fBpcre2_dfa_match()\fP.
+.P
+UTF-16 and UTF-32 strings can indicate their endianness by special code knows
+as a byte-order mark (BOM). The PCRE2 functions do not handle this, expecting
+strings to be in host byte order.
+.P
+Unless PCRE2_NO_UTF_CHECK is set, a UTF string is checked before any other
+processing takes place. In the case of \fBpcre2_match()\fP and
+\fBpcre2_dfa_match()\fP calls with a non-zero starting offset, the check is
+applied only to that part of the subject that could be inspected during
+matching, and there is a check that the starting offset points to the first
+code unit of a character or to the end of the subject. If there are no
+lookbehind assertions in the pattern, the check starts at the starting offset.
+Otherwise, it starts at the length of the longest lookbehind before the
+starting offset, or at the start of the subject if there are not that many
+characters before the starting offset. Note that the sequences \eb and \eB are
+one-character lookbehinds.
+.P
+In addition to checking the format of the string, there is a check to ensure
+that all code points lie in the range U+0 to U+10FFFF, excluding the surrogate
+area. The so-called "non-character" code points are not excluded because
+Unicode corrigendum #9 makes it clear that they should not be.
+.P
+Characters in the "Surrogate Area" of Unicode are reserved for use by UTF-16,
+where they are used in pairs to encode code points with values greater than
+0xFFFF. The code points that are encoded by UTF-16 pairs are available
+independently in the UTF-8 and UTF-32 encodings. (In other words, the whole
+surrogate thing is a fudge for UTF-16 which unfortunately messes up UTF-8 and
+UTF-32.)
+.P
+Setting PCRE2_NO_UTF_CHECK at compile time does not disable the error that is
+given if an escape sequence for an invalid Unicode code point is encountered in
+the pattern. If you want to allow escape sequences such as \ex{d800} (a
+surrogate code point) you can set the PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES extra
+option. However, this is possible only in UTF-8 and UTF-32 modes, because these
+values are not representable in UTF-16.
+.
+.
+.\" HTML
+.SS "Errors in UTF-8 strings"
+.rs
+.sp
+The following negative error codes are given for invalid UTF-8 strings:
+.sp
+ PCRE2_ERROR_UTF8_ERR1
+ PCRE2_ERROR_UTF8_ERR2
+ PCRE2_ERROR_UTF8_ERR3
+ PCRE2_ERROR_UTF8_ERR4
+ PCRE2_ERROR_UTF8_ERR5
+.sp
+The string ends with a truncated UTF-8 character; the code specifies how many
+bytes are missing (1 to 5). Although RFC 3629 restricts UTF-8 characters to be
+no longer than 4 bytes, the encoding scheme (originally defined by RFC 2279)
+allows for up to 6 bytes, and this is checked first; hence the possibility of
+4 or 5 missing bytes.
+.sp
+ PCRE2_ERROR_UTF8_ERR6
+ PCRE2_ERROR_UTF8_ERR7
+ PCRE2_ERROR_UTF8_ERR8
+ PCRE2_ERROR_UTF8_ERR9
+ PCRE2_ERROR_UTF8_ERR10
+.sp
+The two most significant bits of the 2nd, 3rd, 4th, 5th, or 6th byte of the
+character do not have the binary value 0b10 (that is, either the most
+significant bit is 0, or the next bit is 1).
+.sp
+ PCRE2_ERROR_UTF8_ERR11
+ PCRE2_ERROR_UTF8_ERR12
+.sp
+A character that is valid by the RFC 2279 rules is either 5 or 6 bytes long;
+these code points are excluded by RFC 3629.
+.sp
+ PCRE2_ERROR_UTF8_ERR13
+.sp
+A 4-byte character has a value greater than 0x10ffff; these code points are
+excluded by RFC 3629.
+.sp
+ PCRE2_ERROR_UTF8_ERR14
+.sp
+A 3-byte character has a value in the range 0xd800 to 0xdfff; this range of
+code points are reserved by RFC 3629 for use with UTF-16, and so are excluded
+from UTF-8.
+.sp
+ PCRE2_ERROR_UTF8_ERR15
+ PCRE2_ERROR_UTF8_ERR16
+ PCRE2_ERROR_UTF8_ERR17
+ PCRE2_ERROR_UTF8_ERR18
+ PCRE2_ERROR_UTF8_ERR19
+.sp
+A 2-, 3-, 4-, 5-, or 6-byte character is "overlong", that is, it codes for a
+value that can be represented by fewer bytes, which is invalid. For example,
+the two bytes 0xc0, 0xae give the value 0x2e, whose correct coding uses just
+one byte.
+.sp
+ PCRE2_ERROR_UTF8_ERR20
+.sp
+The two most significant bits of the first byte of a character have the binary
+value 0b10 (that is, the most significant bit is 1 and the second is 0). Such a
+byte can only validly occur as the second or subsequent byte of a multi-byte
+character.
+.sp
+ PCRE2_ERROR_UTF8_ERR21
+.sp
+The first byte of a character has the value 0xfe or 0xff. These values can
+never occur in a valid UTF-8 string.
+.
+.
+.\" HTML
+.SS "Errors in UTF-16 strings"
+.rs
+.sp
+The following negative error codes are given for invalid UTF-16 strings:
+.sp
+ PCRE2_ERROR_UTF16_ERR1 Missing low surrogate at end of string
+ PCRE2_ERROR_UTF16_ERR2 Invalid low surrogate follows high surrogate
+ PCRE2_ERROR_UTF16_ERR3 Isolated low surrogate
+.sp
+.
+.
+.\" HTML
+.SS "Errors in UTF-32 strings"
+.rs
+.sp
+The following negative error codes are given for invalid UTF-32 strings:
+.sp
+ PCRE2_ERROR_UTF32_ERR1 Surrogate character (0xd800 to 0xdfff)
+ PCRE2_ERROR_UTF32_ERR2 Code point is greater than 0x10ffff
+.sp
+.
+.
+.\" HTML
+.SH "MATCHING IN INVALID UTF STRINGS"
+.rs
+.sp
+You can run pattern matches on subject strings that may contain invalid UTF
+sequences if you call \fBpcre2_compile()\fP with the PCRE2_MATCH_INVALID_UTF
+option. This is supported by \fBpcre2_match()\fP, including JIT matching, but
+not by \fBpcre2_dfa_match()\fP. When PCRE2_MATCH_INVALID_UTF is set, it forces
+PCRE2_UTF to be set as well. Note, however, that the pattern itself must be a
+valid UTF string.
+.P
+If you do not set PCRE2_MATCH_INVALID_UTF when calling \fBpcre2_compile\fP, and
+you are not certain that your subject strings are valid UTF sequences, you
+should not make use of the JIT "fast path" function \fBpcre2_jit_match()\fP
+because it bypasses sanity checks, including the one for UTF validity. An
+invalid string may cause undefined behaviour, including looping, crashing, or
+giving the wrong answer.
+.P
+Setting PCRE2_MATCH_INVALID_UTF does not affect what \fBpcre2_compile()\fP
+generates, but if \fBpcre2_jit_compile()\fP is subsequently called, it does
+generate different code. If JIT is not used, the option affects the behaviour
+of the interpretive code in \fBpcre2_match()\fP. When PCRE2_MATCH_INVALID_UTF
+is set at compile time, PCRE2_NO_UTF_CHECK is ignored at match time.
+.P
+In this mode, an invalid code unit sequence in the subject never matches any
+pattern item. It does not match dot, it does not match \ep{Any}, it does not
+even match negative items such as [^X]. A lookbehind assertion fails if it
+encounters an invalid sequence while moving the current point backwards. In
+other words, an invalid UTF code unit sequence acts as a barrier which no match
+can cross.
+.P
+You can also think of this as the subject being split up into fragments of
+valid UTF, delimited internally by invalid code unit sequences. The pattern is
+matched fragment by fragment. The result of a successful match, however, is
+given as code unit offsets in the entire subject string in the usual way. There
+are a few points to consider:
+.P
+The internal boundaries are not interpreted as the beginnings or ends of lines
+and so do not match circumflex or dollar characters in the pattern.
+.P
+If \fBpcre2_match()\fP is called with an offset that points to an invalid
+UTF-sequence, that sequence is skipped, and the match starts at the next valid
+UTF character, or the end of the subject.
+.P
+At internal fragment boundaries, \eb and \eB behave in the same way as at the
+beginning and end of the subject. For example, a sequence such as \ebWORD\eb
+would match an instance of WORD that is surrounded by invalid UTF code units.
+.P
+Using PCRE2_MATCH_INVALID_UTF, an application can run matches on arbitrary
+data, knowing that any matched strings that are returned are valid UTF. This
+can be useful when searching for UTF text in executable or other binary files.
+.P
+Note, however, that the 16-bit and 32-bit PCRE2 libraries process strings as
+sequences of uint16_t or uint32_t code points. They cannot find valid UTF
+sequences within an arbitrary string of bytes unless such sequences are
+suitably aligned.
+.
+.
+.SH AUTHOR
+.rs
+.sp
+.nf
+Philip Hazel
+Retired from University Computing Service
+Cambridge, England.
+.fi
+.
+.
+.SH REVISION
+.rs
+.sp
+.nf
+Last updated: 27 November 2024
+Copyright (c) 1997-2024 University of Cambridge.
+.fi
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..ec298b5
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,541 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2020-11-14.01; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# 'make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+tab=' '
+nl='
+'
+IFS=" $tab$nl"
+
+# Set DOITPROG to "echo" to test this script.
+
+doit=${DOITPROG-}
+doit_exec=${doit:-exec}
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+# Create dirs (including intermediate dirs) using mode 755.
+# This is like GNU 'install' as of coreutils 8.32 (2020).
+mkdir_umask=22
+
+backupsuffix=
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+is_target_a_directory=possibly
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -p pass -p to $cpprog.
+ -s $stripprog installed files.
+ -S SUFFIX attempt to back up existing files, with suffix SUFFIX.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+
+By default, rm is invoked with -f; when overridden with RMPROG,
+it's up to you to specify -f if you want it.
+
+If -S is not specified, no backups are attempted.
+
+Email bug reports to bug-automake@gnu.org.
+Automake home page: https://www.gnu.org/software/automake/
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -p) cpprog="$cpprog -p";;
+
+ -s) stripcmd=$stripprog;;
+
+ -S) backupsuffix="$2"
+ shift;;
+
+ -t)
+ is_target_a_directory=always
+ dst_arg=$2
+ # Protect names problematic for 'test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ shift;;
+
+ -T) is_target_a_directory=never;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+# We allow the use of options -d and -T together, by making -d
+# take the precedence; this is for compatibility with GNU install.
+
+if test -n "$dir_arg"; then
+ if test -n "$dst_arg"; then
+ echo "$0: target directory not allowed when installing a directory." >&2
+ exit 1
+ fi
+fi
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ # Protect names problematic for 'test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call 'install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ if test $# -gt 1 || test "$is_target_a_directory" = always; then
+ if test ! -d "$dst_arg"; then
+ echo "$0: $dst_arg: Is not a directory." >&2
+ exit 1
+ fi
+ fi
+fi
+
+if test -z "$dir_arg"; then
+ do_exit='(exit $ret); exit $ret'
+ trap "ret=129; $do_exit" 1
+ trap "ret=130; $do_exit" 2
+ trap "ret=141; $do_exit" 13
+ trap "ret=143; $do_exit" 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names problematic for 'test' and other utilities.
+ case $src in
+ -* | [=\(\)!]) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ # Don't chown directories that already exist.
+ if test $dstdir_status = 0; then
+ chowncmd=""
+ fi
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+ dst=$dst_arg
+
+ # If destination is a directory, append the input filename.
+ if test -d "$dst"; then
+ if test "$is_target_a_directory" = never; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dstbase=`basename "$src"`
+ case $dst in
+ */) dst=$dst$dstbase;;
+ *) dst=$dst/$dstbase;;
+ esac
+ dstdir_status=0
+ else
+ dstdir=`dirname "$dst"`
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ case $dstdir in
+ */) dstdirslash=$dstdir;;
+ *) dstdirslash=$dstdir/;;
+ esac
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ # The $RANDOM variable is not portable (e.g., dash). Use it
+ # here however when possible just to lower collision chance.
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+
+ trap '
+ ret=$?
+ rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
+ exit $ret
+ ' 0
+
+ # Because "mkdir -p" follows existing symlinks and we likely work
+ # directly in world-writeable /tmp, make sure that the '$tmpdir'
+ # directory is successfully created first before we actually test
+ # 'mkdir -p'.
+ if (umask $mkdir_umask &&
+ $mkdirprog $mkdir_mode "$tmpdir" &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ test_tmpdir="$tmpdir/a"
+ ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
+ fi
+ trap '' 0;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ [-=\(\)!]*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ oIFS=$IFS
+ IFS=/
+ set -f
+ set fnord $dstdir
+ shift
+ set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test X"$d" = X && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=${dstdirslash}_inst.$$_
+ rmtmp=${dstdirslash}_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask &&
+ { test -z "$stripcmd" || {
+ # Create $dsttmp read-write so that cp doesn't create it read-only,
+ # which would cause strip to fail.
+ if test -z "$doit"; then
+ : >"$dsttmp" # No need to fork-exec 'touch'.
+ else
+ $doit touch "$dsttmp"
+ fi
+ }
+ } &&
+ $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+ set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ set +f &&
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # If $backupsuffix is set, and the file being installed
+ # already exists, attempt a backup. Don't worry if it fails,
+ # e.g., if mv doesn't support -f.
+ if test -n "$backupsuffix" && test -f "$dst"; then
+ $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
+ fi
+
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/libpcre2-16.pc.in b/libpcre2-16.pc.in
new file mode 100644
index 0000000..fe47b58
--- /dev/null
+++ b/libpcre2-16.pc.in
@@ -0,0 +1,14 @@
+# Package Information for pkg-config
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libpcre2-16
+Description: PCRE2 - Perl compatible regular expressions C library (2nd API) with 16 bit character support
+Version: @PACKAGE_VERSION@
+License: BSD-3-Clause WITH PCRE2-exception
+Libs: -L${libdir} -lpcre2-16@LIB_POSTFIX@
+Libs.private: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
+Cflags: -I${includedir} @PCRE2_STATIC_CFLAG@
diff --git a/libpcre2-32.pc.in b/libpcre2-32.pc.in
new file mode 100644
index 0000000..f2e9192
--- /dev/null
+++ b/libpcre2-32.pc.in
@@ -0,0 +1,14 @@
+# Package Information for pkg-config
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libpcre2-32
+Description: PCRE2 - Perl compatible regular expressions C library (2nd API) with 32 bit character support
+Version: @PACKAGE_VERSION@
+License: BSD-3-Clause WITH PCRE2-exception
+Libs: -L${libdir} -lpcre2-32@LIB_POSTFIX@
+Libs.private: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
+Cflags: -I${includedir} @PCRE2_STATIC_CFLAG@
diff --git a/libpcre2-8.pc.in b/libpcre2-8.pc.in
new file mode 100644
index 0000000..8697a95
--- /dev/null
+++ b/libpcre2-8.pc.in
@@ -0,0 +1,14 @@
+# Package Information for pkg-config
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libpcre2-8
+Description: PCRE2 - Perl compatible regular expressions C library (2nd API) with 8 bit character support
+Version: @PACKAGE_VERSION@
+License: BSD-3-Clause WITH PCRE2-exception
+Libs: -L${libdir} -lpcre2-8@LIB_POSTFIX@
+Libs.private: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
+Cflags: -I${includedir} @PCRE2_STATIC_CFLAG@
diff --git a/libpcre2-posix.pc.in b/libpcre2-posix.pc.in
new file mode 100644
index 0000000..faac2c5
--- /dev/null
+++ b/libpcre2-posix.pc.in
@@ -0,0 +1,14 @@
+# Package Information for pkg-config
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libpcre2-posix
+Description: Posix compatible interface to libpcre2-8
+Version: @PACKAGE_VERSION@
+License: BSD-3-Clause WITH PCRE2-exception
+Libs: -L${libdir} -lpcre2-posix@LIB_POSTFIX@
+Cflags: -I${includedir} @PCRE2POSIX_CFLAG@
+Requires.private: libpcre2-8
diff --git a/ltmain.sh b/ltmain.sh
new file mode 100755
index 0000000..977e523
--- /dev/null
+++ b/ltmain.sh
@@ -0,0 +1,11436 @@
+#! /usr/bin/env sh
+## DO NOT EDIT - This file generated from ./build-aux/ltmain.in
+## by inline-source v2019-02-19.15
+
+# libtool (GNU libtool) 2.4.7
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit , 1996
+
+# Copyright (C) 1996-2019, 2021-2022 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions. There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+
+PROGRAM=libtool
+PACKAGE=libtool
+VERSION="2.4.7 Debian-2.4.7-7build1"
+package_revision=2.4.7
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# Run './libtool --help' for help with using this script from the
+# command line.
+
+
+## ------------------------------- ##
+## User overridable command paths. ##
+## ------------------------------- ##
+
+# After configure completes, it has a better idea of some of the
+# shell tools we need than the defaults used by the functions shared
+# with bootstrap, so set those here where they can still be over-
+# ridden by the user, but otherwise take precedence.
+
+: ${AUTOCONF="autoconf"}
+: ${AUTOMAKE="automake"}
+
+
+## -------------------------- ##
+## Source external libraries. ##
+## -------------------------- ##
+
+# Much of our low-level functionality needs to be sourced from external
+# libraries, which are installed to $pkgauxdir.
+
+# Set a version string for this script.
+scriptversion=2019-02-19.15; # UTC
+
+# General shell script boiler plate, and helper functions.
+# Written by Gary V. Vaughan, 2004
+
+# This is free software. There is NO warranty; not even for
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Copyright (C) 2004-2019, 2021 Bootstrap Authors
+#
+# This file is dual licensed under the terms of the MIT license
+# , and GPL version 2 or later
+# . You must apply one of
+# these licenses when using or redistributing this software or any of
+# the files within it. See the URLs above, or the file `LICENSE`
+# included in the Bootstrap distribution for the full license texts.
+
+# Please report bugs or propose patches to:
+#
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# Evaluate this file near the top of your script to gain access to
+# the functions and variables defined here:
+#
+# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh
+#
+# If you need to override any of the default environment variable
+# settings, do that before evaluating this file.
+
+
+## -------------------- ##
+## Shell normalisation. ##
+## -------------------- ##
+
+# Some shells need a little help to be as Bourne compatible as possible.
+# Before doing anything else, make sure all that help has been provided!
+
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac
+fi
+
+# NLS nuisances: We save the old values in case they are required later.
+_G_user_locale=
+_G_safe_locale=
+for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+ eval "if test set = \"\${$_G_var+set}\"; then
+ save_$_G_var=\$$_G_var
+ $_G_var=C
+ export $_G_var
+ _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\"
+ _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\"
+ fi"
+done
+# These NLS vars are set unconditionally (bootstrap issue #24). Unset those
+# in case the environment reset is needed later and the $save_* variant is not
+# defined (see the code above).
+LC_ALL=C
+LANGUAGE=C
+export LANGUAGE LC_ALL
+
+# Make sure IFS has a sensible default
+sp=' '
+nl='
+'
+IFS="$sp $nl"
+
+# There are apparently some retarded systems that use ';' as a PATH separator!
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# func_unset VAR
+# --------------
+# Portably unset VAR.
+# In some shells, an 'unset VAR' statement leaves a non-zero return
+# status if VAR is already unset, which might be problematic if the
+# statement is used at the end of a function (thus poisoning its return
+# value) or when 'set -e' is active (causing even a spurious abort of
+# the script in this case).
+func_unset ()
+{
+ { eval $1=; (eval unset $1) >/dev/null 2>&1 && eval unset $1 || : ; }
+}
+
+
+# Make sure CDPATH doesn't cause `cd` commands to output the target dir.
+func_unset CDPATH
+
+# Make sure ${,E,F}GREP behave sanely.
+func_unset GREP_OPTIONS
+
+
+## ------------------------- ##
+## Locate command utilities. ##
+## ------------------------- ##
+
+
+# func_executable_p FILE
+# ----------------------
+# Check that FILE is an executable regular file.
+func_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+}
+
+
+# func_path_progs PROGS_LIST CHECK_FUNC [PATH]
+# --------------------------------------------
+# Search for either a program that responds to --version with output
+# containing "GNU", or else returned by CHECK_FUNC otherwise, by
+# trying all the directories in PATH with each of the elements of
+# PROGS_LIST.
+#
+# CHECK_FUNC should accept the path to a candidate program, and
+# set $func_check_prog_result if it truncates its output less than
+# $_G_path_prog_max characters.
+func_path_progs ()
+{
+ _G_progs_list=$1
+ _G_check_func=$2
+ _G_PATH=${3-"$PATH"}
+
+ _G_path_prog_max=0
+ _G_path_prog_found=false
+ _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:}
+ for _G_dir in $_G_PATH; do
+ IFS=$_G_save_IFS
+ test -z "$_G_dir" && _G_dir=.
+ for _G_prog_name in $_G_progs_list; do
+ for _exeext in '' .EXE; do
+ _G_path_prog=$_G_dir/$_G_prog_name$_exeext
+ func_executable_p "$_G_path_prog" || continue
+ case `"$_G_path_prog" --version 2>&1` in
+ *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;;
+ *) $_G_check_func $_G_path_prog
+ func_path_progs_result=$func_check_prog_result
+ ;;
+ esac
+ $_G_path_prog_found && break 3
+ done
+ done
+ done
+ IFS=$_G_save_IFS
+ test -z "$func_path_progs_result" && {
+ echo "no acceptable sed could be found in \$PATH" >&2
+ exit 1
+ }
+}
+
+
+# We want to be able to use the functions in this file before configure
+# has figured out where the best binaries are kept, which means we have
+# to search for them ourselves - except when the results are already set
+# where we skip the searches.
+
+# Unless the user overrides by setting SED, search the path for either GNU
+# sed, or the sed that truncates its output the least.
+test -z "$SED" && {
+ _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+ for _G_i in 1 2 3 4 5 6 7; do
+ _G_sed_script=$_G_sed_script$nl$_G_sed_script
+ done
+ echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed
+ _G_sed_script=
+
+ func_check_prog_sed ()
+ {
+ _G_path_prog=$1
+
+ _G_count=0
+ printf 0123456789 >conftest.in
+ while :
+ do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo '' >> conftest.nl
+ "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break
+ diff conftest.out conftest.nl >/dev/null 2>&1 || break
+ _G_count=`expr $_G_count + 1`
+ if test "$_G_count" -gt "$_G_path_prog_max"; then
+ # Best one so far, save it but keep looking for a better one
+ func_check_prog_result=$_G_path_prog
+ _G_path_prog_max=$_G_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test 10 -lt "$_G_count" && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out
+ }
+
+ func_path_progs "sed gsed" func_check_prog_sed "$PATH:/usr/xpg4/bin"
+ rm -f conftest.sed
+ SED=$func_path_progs_result
+}
+
+
+# Unless the user overrides by setting GREP, search the path for either GNU
+# grep, or the grep that truncates its output the least.
+test -z "$GREP" && {
+ func_check_prog_grep ()
+ {
+ _G_path_prog=$1
+
+ _G_count=0
+ _G_path_prog_max=0
+ printf 0123456789 >conftest.in
+ while :
+ do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo 'GREP' >> conftest.nl
+ "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break
+ diff conftest.out conftest.nl >/dev/null 2>&1 || break
+ _G_count=`expr $_G_count + 1`
+ if test "$_G_count" -gt "$_G_path_prog_max"; then
+ # Best one so far, save it but keep looking for a better one
+ func_check_prog_result=$_G_path_prog
+ _G_path_prog_max=$_G_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test 10 -lt "$_G_count" && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out
+ }
+
+ func_path_progs "grep ggrep" func_check_prog_grep "$PATH:/usr/xpg4/bin"
+ GREP=$func_path_progs_result
+}
+
+
+## ------------------------------- ##
+## User overridable command paths. ##
+## ------------------------------- ##
+
+# All uppercase variable names are used for environment variables. These
+# variables can be overridden by the user before calling a script that
+# uses them if a suitable command of that name is not already available
+# in the command search PATH.
+
+: ${CP="cp -f"}
+: ${ECHO="printf %s\n"}
+: ${EGREP="$GREP -E"}
+: ${FGREP="$GREP -F"}
+: ${LN_S="ln -s"}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+
+
+## -------------------- ##
+## Useful sed snippets. ##
+## -------------------- ##
+
+sed_dirname='s|/[^/]*$||'
+sed_basename='s|^.*/||'
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s|\([`"$\\]\)|\\\1|g'
+
+# Same as above, but do not quote variable references.
+sed_double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution that turns a string into a regex matching for the
+# string literally.
+sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g'
+
+# Sed substitution that converts a w32 file name or path
+# that contains forward slashes, into one that contains
+# (escaped) backslashes. A very naive implementation.
+sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+
+# Re-'\' parameter expansions in output of sed_double_quote_subst that
+# were '\'-ed in input to the same. If an odd number of '\' preceded a
+# '$' in input to sed_double_quote_subst, that '$' was protected from
+# expansion. Since each input '\' is now two '\'s, look for any number
+# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'.
+_G_bs='\\'
+_G_bs2='\\\\'
+_G_bs4='\\\\\\\\'
+_G_dollar='\$'
+sed_double_backslash="\
+ s/$_G_bs4/&\\
+/g
+ s/^$_G_bs2$_G_dollar/$_G_bs&/
+ s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g
+ s/\n//g"
+
+# require_check_ifs_backslash
+# ---------------------------
+# Check if we can use backslash as IFS='\' separator, and set
+# $check_ifs_backshlash_broken to ':' or 'false'.
+require_check_ifs_backslash=func_require_check_ifs_backslash
+func_require_check_ifs_backslash ()
+{
+ _G_save_IFS=$IFS
+ IFS='\'
+ _G_check_ifs_backshlash='a\\b'
+ for _G_i in $_G_check_ifs_backshlash
+ do
+ case $_G_i in
+ a)
+ check_ifs_backshlash_broken=false
+ ;;
+ '')
+ break
+ ;;
+ *)
+ check_ifs_backshlash_broken=:
+ break
+ ;;
+ esac
+ done
+ IFS=$_G_save_IFS
+ require_check_ifs_backslash=:
+}
+
+
+## ----------------- ##
+## Global variables. ##
+## ----------------- ##
+
+# Except for the global variables explicitly listed below, the following
+# functions in the '^func_' namespace, and the '^require_' namespace
+# variables initialised in the 'Resource management' section, sourcing
+# this file will not pollute your global namespace with anything
+# else. There's no portable way to scope variables in Bourne shell
+# though, so actually running these functions will sometimes place
+# results into a variable named after the function, and often use
+# temporary variables in the '^_G_' namespace. If you are careful to
+# avoid using those namespaces casually in your sourcing script, things
+# should continue to work as you expect. And, of course, you can freely
+# overwrite any of the functions or variables defined here before
+# calling anything to customize them.
+
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing.
+EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake.
+
+# Allow overriding, eg assuming that you follow the convention of
+# putting '$debug_cmd' at the start of all your functions, you can get
+# bash to show function call trace with:
+#
+# debug_cmd='echo "${FUNCNAME[0]} $*" >&2' bash your-script-name
+debug_cmd=${debug_cmd-":"}
+exit_cmd=:
+
+# By convention, finish your script with:
+#
+# exit $exit_status
+#
+# so that you can set exit_status to non-zero if you want to indicate
+# something went wrong during execution without actually bailing out at
+# the point of failure.
+exit_status=$EXIT_SUCCESS
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath=$0
+
+# The name of this program.
+progname=`$ECHO "$progpath" |$SED "$sed_basename"`
+
+# Make sure we have an absolute progpath for reexecution:
+case $progpath in
+ [\\/]*|[A-Za-z]:\\*) ;;
+ *[\\/]*)
+ progdir=`$ECHO "$progpath" |$SED "$sed_dirname"`
+ progdir=`cd "$progdir" && pwd`
+ progpath=$progdir/$progname
+ ;;
+ *)
+ _G_IFS=$IFS
+ IFS=${PATH_SEPARATOR-:}
+ for progdir in $PATH; do
+ IFS=$_G_IFS
+ test -x "$progdir/$progname" && break
+ done
+ IFS=$_G_IFS
+ test -n "$progdir" || progdir=`pwd`
+ progpath=$progdir/$progname
+ ;;
+esac
+
+
+## ----------------- ##
+## Standard options. ##
+## ----------------- ##
+
+# The following options affect the operation of the functions defined
+# below, and should be set appropriately depending on run-time para-
+# meters passed on the command line.
+
+opt_dry_run=false
+opt_quiet=false
+opt_verbose=false
+
+# Categories 'all' and 'none' are always available. Append any others
+# you will pass as the first argument to func_warning from your own
+# code.
+warning_categories=
+
+# By default, display warnings according to 'opt_warning_types'. Set
+# 'warning_func' to ':' to elide all warnings, or func_fatal_error to
+# treat the next displayed warning as a fatal error.
+warning_func=func_warn_and_continue
+
+# Set to 'all' to display all warnings, 'none' to suppress all
+# warnings, or a space delimited list of some subset of
+# 'warning_categories' to display only the listed warnings.
+opt_warning_types=all
+
+
+## -------------------- ##
+## Resource management. ##
+## -------------------- ##
+
+# This section contains definitions for functions that each ensure a
+# particular resource (a file, or a non-empty configuration variable for
+# example) is available, and if appropriate to extract default values
+# from pertinent package files. Call them using their associated
+# 'require_*' variable to ensure that they are executed, at most, once.
+#
+# It's entirely deliberate that calling these functions can set
+# variables that don't obey the namespace limitations obeyed by the rest
+# of this file, in order that that they be as useful as possible to
+# callers.
+
+
+# require_term_colors
+# -------------------
+# Allow display of bold text on terminals that support it.
+require_term_colors=func_require_term_colors
+func_require_term_colors ()
+{
+ $debug_cmd
+
+ test -t 1 && {
+ # COLORTERM and USE_ANSI_COLORS environment variables take
+ # precedence, because most terminfo databases neglect to describe
+ # whether color sequences are supported.
+ test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"}
+
+ if test 1 = "$USE_ANSI_COLORS"; then
+ # Standard ANSI escape sequences
+ tc_reset='[0m'
+ tc_bold='[1m'; tc_standout='[7m'
+ tc_red='[31m'; tc_green='[32m'
+ tc_blue='[34m'; tc_cyan='[36m'
+ else
+ # Otherwise trust the terminfo database after all.
+ test -n "`tput sgr0 2>/dev/null`" && {
+ tc_reset=`tput sgr0`
+ test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold`
+ tc_standout=$tc_bold
+ test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso`
+ test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1`
+ test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2`
+ test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4`
+ test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5`
+ }
+ fi
+ }
+
+ require_term_colors=:
+}
+
+
+## ----------------- ##
+## Function library. ##
+## ----------------- ##
+
+# This section contains a variety of useful functions to call in your
+# scripts. Take note of the portable wrappers for features provided by
+# some modern shells, which will fall back to slower equivalents on
+# less featureful shells.
+
+
+# func_append VAR VALUE
+# ---------------------
+# Append VALUE onto the existing contents of VAR.
+
+ # _G_HAVE_PLUSEQ_OP
+ # Can be empty, in which case the shell is probed, "yes" if += is
+ # useable or anything else if it does not work.
+ if test -z "$_G_HAVE_PLUSEQ_OP" && \
+ __PLUSEQ_TEST="a" && \
+ __PLUSEQ_TEST+=" b" 2>/dev/null && \
+ test "a b" = "$__PLUSEQ_TEST"; then
+ _G_HAVE_PLUSEQ_OP=yes
+ fi
+
+if test yes = "$_G_HAVE_PLUSEQ_OP"
+then
+ # This is an XSI compatible shell, allowing a faster implementation...
+ eval 'func_append ()
+ {
+ $debug_cmd
+
+ eval "$1+=\$2"
+ }'
+else
+ # ...otherwise fall back to using expr, which is often a shell builtin.
+ func_append ()
+ {
+ $debug_cmd
+
+ eval "$1=\$$1\$2"
+ }
+fi
+
+
+# func_append_quoted VAR VALUE
+# ----------------------------
+# Quote VALUE and append to the end of shell variable VAR, separated
+# by a space.
+if test yes = "$_G_HAVE_PLUSEQ_OP"; then
+ eval 'func_append_quoted ()
+ {
+ $debug_cmd
+
+ func_quote_arg pretty "$2"
+ eval "$1+=\\ \$func_quote_arg_result"
+ }'
+else
+ func_append_quoted ()
+ {
+ $debug_cmd
+
+ func_quote_arg pretty "$2"
+ eval "$1=\$$1\\ \$func_quote_arg_result"
+ }
+fi
+
+
+# func_append_uniq VAR VALUE
+# --------------------------
+# Append unique VALUE onto the existing contents of VAR, assuming
+# entries are delimited by the first character of VALUE. For example:
+#
+# func_append_uniq options " --another-option option-argument"
+#
+# will only append to $options if " --another-option option-argument "
+# is not already present somewhere in $options already (note spaces at
+# each end implied by leading space in second argument).
+func_append_uniq ()
+{
+ $debug_cmd
+
+ eval _G_current_value='`$ECHO $'$1'`'
+ _G_delim=`expr "$2" : '\(.\)'`
+
+ case $_G_delim$_G_current_value$_G_delim in
+ *"$2$_G_delim"*) ;;
+ *) func_append "$@" ;;
+ esac
+}
+
+
+# func_arith TERM...
+# ------------------
+# Set func_arith_result to the result of evaluating TERMs.
+ test -z "$_G_HAVE_ARITH_OP" \
+ && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \
+ && _G_HAVE_ARITH_OP=yes
+
+if test yes = "$_G_HAVE_ARITH_OP"; then
+ eval 'func_arith ()
+ {
+ $debug_cmd
+
+ func_arith_result=$(( $* ))
+ }'
+else
+ func_arith ()
+ {
+ $debug_cmd
+
+ func_arith_result=`expr "$@"`
+ }
+fi
+
+
+# func_basename FILE
+# ------------------
+# Set func_basename_result to FILE with everything up to and including
+# the last / stripped.
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ # If this shell supports suffix pattern removal, then use it to avoid
+ # forking. Hide the definitions single quotes in case the shell chokes
+ # on unsupported syntax...
+ _b='func_basename_result=${1##*/}'
+ _d='case $1 in
+ */*) func_dirname_result=${1%/*}$2 ;;
+ * ) func_dirname_result=$3 ;;
+ esac'
+
+else
+ # ...otherwise fall back to using sed.
+ _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`'
+ _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"`
+ if test "X$func_dirname_result" = "X$1"; then
+ func_dirname_result=$3
+ else
+ func_append func_dirname_result "$2"
+ fi'
+fi
+
+eval 'func_basename ()
+{
+ $debug_cmd
+
+ '"$_b"'
+}'
+
+
+# func_dirname FILE APPEND NONDIR_REPLACEMENT
+# -------------------------------------------
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+eval 'func_dirname ()
+{
+ $debug_cmd
+
+ '"$_d"'
+}'
+
+
+# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT
+# --------------------------------------------------------
+# Perform func_basename and func_dirname in a single function
+# call:
+# dirname: Compute the dirname of FILE. If nonempty,
+# add APPEND to the result, otherwise set result
+# to NONDIR_REPLACEMENT.
+# value returned in "$func_dirname_result"
+# basename: Compute filename of FILE.
+# value retuned in "$func_basename_result"
+# For efficiency, we do not delegate to the functions above but instead
+# duplicate the functionality here.
+eval 'func_dirname_and_basename ()
+{
+ $debug_cmd
+
+ '"$_b"'
+ '"$_d"'
+}'
+
+
+# func_echo ARG...
+# ----------------
+# Echo program name prefixed message.
+func_echo ()
+{
+ $debug_cmd
+
+ _G_message=$*
+
+ func_echo_IFS=$IFS
+ IFS=$nl
+ for _G_line in $_G_message; do
+ IFS=$func_echo_IFS
+ $ECHO "$progname: $_G_line"
+ done
+ IFS=$func_echo_IFS
+}
+
+
+# func_echo_all ARG...
+# --------------------
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+ $ECHO "$*"
+}
+
+
+# func_echo_infix_1 INFIX ARG...
+# ------------------------------
+# Echo program name, followed by INFIX on the first line, with any
+# additional lines not showing INFIX.
+func_echo_infix_1 ()
+{
+ $debug_cmd
+
+ $require_term_colors
+
+ _G_infix=$1; shift
+ _G_indent=$_G_infix
+ _G_prefix="$progname: $_G_infix: "
+ _G_message=$*
+
+ # Strip color escape sequences before counting printable length
+ for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan"
+ do
+ test -n "$_G_tc" && {
+ _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"`
+ _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"`
+ }
+ done
+ _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes
+
+ func_echo_infix_1_IFS=$IFS
+ IFS=$nl
+ for _G_line in $_G_message; do
+ IFS=$func_echo_infix_1_IFS
+ $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2
+ _G_prefix=$_G_indent
+ done
+ IFS=$func_echo_infix_1_IFS
+}
+
+
+# func_error ARG...
+# -----------------
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+ $debug_cmd
+
+ $require_term_colors
+
+ func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2
+}
+
+
+# func_fatal_error ARG...
+# -----------------------
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+ $debug_cmd
+
+ func_error "$*"
+ exit $EXIT_FAILURE
+}
+
+
+# func_grep EXPRESSION FILENAME
+# -----------------------------
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+ $debug_cmd
+
+ $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_len STRING
+# ---------------
+# Set func_len_result to the length of STRING. STRING may not
+# start with a hyphen.
+ test -z "$_G_HAVE_XSI_OPS" \
+ && (eval 'x=a/b/c;
+ test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
+ && _G_HAVE_XSI_OPS=yes
+
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ eval 'func_len ()
+ {
+ $debug_cmd
+
+ func_len_result=${#1}
+ }'
+else
+ func_len ()
+ {
+ $debug_cmd
+
+ func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
+ }
+fi
+
+
+# func_mkdir_p DIRECTORY-PATH
+# ---------------------------
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+ $debug_cmd
+
+ _G_directory_path=$1
+ _G_dir_list=
+
+ if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then
+
+ # Protect directory names starting with '-'
+ case $_G_directory_path in
+ -*) _G_directory_path=./$_G_directory_path ;;
+ esac
+
+ # While some portion of DIR does not yet exist...
+ while test ! -d "$_G_directory_path"; do
+ # ...make a list in topmost first order. Use a colon delimited
+ # list incase some portion of path contains whitespace.
+ _G_dir_list=$_G_directory_path:$_G_dir_list
+
+ # If the last portion added has no slash in it, the list is done
+ case $_G_directory_path in */*) ;; *) break ;; esac
+
+ # ...otherwise throw away the child directory and loop
+ _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"`
+ done
+ _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'`
+
+ func_mkdir_p_IFS=$IFS; IFS=:
+ for _G_dir in $_G_dir_list; do
+ IFS=$func_mkdir_p_IFS
+ # mkdir can fail with a 'File exist' error if two processes
+ # try to create one of the directories concurrently. Don't
+ # stop in that case!
+ $MKDIR "$_G_dir" 2>/dev/null || :
+ done
+ IFS=$func_mkdir_p_IFS
+
+ # Bail out if we (or some other process) failed to create a directory.
+ test -d "$_G_directory_path" || \
+ func_fatal_error "Failed to create '$1'"
+ fi
+}
+
+
+# func_mktempdir [BASENAME]
+# -------------------------
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible. If
+# given, BASENAME is the basename for that directory.
+func_mktempdir ()
+{
+ $debug_cmd
+
+ _G_template=${TMPDIR-/tmp}/${1-$progname}
+
+ if test : = "$opt_dry_run"; then
+ # Return a directory name, but don't create it in dry-run mode
+ _G_tmpdir=$_G_template-$$
+ else
+
+ # If mktemp works, use that first and foremost
+ _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null`
+
+ if test ! -d "$_G_tmpdir"; then
+ # Failing that, at least try and use $RANDOM to avoid a race
+ _G_tmpdir=$_G_template-${RANDOM-0}$$
+
+ func_mktempdir_umask=`umask`
+ umask 0077
+ $MKDIR "$_G_tmpdir"
+ umask $func_mktempdir_umask
+ fi
+
+ # If we're not in dry-run mode, bomb out on failure
+ test -d "$_G_tmpdir" || \
+ func_fatal_error "cannot create temporary directory '$_G_tmpdir'"
+ fi
+
+ $ECHO "$_G_tmpdir"
+}
+
+
+# func_normal_abspath PATH
+# ------------------------
+# Remove doubled-up and trailing slashes, "." path components,
+# and cancel out any ".." path components in PATH after making
+# it an absolute path.
+func_normal_abspath ()
+{
+ $debug_cmd
+
+ # These SED scripts presuppose an absolute path with a trailing slash.
+ _G_pathcar='s|^/\([^/]*\).*$|\1|'
+ _G_pathcdr='s|^/[^/]*||'
+ _G_removedotparts=':dotsl
+ s|/\./|/|g
+ t dotsl
+ s|/\.$|/|'
+ _G_collapseslashes='s|/\{1,\}|/|g'
+ _G_finalslash='s|/*$|/|'
+
+ # Start from root dir and reassemble the path.
+ func_normal_abspath_result=
+ func_normal_abspath_tpath=$1
+ func_normal_abspath_altnamespace=
+ case $func_normal_abspath_tpath in
+ "")
+ # Empty path, that just means $cwd.
+ func_stripname '' '/' "`pwd`"
+ func_normal_abspath_result=$func_stripname_result
+ return
+ ;;
+ # The next three entries are used to spot a run of precisely
+ # two leading slashes without using negated character classes;
+ # we take advantage of case's first-match behaviour.
+ ///*)
+ # Unusual form of absolute path, do nothing.
+ ;;
+ //*)
+ # Not necessarily an ordinary path; POSIX reserves leading '//'
+ # and for example Cygwin uses it to access remote file shares
+ # over CIFS/SMB, so we conserve a leading double slash if found.
+ func_normal_abspath_altnamespace=/
+ ;;
+ /*)
+ # Absolute path, do nothing.
+ ;;
+ *)
+ # Relative path, prepend $cwd.
+ func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath
+ ;;
+ esac
+
+ # Cancel out all the simple stuff to save iterations. We also want
+ # the path to end with a slash for ease of parsing, so make sure
+ # there is one (and only one) here.
+ func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+ -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"`
+ while :; do
+ # Processed it all yet?
+ if test / = "$func_normal_abspath_tpath"; then
+ # If we ascended to the root using ".." the result may be empty now.
+ if test -z "$func_normal_abspath_result"; then
+ func_normal_abspath_result=/
+ fi
+ break
+ fi
+ func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \
+ -e "$_G_pathcar"`
+ func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+ -e "$_G_pathcdr"`
+ # Figure out what to do with it
+ case $func_normal_abspath_tcomponent in
+ "")
+ # Trailing empty path component, ignore it.
+ ;;
+ ..)
+ # Parent dir; strip last assembled component from result.
+ func_dirname "$func_normal_abspath_result"
+ func_normal_abspath_result=$func_dirname_result
+ ;;
+ *)
+ # Actual path component, append it.
+ func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent"
+ ;;
+ esac
+ done
+ # Restore leading double-slash if one was found on entry.
+ func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result
+}
+
+
+# func_notquiet ARG...
+# --------------------
+# Echo program name prefixed message only when not in quiet mode.
+func_notquiet ()
+{
+ $debug_cmd
+
+ $opt_quiet || func_echo ${1+"$@"}
+
+ # A bug in bash halts the script if the last line of a function
+ # fails when set -e is in force, so we need another command to
+ # work around that:
+ :
+}
+
+
+# func_relative_path SRCDIR DSTDIR
+# --------------------------------
+# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR.
+func_relative_path ()
+{
+ $debug_cmd
+
+ func_relative_path_result=
+ func_normal_abspath "$1"
+ func_relative_path_tlibdir=$func_normal_abspath_result
+ func_normal_abspath "$2"
+ func_relative_path_tbindir=$func_normal_abspath_result
+
+ # Ascend the tree starting from libdir
+ while :; do
+ # check if we have found a prefix of bindir
+ case $func_relative_path_tbindir in
+ $func_relative_path_tlibdir)
+ # found an exact match
+ func_relative_path_tcancelled=
+ break
+ ;;
+ $func_relative_path_tlibdir*)
+ # found a matching prefix
+ func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir"
+ func_relative_path_tcancelled=$func_stripname_result
+ if test -z "$func_relative_path_result"; then
+ func_relative_path_result=.
+ fi
+ break
+ ;;
+ *)
+ func_dirname $func_relative_path_tlibdir
+ func_relative_path_tlibdir=$func_dirname_result
+ if test -z "$func_relative_path_tlibdir"; then
+ # Have to descend all the way to the root!
+ func_relative_path_result=../$func_relative_path_result
+ func_relative_path_tcancelled=$func_relative_path_tbindir
+ break
+ fi
+ func_relative_path_result=../$func_relative_path_result
+ ;;
+ esac
+ done
+
+ # Now calculate path; take care to avoid doubling-up slashes.
+ func_stripname '' '/' "$func_relative_path_result"
+ func_relative_path_result=$func_stripname_result
+ func_stripname '/' '/' "$func_relative_path_tcancelled"
+ if test -n "$func_stripname_result"; then
+ func_append func_relative_path_result "/$func_stripname_result"
+ fi
+
+ # Normalisation. If bindir is libdir, return '.' else relative path.
+ if test -n "$func_relative_path_result"; then
+ func_stripname './' '' "$func_relative_path_result"
+ func_relative_path_result=$func_stripname_result
+ fi
+
+ test -n "$func_relative_path_result" || func_relative_path_result=.
+
+ :
+}
+
+
+# func_quote_portable EVAL ARG
+# ----------------------------
+# Internal function to portably implement func_quote_arg. Note that we still
+# keep attention to performance here so we as much as possible try to avoid
+# calling sed binary (so far O(N) complexity as long as func_append is O(1)).
+func_quote_portable ()
+{
+ $debug_cmd
+
+ $require_check_ifs_backslash
+
+ func_quote_portable_result=$2
+
+ # one-time-loop (easy break)
+ while true
+ do
+ if $1; then
+ func_quote_portable_result=`$ECHO "$2" | $SED \
+ -e "$sed_double_quote_subst" -e "$sed_double_backslash"`
+ break
+ fi
+
+ # Quote for eval.
+ case $func_quote_portable_result in
+ *[\\\`\"\$]*)
+ # Fallback to sed for $func_check_bs_ifs_broken=:, or when the string
+ # contains the shell wildcard characters.
+ case $check_ifs_backshlash_broken$func_quote_portable_result in
+ :*|*[\[\*\?]*)
+ func_quote_portable_result=`$ECHO "$func_quote_portable_result" \
+ | $SED "$sed_quote_subst"`
+ break
+ ;;
+ esac
+
+ func_quote_portable_old_IFS=$IFS
+ for _G_char in '\' '`' '"' '$'
+ do
+ # STATE($1) PREV($2) SEPARATOR($3)
+ set start "" ""
+ func_quote_portable_result=dummy"$_G_char$func_quote_portable_result$_G_char"dummy
+ IFS=$_G_char
+ for _G_part in $func_quote_portable_result
+ do
+ case $1 in
+ quote)
+ func_append func_quote_portable_result "$3$2"
+ set quote "$_G_part" "\\$_G_char"
+ ;;
+ start)
+ set first "" ""
+ func_quote_portable_result=
+ ;;
+ first)
+ set quote "$_G_part" ""
+ ;;
+ esac
+ done
+ done
+ IFS=$func_quote_portable_old_IFS
+ ;;
+ *) ;;
+ esac
+ break
+ done
+
+ func_quote_portable_unquoted_result=$func_quote_portable_result
+ case $func_quote_portable_result in
+ # double-quote args containing shell metacharacters to delay
+ # word splitting, command substitution and variable expansion
+ # for a subsequent eval.
+ # many bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ func_quote_portable_result=\"$func_quote_portable_result\"
+ ;;
+ esac
+}
+
+
+# func_quotefast_eval ARG
+# -----------------------
+# Quote one ARG (internal). This is equivalent to 'func_quote_arg eval ARG',
+# but optimized for speed. Result is stored in $func_quotefast_eval.
+if test xyes = `(x=; printf -v x %q yes; echo x"$x") 2>/dev/null`; then
+ printf -v _GL_test_printf_tilde %q '~'
+ if test '\~' = "$_GL_test_printf_tilde"; then
+ func_quotefast_eval ()
+ {
+ printf -v func_quotefast_eval_result %q "$1"
+ }
+ else
+ # Broken older Bash implementations. Make those faster too if possible.
+ func_quotefast_eval ()
+ {
+ case $1 in
+ '~'*)
+ func_quote_portable false "$1"
+ func_quotefast_eval_result=$func_quote_portable_result
+ ;;
+ *)
+ printf -v func_quotefast_eval_result %q "$1"
+ ;;
+ esac
+ }
+ fi
+else
+ func_quotefast_eval ()
+ {
+ func_quote_portable false "$1"
+ func_quotefast_eval_result=$func_quote_portable_result
+ }
+fi
+
+
+# func_quote_arg MODEs ARG
+# ------------------------
+# Quote one ARG to be evaled later. MODEs argument may contain zero or more
+# specifiers listed below separated by ',' character. This function returns two
+# values:
+# i) func_quote_arg_result
+# double-quoted (when needed), suitable for a subsequent eval
+# ii) func_quote_arg_unquoted_result
+# has all characters that are still active within double
+# quotes backslashified. Available only if 'unquoted' is specified.
+#
+# Available modes:
+# ----------------
+# 'eval' (default)
+# - escape shell special characters
+# 'expand'
+# - the same as 'eval'; but do not quote variable references
+# 'pretty'
+# - request aesthetic output, i.e. '"a b"' instead of 'a\ b'. This might
+# be used later in func_quote to get output like: 'echo "a b"' instead
+# of 'echo a\ b'. This is slower than default on some shells.
+# 'unquoted'
+# - produce also $func_quote_arg_unquoted_result which does not contain
+# wrapping double-quotes.
+#
+# Examples for 'func_quote_arg pretty,unquoted string':
+#
+# string | *_result | *_unquoted_result
+# ------------+-----------------------+-------------------
+# " | \" | \"
+# a b | "a b" | a b
+# "a b" | "\"a b\"" | \"a b\"
+# * | "*" | *
+# z="${x-$y}" | "z=\"\${x-\$y}\"" | z=\"\${x-\$y}\"
+#
+# Examples for 'func_quote_arg pretty,unquoted,expand string':
+#
+# string | *_result | *_unquoted_result
+# --------------+---------------------+--------------------
+# z="${x-$y}" | "z=\"${x-$y}\"" | z=\"${x-$y}\"
+func_quote_arg ()
+{
+ _G_quote_expand=false
+ case ,$1, in
+ *,expand,*)
+ _G_quote_expand=:
+ ;;
+ esac
+
+ case ,$1, in
+ *,pretty,*|*,expand,*|*,unquoted,*)
+ func_quote_portable $_G_quote_expand "$2"
+ func_quote_arg_result=$func_quote_portable_result
+ func_quote_arg_unquoted_result=$func_quote_portable_unquoted_result
+ ;;
+ *)
+ # Faster quote-for-eval for some shells.
+ func_quotefast_eval "$2"
+ func_quote_arg_result=$func_quotefast_eval_result
+ ;;
+ esac
+}
+
+
+# func_quote MODEs ARGs...
+# ------------------------
+# Quote all ARGs to be evaled later and join them into single command. See
+# func_quote_arg's description for more info.
+func_quote ()
+{
+ $debug_cmd
+ _G_func_quote_mode=$1 ; shift
+ func_quote_result=
+ while test 0 -lt $#; do
+ func_quote_arg "$_G_func_quote_mode" "$1"
+ if test -n "$func_quote_result"; then
+ func_append func_quote_result " $func_quote_arg_result"
+ else
+ func_append func_quote_result "$func_quote_arg_result"
+ fi
+ shift
+ done
+}
+
+
+# func_stripname PREFIX SUFFIX NAME
+# ---------------------------------
+# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ eval 'func_stripname ()
+ {
+ $debug_cmd
+
+ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+ # positional parameters, so assign one to ordinary variable first.
+ func_stripname_result=$3
+ func_stripname_result=${func_stripname_result#"$1"}
+ func_stripname_result=${func_stripname_result%"$2"}
+ }'
+else
+ func_stripname ()
+ {
+ $debug_cmd
+
+ case $2 in
+ .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;;
+ *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;;
+ esac
+ }
+fi
+
+
+# func_show_eval CMD [FAIL_EXP]
+# -----------------------------
+# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is
+# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.
+func_show_eval ()
+{
+ $debug_cmd
+
+ _G_cmd=$1
+ _G_fail_exp=${2-':'}
+
+ func_quote_arg pretty,expand "$_G_cmd"
+ eval "func_notquiet $func_quote_arg_result"
+
+ $opt_dry_run || {
+ eval "$_G_cmd"
+ _G_status=$?
+ if test 0 -ne "$_G_status"; then
+ eval "(exit $_G_status); $_G_fail_exp"
+ fi
+ }
+}
+
+
+# func_show_eval_locale CMD [FAIL_EXP]
+# ------------------------------------
+# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is
+# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it. Use the saved locale for evaluation.
+func_show_eval_locale ()
+{
+ $debug_cmd
+
+ _G_cmd=$1
+ _G_fail_exp=${2-':'}
+
+ $opt_quiet || {
+ func_quote_arg expand,pretty "$_G_cmd"
+ eval "func_echo $func_quote_arg_result"
+ }
+
+ $opt_dry_run || {
+ eval "$_G_user_locale
+ $_G_cmd"
+ _G_status=$?
+ eval "$_G_safe_locale"
+ if test 0 -ne "$_G_status"; then
+ eval "(exit $_G_status); $_G_fail_exp"
+ fi
+ }
+}
+
+
+# func_tr_sh
+# ----------
+# Turn $1 into a string suitable for a shell variable name.
+# Result is stored in $func_tr_sh_result. All characters
+# not in the set a-zA-Z0-9_ are replaced with '_'. Further,
+# if $1 begins with a digit, a '_' is prepended as well.
+func_tr_sh ()
+{
+ $debug_cmd
+
+ case $1 in
+ [0-9]* | *[!a-zA-Z0-9_]*)
+ func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'`
+ ;;
+ * )
+ func_tr_sh_result=$1
+ ;;
+ esac
+}
+
+
+# func_verbose ARG...
+# -------------------
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+ $debug_cmd
+
+ $opt_verbose && func_echo "$*"
+
+ :
+}
+
+
+# func_warn_and_continue ARG...
+# -----------------------------
+# Echo program name prefixed warning message to standard error.
+func_warn_and_continue ()
+{
+ $debug_cmd
+
+ $require_term_colors
+
+ func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2
+}
+
+
+# func_warning CATEGORY ARG...
+# ----------------------------
+# Echo program name prefixed warning message to standard error. Warning
+# messages can be filtered according to CATEGORY, where this function
+# elides messages where CATEGORY is not listed in the global variable
+# 'opt_warning_types'.
+func_warning ()
+{
+ $debug_cmd
+
+ # CATEGORY must be in the warning_categories list!
+ case " $warning_categories " in
+ *" $1 "*) ;;
+ *) func_internal_error "invalid warning category '$1'" ;;
+ esac
+
+ _G_category=$1
+ shift
+
+ case " $opt_warning_types " in
+ *" $_G_category "*) $warning_func ${1+"$@"} ;;
+ esac
+}
+
+
+# func_sort_ver VER1 VER2
+# -----------------------
+# 'sort -V' is not generally available.
+# Note this deviates from the version comparison in automake
+# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a
+# but this should suffice as we won't be specifying old
+# version formats or redundant trailing .0 in bootstrap.conf.
+# If we did want full compatibility then we should probably
+# use m4_version_compare from autoconf.
+func_sort_ver ()
+{
+ $debug_cmd
+
+ printf '%s\n%s\n' "$1" "$2" \
+ | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n
+}
+
+# func_lt_ver PREV CURR
+# ---------------------
+# Return true if PREV and CURR are in the correct order according to
+# func_sort_ver, otherwise false. Use it like this:
+#
+# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..."
+func_lt_ver ()
+{
+ $debug_cmd
+
+ test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q`
+}
+
+
+# Local variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC"
+# time-stamp-time-zone: "UTC"
+# End:
+#! /bin/sh
+
+# A portable, pluggable option parser for Bourne shell.
+# Written by Gary V. Vaughan, 2010
+
+# This is free software. There is NO warranty; not even for
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Copyright (C) 2010-2019, 2021 Bootstrap Authors
+#
+# This file is dual licensed under the terms of the MIT license
+# , and GPL version 2 or later
+# . You must apply one of
+# these licenses when using or redistributing this software or any of
+# the files within it. See the URLs above, or the file `LICENSE`
+# included in the Bootstrap distribution for the full license texts.
+
+# Please report bugs or propose patches to:
+#
+
+# Set a version string for this script.
+scriptversion=2019-02-19.15; # UTC
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# This file is a library for parsing options in your shell scripts along
+# with assorted other useful supporting features that you can make use
+# of too.
+#
+# For the simplest scripts you might need only:
+#
+# #!/bin/sh
+# . relative/path/to/funclib.sh
+# . relative/path/to/options-parser
+# scriptversion=1.0
+# func_options ${1+"$@"}
+# eval set dummy "$func_options_result"; shift
+# ...rest of your script...
+#
+# In order for the '--version' option to work, you will need to have a
+# suitably formatted comment like the one at the top of this file
+# starting with '# Written by ' and ending with '# Copyright'.
+#
+# For '-h' and '--help' to work, you will also need a one line
+# description of your script's purpose in a comment directly above the
+# '# Written by ' line, like the one at the top of this file.
+#
+# The default options also support '--debug', which will turn on shell
+# execution tracing (see the comment above debug_cmd below for another
+# use), and '--verbose' and the func_verbose function to allow your script
+# to display verbose messages only when your user has specified
+# '--verbose'.
+#
+# After sourcing this file, you can plug in processing for additional
+# options by amending the variables from the 'Configuration' section
+# below, and following the instructions in the 'Option parsing'
+# section further down.
+
+## -------------- ##
+## Configuration. ##
+## -------------- ##
+
+# You should override these variables in your script after sourcing this
+# file so that they reflect the customisations you have added to the
+# option parser.
+
+# The usage line for option parsing errors and the start of '-h' and
+# '--help' output messages. You can embed shell variables for delayed
+# expansion at the time the message is displayed, but you will need to
+# quote other shell meta-characters carefully to prevent them being
+# expanded when the contents are evaled.
+usage='$progpath [OPTION]...'
+
+# Short help message in response to '-h' and '--help'. Add to this or
+# override it after sourcing this library to reflect the full set of
+# options your script accepts.
+usage_message="\
+ --debug enable verbose shell tracing
+ -W, --warnings=CATEGORY
+ report the warnings falling in CATEGORY [all]
+ -v, --verbose verbosely report processing
+ --version print version information and exit
+ -h, --help print short or long help message and exit
+"
+
+# Additional text appended to 'usage_message' in response to '--help'.
+long_help_message="
+Warning categories include:
+ 'all' show all warnings
+ 'none' turn off all the warnings
+ 'error' warnings are treated as fatal errors"
+
+# Help message printed before fatal option parsing errors.
+fatal_help="Try '\$progname --help' for more information."
+
+
+
+## ------------------------- ##
+## Hook function management. ##
+## ------------------------- ##
+
+# This section contains functions for adding, removing, and running hooks
+# in the main code. A hook is just a list of function names that can be
+# run in order later on.
+
+# func_hookable FUNC_NAME
+# -----------------------
+# Declare that FUNC_NAME will run hooks added with
+# 'func_add_hook FUNC_NAME ...'.
+func_hookable ()
+{
+ $debug_cmd
+
+ func_append hookable_fns " $1"
+}
+
+
+# func_add_hook FUNC_NAME HOOK_FUNC
+# ---------------------------------
+# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must
+# first have been declared "hookable" by a call to 'func_hookable'.
+func_add_hook ()
+{
+ $debug_cmd
+
+ case " $hookable_fns " in
+ *" $1 "*) ;;
+ *) func_fatal_error "'$1' does not accept hook functions." ;;
+ esac
+
+ eval func_append ${1}_hooks '" $2"'
+}
+
+
+# func_remove_hook FUNC_NAME HOOK_FUNC
+# ------------------------------------
+# Remove HOOK_FUNC from the list of hook functions to be called by
+# FUNC_NAME.
+func_remove_hook ()
+{
+ $debug_cmd
+
+ eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`'
+}
+
+
+# func_propagate_result FUNC_NAME_A FUNC_NAME_B
+# ---------------------------------------------
+# If the *_result variable of FUNC_NAME_A _is set_, assign its value to
+# *_result variable of FUNC_NAME_B.
+func_propagate_result ()
+{
+ $debug_cmd
+
+ func_propagate_result_result=:
+ if eval "test \"\${${1}_result+set}\" = set"
+ then
+ eval "${2}_result=\$${1}_result"
+ else
+ func_propagate_result_result=false
+ fi
+}
+
+
+# func_run_hooks FUNC_NAME [ARG]...
+# ---------------------------------
+# Run all hook functions registered to FUNC_NAME.
+# It's assumed that the list of hook functions contains nothing more
+# than a whitespace-delimited list of legal shell function names, and
+# no effort is wasted trying to catch shell meta-characters or preserve
+# whitespace.
+func_run_hooks ()
+{
+ $debug_cmd
+
+ _G_rc_run_hooks=false
+
+ case " $hookable_fns " in
+ *" $1 "*) ;;
+ *) func_fatal_error "'$1' does not support hook functions." ;;
+ esac
+
+ eval _G_hook_fns=\$$1_hooks; shift
+
+ for _G_hook in $_G_hook_fns; do
+ func_unset "${_G_hook}_result"
+ eval $_G_hook '${1+"$@"}'
+ func_propagate_result $_G_hook func_run_hooks
+ if $func_propagate_result_result; then
+ eval set dummy "$func_run_hooks_result"; shift
+ fi
+ done
+}
+
+
+
+## --------------- ##
+## Option parsing. ##
+## --------------- ##
+
+# In order to add your own option parsing hooks, you must accept the
+# full positional parameter list from your hook function. You may remove
+# or edit any options that you action, and then pass back the remaining
+# unprocessed options in '_result', escaped
+# suitably for 'eval'.
+#
+# The '_result' variable is automatically unset
+# before your hook gets called; for best performance, only set the
+# *_result variable when necessary (i.e. don't call the 'func_quote'
+# function unnecessarily because it can be an expensive operation on some
+# machines).
+#
+# Like this:
+#
+# my_options_prep ()
+# {
+# $debug_cmd
+#
+# # Extend the existing usage message.
+# usage_message=$usage_message'
+# -s, --silent don'\''t print informational messages
+# '
+# # No change in '$@' (ignored completely by this hook). Leave
+# # my_options_prep_result variable intact.
+# }
+# func_add_hook func_options_prep my_options_prep
+#
+#
+# my_silent_option ()
+# {
+# $debug_cmd
+#
+# args_changed=false
+#
+# # Note that, for efficiency, we parse as many options as we can
+# # recognise in a loop before passing the remainder back to the
+# # caller on the first unrecognised argument we encounter.
+# while test $# -gt 0; do
+# opt=$1; shift
+# case $opt in
+# --silent|-s) opt_silent=:
+# args_changed=:
+# ;;
+# # Separate non-argument short options:
+# -s*) func_split_short_opt "$_G_opt"
+# set dummy "$func_split_short_opt_name" \
+# "-$func_split_short_opt_arg" ${1+"$@"}
+# shift
+# args_changed=:
+# ;;
+# *) # Make sure the first unrecognised option "$_G_opt"
+# # is added back to "$@" in case we need it later,
+# # if $args_changed was set to 'true'.
+# set dummy "$_G_opt" ${1+"$@"}; shift; break ;;
+# esac
+# done
+#
+# # Only call 'func_quote' here if we processed at least one argument.
+# if $args_changed; then
+# func_quote eval ${1+"$@"}
+# my_silent_option_result=$func_quote_result
+# fi
+# }
+# func_add_hook func_parse_options my_silent_option
+#
+#
+# my_option_validation ()
+# {
+# $debug_cmd
+#
+# $opt_silent && $opt_verbose && func_fatal_help "\
+# '--silent' and '--verbose' options are mutually exclusive."
+# }
+# func_add_hook func_validate_options my_option_validation
+#
+# You'll also need to manually amend $usage_message to reflect the extra
+# options you parse. It's preferable to append if you can, so that
+# multiple option parsing hooks can be added safely.
+
+
+# func_options_finish [ARG]...
+# ----------------------------
+# Finishing the option parse loop (call 'func_options' hooks ATM).
+func_options_finish ()
+{
+ $debug_cmd
+
+ func_run_hooks func_options ${1+"$@"}
+ func_propagate_result func_run_hooks func_options_finish
+}
+
+
+# func_options [ARG]...
+# ---------------------
+# All the functions called inside func_options are hookable. See the
+# individual implementations for details.
+func_hookable func_options
+func_options ()
+{
+ $debug_cmd
+
+ _G_options_quoted=false
+
+ for my_func in options_prep parse_options validate_options options_finish
+ do
+ func_unset func_${my_func}_result
+ func_unset func_run_hooks_result
+ eval func_$my_func '${1+"$@"}'
+ func_propagate_result func_$my_func func_options
+ if $func_propagate_result_result; then
+ eval set dummy "$func_options_result"; shift
+ _G_options_quoted=:
+ fi
+ done
+
+ $_G_options_quoted || {
+ # As we (func_options) are top-level options-parser function and
+ # nobody quoted "$@" for us yet, we need to do it explicitly for
+ # caller.
+ func_quote eval ${1+"$@"}
+ func_options_result=$func_quote_result
+ }
+}
+
+
+# func_options_prep [ARG]...
+# --------------------------
+# All initialisations required before starting the option parse loop.
+# Note that when calling hook functions, we pass through the list of
+# positional parameters. If a hook function modifies that list, and
+# needs to propagate that back to rest of this script, then the complete
+# modified list must be put in 'func_run_hooks_result' before returning.
+func_hookable func_options_prep
+func_options_prep ()
+{
+ $debug_cmd
+
+ # Option defaults:
+ opt_verbose=false
+ opt_warning_types=
+
+ func_run_hooks func_options_prep ${1+"$@"}
+ func_propagate_result func_run_hooks func_options_prep
+}
+
+
+# func_parse_options [ARG]...
+# ---------------------------
+# The main option parsing loop.
+func_hookable func_parse_options
+func_parse_options ()
+{
+ $debug_cmd
+
+ _G_parse_options_requote=false
+ # this just eases exit handling
+ while test $# -gt 0; do
+ # Defer to hook functions for initial option parsing, so they
+ # get priority in the event of reusing an option name.
+ func_run_hooks func_parse_options ${1+"$@"}
+ func_propagate_result func_run_hooks func_parse_options
+ if $func_propagate_result_result; then
+ eval set dummy "$func_parse_options_result"; shift
+ # Even though we may have changed "$@", we passed the "$@" array
+ # down into the hook and it quoted it for us (because we are in
+ # this if-branch). No need to quote it again.
+ _G_parse_options_requote=false
+ fi
+
+ # Break out of the loop if we already parsed every option.
+ test $# -gt 0 || break
+
+ # We expect that one of the options parsed in this function matches
+ # and thus we remove _G_opt from "$@" and need to re-quote.
+ _G_match_parse_options=:
+ _G_opt=$1
+ shift
+ case $_G_opt in
+ --debug|-x) debug_cmd='set -x'
+ func_echo "enabling shell trace mode" >&2
+ $debug_cmd
+ ;;
+
+ --no-warnings|--no-warning|--no-warn)
+ set dummy --warnings none ${1+"$@"}
+ shift
+ ;;
+
+ --warnings|--warning|-W)
+ if test $# = 0 && func_missing_arg $_G_opt; then
+ _G_parse_options_requote=:
+ break
+ fi
+ case " $warning_categories $1" in
+ *" $1 "*)
+ # trailing space prevents matching last $1 above
+ func_append_uniq opt_warning_types " $1"
+ ;;
+ *all)
+ opt_warning_types=$warning_categories
+ ;;
+ *none)
+ opt_warning_types=none
+ warning_func=:
+ ;;
+ *error)
+ opt_warning_types=$warning_categories
+ warning_func=func_fatal_error
+ ;;
+ *)
+ func_fatal_error \
+ "unsupported warning category: '$1'"
+ ;;
+ esac
+ shift
+ ;;
+
+ --verbose|-v) opt_verbose=: ;;
+ --version) func_version ;;
+ -\?|-h) func_usage ;;
+ --help) func_help ;;
+
+ # Separate optargs to long options (plugins may need this):
+ --*=*) func_split_equals "$_G_opt"
+ set dummy "$func_split_equals_lhs" \
+ "$func_split_equals_rhs" ${1+"$@"}
+ shift
+ ;;
+
+ # Separate optargs to short options:
+ -W*)
+ func_split_short_opt "$_G_opt"
+ set dummy "$func_split_short_opt_name" \
+ "$func_split_short_opt_arg" ${1+"$@"}
+ shift
+ ;;
+
+ # Separate non-argument short options:
+ -\?*|-h*|-v*|-x*)
+ func_split_short_opt "$_G_opt"
+ set dummy "$func_split_short_opt_name" \
+ "-$func_split_short_opt_arg" ${1+"$@"}
+ shift
+ ;;
+
+ --) _G_parse_options_requote=: ; break ;;
+ -*) func_fatal_help "unrecognised option: '$_G_opt'" ;;
+ *) set dummy "$_G_opt" ${1+"$@"}; shift
+ _G_match_parse_options=false
+ break
+ ;;
+ esac
+
+ if $_G_match_parse_options; then
+ _G_parse_options_requote=:
+ fi
+ done
+
+ if $_G_parse_options_requote; then
+ # save modified positional parameters for caller
+ func_quote eval ${1+"$@"}
+ func_parse_options_result=$func_quote_result
+ fi
+}
+
+
+# func_validate_options [ARG]...
+# ------------------------------
+# Perform any sanity checks on option settings and/or unconsumed
+# arguments.
+func_hookable func_validate_options
+func_validate_options ()
+{
+ $debug_cmd
+
+ # Display all warnings if -W was not given.
+ test -n "$opt_warning_types" || opt_warning_types=" $warning_categories"
+
+ func_run_hooks func_validate_options ${1+"$@"}
+ func_propagate_result func_run_hooks func_validate_options
+
+ # Bail if the options were screwed!
+ $exit_cmd $EXIT_FAILURE
+}
+
+
+
+## ----------------- ##
+## Helper functions. ##
+## ----------------- ##
+
+# This section contains the helper functions used by the rest of the
+# hookable option parser framework in ascii-betical order.
+
+
+# func_fatal_help ARG...
+# ----------------------
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+ $debug_cmd
+
+ eval \$ECHO \""Usage: $usage"\"
+ eval \$ECHO \""$fatal_help"\"
+ func_error ${1+"$@"}
+ exit $EXIT_FAILURE
+}
+
+
+# func_help
+# ---------
+# Echo long help message to standard output and exit.
+func_help ()
+{
+ $debug_cmd
+
+ func_usage_message
+ $ECHO "$long_help_message"
+ exit 0
+}
+
+
+# func_missing_arg ARGNAME
+# ------------------------
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+ $debug_cmd
+
+ func_error "Missing argument for '$1'."
+ exit_cmd=exit
+}
+
+
+# func_split_equals STRING
+# ------------------------
+# Set func_split_equals_lhs and func_split_equals_rhs shell variables
+# after splitting STRING at the '=' sign.
+test -z "$_G_HAVE_XSI_OPS" \
+ && (eval 'x=a/b/c;
+ test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
+ && _G_HAVE_XSI_OPS=yes
+
+if test yes = "$_G_HAVE_XSI_OPS"
+then
+ # This is an XSI compatible shell, allowing a faster implementation...
+ eval 'func_split_equals ()
+ {
+ $debug_cmd
+
+ func_split_equals_lhs=${1%%=*}
+ func_split_equals_rhs=${1#*=}
+ if test "x$func_split_equals_lhs" = "x$1"; then
+ func_split_equals_rhs=
+ fi
+ }'
+else
+ # ...otherwise fall back to using expr, which is often a shell builtin.
+ func_split_equals ()
+ {
+ $debug_cmd
+
+ func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'`
+ func_split_equals_rhs=
+ test "x$func_split_equals_lhs=" = "x$1" \
+ || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'`
+ }
+fi #func_split_equals
+
+
+# func_split_short_opt SHORTOPT
+# -----------------------------
+# Set func_split_short_opt_name and func_split_short_opt_arg shell
+# variables after splitting SHORTOPT after the 2nd character.
+if test yes = "$_G_HAVE_XSI_OPS"
+then
+ # This is an XSI compatible shell, allowing a faster implementation...
+ eval 'func_split_short_opt ()
+ {
+ $debug_cmd
+
+ func_split_short_opt_arg=${1#??}
+ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}
+ }'
+else
+ # ...otherwise fall back to using expr, which is often a shell builtin.
+ func_split_short_opt ()
+ {
+ $debug_cmd
+
+ func_split_short_opt_name=`expr "x$1" : 'x\(-.\)'`
+ func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'`
+ }
+fi #func_split_short_opt
+
+
+# func_usage
+# ----------
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+ $debug_cmd
+
+ func_usage_message
+ $ECHO "Run '$progname --help |${PAGER-more}' for full usage"
+ exit 0
+}
+
+
+# func_usage_message
+# ------------------
+# Echo short help message to standard output.
+func_usage_message ()
+{
+ $debug_cmd
+
+ eval \$ECHO \""Usage: $usage"\"
+ echo
+ $SED -n 's|^# ||
+ /^Written by/{
+ x;p;x
+ }
+ h
+ /^Written by/q' < "$progpath"
+ echo
+ eval \$ECHO \""$usage_message"\"
+}
+
+
+# func_version
+# ------------
+# Echo version message to standard output and exit.
+# The version message is extracted from the calling file's header
+# comments, with leading '# ' stripped:
+# 1. First display the progname and version
+# 2. Followed by the header comment line matching /^# Written by /
+# 3. Then a blank line followed by the first following line matching
+# /^# Copyright /
+# 4. Immediately followed by any lines between the previous matches,
+# except lines preceding the intervening completely blank line.
+# For example, see the header comments of this file.
+func_version ()
+{
+ $debug_cmd
+
+ printf '%s\n' "$progname $scriptversion"
+ $SED -n '
+ /^# Written by /!b
+ s|^# ||; p; n
+
+ :fwd2blnk
+ /./ {
+ n
+ b fwd2blnk
+ }
+ p; n
+
+ :holdwrnt
+ s|^# ||
+ s|^# *$||
+ /^Copyright /!{
+ /./H
+ n
+ b holdwrnt
+ }
+
+ s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2|
+ G
+ s|\(\n\)\n*|\1|g
+ p; q' < "$progpath"
+
+ exit $?
+}
+
+
+# Local variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-pattern: "30/scriptversion=%:y-%02m-%02d.%02H; # UTC"
+# time-stamp-time-zone: "UTC"
+# End:
+
+# Set a version string.
+scriptversion='(GNU libtool) 2.4.7'
+
+
+# func_echo ARG...
+# ----------------
+# Libtool also displays the current mode in messages, so override
+# funclib.sh func_echo with this custom definition.
+func_echo ()
+{
+ $debug_cmd
+
+ _G_message=$*
+
+ func_echo_IFS=$IFS
+ IFS=$nl
+ for _G_line in $_G_message; do
+ IFS=$func_echo_IFS
+ $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line"
+ done
+ IFS=$func_echo_IFS
+}
+
+
+# func_warning ARG...
+# -------------------
+# Libtool warnings are not categorized, so override funclib.sh
+# func_warning with this simpler definition.
+func_warning ()
+{
+ $debug_cmd
+
+ $warning_func ${1+"$@"}
+}
+
+
+## ---------------- ##
+## Options parsing. ##
+## ---------------- ##
+
+# Hook in the functions to make sure our own options are parsed during
+# the option parsing loop.
+
+usage='$progpath [OPTION]... [MODE-ARG]...'
+
+# Short help message in response to '-h'.
+usage_message="Options:
+ --config show all configuration variables
+ --debug enable verbose shell tracing
+ -n, --dry-run display commands without modifying any files
+ --features display basic configuration information and exit
+ --mode=MODE use operation mode MODE
+ --no-warnings equivalent to '-Wnone'
+ --preserve-dup-deps don't remove duplicate dependency libraries
+ --quiet, --silent don't print informational messages
+ --tag=TAG use configuration variables from tag TAG
+ -v, --verbose print more informational messages than default
+ --version print version information
+ -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all]
+ -h, --help, --help-all print short, long, or detailed help message
+"
+
+# Additional text appended to 'usage_message' in response to '--help'.
+func_help ()
+{
+ $debug_cmd
+
+ func_usage_message
+ $ECHO "$long_help_message
+
+MODE must be one of the following:
+
+ clean remove files from the build directory
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. When passed as first option,
+'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that.
+Try '$progname --help --mode=MODE' for a more detailed description of MODE.
+
+When reporting a bug, please describe a test case to reproduce it and
+include the following information:
+
+ host-triplet: $host
+ shell: $SHELL
+ compiler: $LTCC
+ compiler flags: $LTCFLAGS
+ linker: $LD (gnu? $with_gnu_ld)
+ version: $progname $scriptversion Debian-2.4.7-7build1
+ automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
+ autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q`
+
+Report bugs to .
+GNU libtool home page: .
+General help using GNU software: ."
+ exit 0
+}
+
+
+# func_lo2o OBJECT-NAME
+# ---------------------
+# Transform OBJECT-NAME from a '.lo' suffix to the platform specific
+# object suffix.
+
+lo2o=s/\\.lo\$/.$objext/
+o2lo=s/\\.$objext\$/.lo/
+
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ eval 'func_lo2o ()
+ {
+ case $1 in
+ *.lo) func_lo2o_result=${1%.lo}.$objext ;;
+ * ) func_lo2o_result=$1 ;;
+ esac
+ }'
+
+ # func_xform LIBOBJ-OR-SOURCE
+ # ---------------------------
+ # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise)
+ # suffix to a '.lo' libtool-object suffix.
+ eval 'func_xform ()
+ {
+ func_xform_result=${1%.*}.lo
+ }'
+else
+ # ...otherwise fall back to using sed.
+ func_lo2o ()
+ {
+ func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"`
+ }
+
+ func_xform ()
+ {
+ func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'`
+ }
+fi
+
+
+# func_fatal_configuration ARG...
+# -------------------------------
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+ func_fatal_error ${1+"$@"} \
+ "See the $PACKAGE documentation for more information." \
+ "Fatal configuration error."
+}
+
+
+# func_config
+# -----------
+# Display the configuration for all the tags in this script.
+func_config ()
+{
+ re_begincf='^# ### BEGIN LIBTOOL'
+ re_endcf='^# ### END LIBTOOL'
+
+ # Default configuration.
+ $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
+
+ # Now print the configurations for the tags.
+ for tagname in $taglist; do
+ $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
+ done
+
+ exit $?
+}
+
+
+# func_features
+# -------------
+# Display the features supported by this script.
+func_features ()
+{
+ echo "host: $host"
+ if test yes = "$build_libtool_libs"; then
+ echo "enable shared libraries"
+ else
+ echo "disable shared libraries"
+ fi
+ if test yes = "$build_old_libs"; then
+ echo "enable static libraries"
+ else
+ echo "disable static libraries"
+ fi
+
+ exit $?
+}
+
+
+# func_enable_tag TAGNAME
+# -----------------------
+# Verify that TAGNAME is valid, and either flag an error and exit, or
+# enable the TAGNAME tag. We also add TAGNAME to the global $taglist
+# variable here.
+func_enable_tag ()
+{
+ # Global variable:
+ tagname=$1
+
+ re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
+ re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
+ sed_extractcf=/$re_begincf/,/$re_endcf/p
+
+ # Validate tagname.
+ case $tagname in
+ *[!-_A-Za-z0-9,/]*)
+ func_fatal_error "invalid tag name: $tagname"
+ ;;
+ esac
+
+ # Don't test for the "default" C tag, as we know it's
+ # there but not specially marked.
+ case $tagname in
+ CC) ;;
+ *)
+ if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
+ taglist="$taglist $tagname"
+
+ # Evaluate the configuration. Be careful to quote the path
+ # and the sed script, to avoid splitting on whitespace, but
+ # also don't use non-portable quotes within backquotes within
+ # quotes we have to do it in 2 steps:
+ extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
+ eval "$extractedcf"
+ else
+ func_error "ignoring unknown tag $tagname"
+ fi
+ ;;
+ esac
+}
+
+
+# func_check_version_match
+# ------------------------
+# Ensure that we are using m4 macros, and libtool script from the same
+# release of libtool.
+func_check_version_match ()
+{
+ if test "$package_revision" != "$macro_revision"; then
+ if test "$VERSION" != "$macro_version"; then
+ if test -z "$macro_version"; then
+ cat >&2 <<_LT_EOF
+$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from an older release.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+ else
+ cat >&2 <<_LT_EOF
+$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+ fi
+ else
+ cat >&2 <<_LT_EOF
+$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision,
+$progname: but the definition of this LT_INIT comes from revision $macro_revision.
+$progname: You should recreate aclocal.m4 with macros from revision $package_revision
+$progname: of $PACKAGE $VERSION and run autoconf again.
+_LT_EOF
+ fi
+
+ exit $EXIT_MISMATCH
+ fi
+}
+
+
+# libtool_options_prep [ARG]...
+# -----------------------------
+# Preparation for options parsed by libtool.
+libtool_options_prep ()
+{
+ $debug_mode
+
+ # Option defaults:
+ opt_config=false
+ opt_dlopen=
+ opt_dry_run=false
+ opt_help=false
+ opt_mode=
+ opt_preserve_dup_deps=false
+ opt_quiet=false
+
+ nonopt=
+ preserve_args=
+
+ _G_rc_lt_options_prep=:
+
+ _G_rc_lt_options_prep=:
+
+ # Shorthand for --mode=foo, only valid as the first argument
+ case $1 in
+ clean|clea|cle|cl)
+ shift; set dummy --mode clean ${1+"$@"}; shift
+ ;;
+ compile|compil|compi|comp|com|co|c)
+ shift; set dummy --mode compile ${1+"$@"}; shift
+ ;;
+ execute|execut|execu|exec|exe|ex|e)
+ shift; set dummy --mode execute ${1+"$@"}; shift
+ ;;
+ finish|finis|fini|fin|fi|f)
+ shift; set dummy --mode finish ${1+"$@"}; shift
+ ;;
+ install|instal|insta|inst|ins|in|i)
+ shift; set dummy --mode install ${1+"$@"}; shift
+ ;;
+ link|lin|li|l)
+ shift; set dummy --mode link ${1+"$@"}; shift
+ ;;
+ uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
+ shift; set dummy --mode uninstall ${1+"$@"}; shift
+ ;;
+ *)
+ _G_rc_lt_options_prep=false
+ ;;
+ esac
+
+ if $_G_rc_lt_options_prep; then
+ # Pass back the list of options.
+ func_quote eval ${1+"$@"}
+ libtool_options_prep_result=$func_quote_result
+ fi
+}
+func_add_hook func_options_prep libtool_options_prep
+
+
+# libtool_parse_options [ARG]...
+# ---------------------------------
+# Provide handling for libtool specific options.
+libtool_parse_options ()
+{
+ $debug_cmd
+
+ _G_rc_lt_parse_options=false
+
+ # Perform our own loop to consume as many options as possible in
+ # each iteration.
+ while test $# -gt 0; do
+ _G_match_lt_parse_options=:
+ _G_opt=$1
+ shift
+ case $_G_opt in
+ --dry-run|--dryrun|-n)
+ opt_dry_run=:
+ ;;
+
+ --config) func_config ;;
+
+ --dlopen|-dlopen)
+ opt_dlopen="${opt_dlopen+$opt_dlopen
+}$1"
+ shift
+ ;;
+
+ --preserve-dup-deps)
+ opt_preserve_dup_deps=: ;;
+
+ --features) func_features ;;
+
+ --finish) set dummy --mode finish ${1+"$@"}; shift ;;
+
+ --help) opt_help=: ;;
+
+ --help-all) opt_help=': help-all' ;;
+
+ --mode) test $# = 0 && func_missing_arg $_G_opt && break
+ opt_mode=$1
+ case $1 in
+ # Valid mode arguments:
+ clean|compile|execute|finish|install|link|relink|uninstall) ;;
+
+ # Catch anything else as an error
+ *) func_error "invalid argument for $_G_opt"
+ exit_cmd=exit
+ break
+ ;;
+ esac
+ shift
+ ;;
+
+ --no-silent|--no-quiet)
+ opt_quiet=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --no-warnings|--no-warning|--no-warn)
+ opt_warning=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --no-verbose)
+ opt_verbose=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --silent|--quiet)
+ opt_quiet=:
+ opt_verbose=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --tag) test $# = 0 && func_missing_arg $_G_opt && break
+ opt_tag=$1
+ func_append preserve_args " $_G_opt $1"
+ func_enable_tag "$1"
+ shift
+ ;;
+
+ --verbose|-v) opt_quiet=false
+ opt_verbose=:
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ # An option not handled by this hook function:
+ *) set dummy "$_G_opt" ${1+"$@"} ; shift
+ _G_match_lt_parse_options=false
+ break
+ ;;
+ esac
+ $_G_match_lt_parse_options && _G_rc_lt_parse_options=:
+ done
+
+ if $_G_rc_lt_parse_options; then
+ # save modified positional parameters for caller
+ func_quote eval ${1+"$@"}
+ libtool_parse_options_result=$func_quote_result
+ fi
+}
+func_add_hook func_parse_options libtool_parse_options
+
+
+
+# libtool_validate_options [ARG]...
+# ---------------------------------
+# Perform any sanity checks on option settings and/or unconsumed
+# arguments.
+libtool_validate_options ()
+{
+ # save first non-option argument
+ if test 0 -lt $#; then
+ nonopt=$1
+ shift
+ fi
+
+ # preserve --debug
+ test : = "$debug_cmd" || func_append preserve_args " --debug"
+
+ case $host in
+ # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452
+ # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788
+ *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*)
+ # don't eliminate duplications in $postdeps and $predeps
+ opt_duplicate_compiler_generated_deps=:
+ ;;
+ *)
+ opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps
+ ;;
+ esac
+
+ $opt_help || {
+ # Sanity checks first:
+ func_check_version_match
+
+ test yes != "$build_libtool_libs" \
+ && test yes != "$build_old_libs" \
+ && func_fatal_configuration "not configured to build any kind of library"
+
+ # Darwin sucks
+ eval std_shrext=\"$shrext_cmds\"
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$opt_dlopen" && test execute != "$opt_mode"; then
+ func_error "unrecognized option '-dlopen'"
+ $ECHO "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help=$help
+ help="Try '$progname --help --mode=$opt_mode' for more information."
+ }
+
+ # Pass back the unparsed argument list
+ func_quote eval ${1+"$@"}
+ libtool_validate_options_result=$func_quote_result
+}
+func_add_hook func_validate_options libtool_validate_options
+
+
+# Process options as early as possible so that --help and --version
+# can return quickly.
+func_options ${1+"$@"}
+eval set dummy "$func_options_result"; shift
+
+
+
+## ----------- ##
+## Main. ##
+## ----------- ##
+
+magic='%%%MAGIC variable%%%'
+magic_exe='%%%MAGIC EXE variable%%%'
+
+# Global variables.
+extracted_archives=
+extracted_serial=0
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end. This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+
+# func_generated_by_libtool
+# True iff stdin has been generated by Libtool. This function is only
+# a basic sanity check; it will hardly flush out determined imposters.
+func_generated_by_libtool_p ()
+{
+ $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# func_lalib_p file
+# True iff FILE is a libtool '.la' library or '.lo' object file.
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_lalib_p ()
+{
+ test -f "$1" &&
+ $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p
+}
+
+# func_lalib_unsafe_p file
+# True iff FILE is a libtool '.la' library or '.lo' object file.
+# This function implements the same check as func_lalib_p without
+# resorting to external programs. To this end, it redirects stdin and
+# closes it afterwards, without saving the original file descriptor.
+# As a safety measure, use it only where a negative result would be
+# fatal anyway. Works if 'file' does not exist.
+func_lalib_unsafe_p ()
+{
+ lalib_p=no
+ if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
+ for lalib_p_l in 1 2 3 4
+ do
+ read lalib_p_line
+ case $lalib_p_line in
+ \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
+ esac
+ done
+ exec 0<&5 5<&-
+ fi
+ test yes = "$lalib_p"
+}
+
+# func_ltwrapper_script_p file
+# True iff FILE is a libtool wrapper script
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_script_p ()
+{
+ test -f "$1" &&
+ $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p
+}
+
+# func_ltwrapper_executable_p file
+# True iff FILE is a libtool wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_executable_p ()
+{
+ func_ltwrapper_exec_suffix=
+ case $1 in
+ *.exe) ;;
+ *) func_ltwrapper_exec_suffix=.exe ;;
+ esac
+ $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
+}
+
+# func_ltwrapper_scriptname file
+# Assumes file is an ltwrapper_executable
+# uses $file to determine the appropriate filename for a
+# temporary ltwrapper_script.
+func_ltwrapper_scriptname ()
+{
+ func_dirname_and_basename "$1" "" "."
+ func_stripname '' '.exe' "$func_basename_result"
+ func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper
+}
+
+# func_ltwrapper_p file
+# True iff FILE is a libtool wrapper script or wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_p ()
+{
+ func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
+}
+
+
+# func_execute_cmds commands fail_cmd
+# Execute tilde-delimited COMMANDS.
+# If FAIL_CMD is given, eval that upon failure.
+# FAIL_CMD may read-access the current command in variable CMD!
+func_execute_cmds ()
+{
+ $debug_cmd
+
+ save_ifs=$IFS; IFS='~'
+ for cmd in $1; do
+ IFS=$sp$nl
+ eval cmd=\"$cmd\"
+ IFS=$save_ifs
+ func_show_eval "$cmd" "${2-:}"
+ done
+ IFS=$save_ifs
+}
+
+
+# func_source file
+# Source FILE, adding directory component if necessary.
+# Note that it is not necessary on cygwin/mingw to append a dot to
+# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
+# behavior happens only for exec(3), not for open(2)! Also, sourcing
+# 'FILE.' does not work on cygwin managed mounts.
+func_source ()
+{
+ $debug_cmd
+
+ case $1 in
+ */* | *\\*) . "$1" ;;
+ *) . "./$1" ;;
+ esac
+}
+
+
+# func_resolve_sysroot PATH
+# Replace a leading = in PATH with a sysroot. Store the result into
+# func_resolve_sysroot_result
+func_resolve_sysroot ()
+{
+ func_resolve_sysroot_result=$1
+ case $func_resolve_sysroot_result in
+ =*)
+ func_stripname '=' '' "$func_resolve_sysroot_result"
+ func_resolve_sysroot_result=$lt_sysroot$func_stripname_result
+ ;;
+ esac
+}
+
+# func_replace_sysroot PATH
+# If PATH begins with the sysroot, replace it with = and
+# store the result into func_replace_sysroot_result.
+func_replace_sysroot ()
+{
+ case $lt_sysroot:$1 in
+ ?*:"$lt_sysroot"*)
+ func_stripname "$lt_sysroot" '' "$1"
+ func_replace_sysroot_result='='$func_stripname_result
+ ;;
+ *)
+ # Including no sysroot.
+ func_replace_sysroot_result=$1
+ ;;
+ esac
+}
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+ $debug_cmd
+
+ if test -n "$available_tags" && test -z "$tagname"; then
+ CC_quoted=
+ for arg in $CC; do
+ func_append_quoted CC_quoted "$arg"
+ done
+ CC_expanded=`func_echo_all $CC`
+ CC_quoted_expanded=`func_echo_all $CC_quoted`
+ case $@ in
+ # Blanks in the command may have been stripped by the calling shell,
+ # but not from the CC environment variable when configure was run.
+ " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;;
+ # Blanks at the start of $base_compile will cause this to fail
+ # if we don't check for them as well.
+ *)
+ for z in $available_tags; do
+ if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+ # Evaluate the configuration.
+ eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+ CC_quoted=
+ for arg in $CC; do
+ # Double-quote args containing other shell metacharacters.
+ func_append_quoted CC_quoted "$arg"
+ done
+ CC_expanded=`func_echo_all $CC`
+ CC_quoted_expanded=`func_echo_all $CC_quoted`
+ case "$@ " in
+ " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*)
+ # The compiler in the base compile command matches
+ # the one in the tagged configuration.
+ # Assume this is the tagged configuration we want.
+ tagname=$z
+ break
+ ;;
+ esac
+ fi
+ done
+ # If $tagname still isn't set, then no tagged configuration
+ # was found and let the user know that the "--tag" command
+ # line option must be used.
+ if test -z "$tagname"; then
+ func_echo "unable to infer tagged configuration"
+ func_fatal_error "specify a tag with '--tag'"
+# else
+# func_verbose "using $tagname tagged configuration"
+ fi
+ ;;
+ esac
+ fi
+}
+
+
+
+# func_write_libtool_object output_name pic_name nonpic_name
+# Create a libtool object file (analogous to a ".la" file),
+# but don't create it if we're doing a dry run.
+func_write_libtool_object ()
+{
+ write_libobj=$1
+ if test yes = "$build_libtool_libs"; then
+ write_lobj=\'$2\'
+ else
+ write_lobj=none
+ fi
+
+ if test yes = "$build_old_libs"; then
+ write_oldobj=\'$3\'
+ else
+ write_oldobj=none
+ fi
+
+ $opt_dry_run || {
+ cat >${write_libobj}T </dev/null`
+ if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then
+ func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" |
+ $SED -e "$sed_naive_backslashify"`
+ else
+ func_convert_core_file_wine_to_w32_result=
+ fi
+ fi
+}
+# end: func_convert_core_file_wine_to_w32
+
+
+# func_convert_core_path_wine_to_w32 ARG
+# Helper function used by path conversion functions when $build is *nix, and
+# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly
+# configured wine environment available, with the winepath program in $build's
+# $PATH. Assumes ARG has no leading or trailing path separator characters.
+#
+# ARG is path to be converted from $build format to win32.
+# Result is available in $func_convert_core_path_wine_to_w32_result.
+# Unconvertible file (directory) names in ARG are skipped; if no directory names
+# are convertible, then the result may be empty.
+func_convert_core_path_wine_to_w32 ()
+{
+ $debug_cmd
+
+ # unfortunately, winepath doesn't convert paths, only file names
+ func_convert_core_path_wine_to_w32_result=
+ if test -n "$1"; then
+ oldIFS=$IFS
+ IFS=:
+ for func_convert_core_path_wine_to_w32_f in $1; do
+ IFS=$oldIFS
+ func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f"
+ if test -n "$func_convert_core_file_wine_to_w32_result"; then
+ if test -z "$func_convert_core_path_wine_to_w32_result"; then
+ func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result
+ else
+ func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result"
+ fi
+ fi
+ done
+ IFS=$oldIFS
+ fi
+}
+# end: func_convert_core_path_wine_to_w32
+
+
+# func_cygpath ARGS...
+# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when
+# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2)
+# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or
+# (2), returns the Cygwin file name or path in func_cygpath_result (input
+# file name or path is assumed to be in w32 format, as previously converted
+# from $build's *nix or MSYS format). In case (3), returns the w32 file name
+# or path in func_cygpath_result (input file name or path is assumed to be in
+# Cygwin format). Returns an empty string on error.
+#
+# ARGS are passed to cygpath, with the last one being the file name or path to
+# be converted.
+#
+# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH
+# environment variable; do not put it in $PATH.
+func_cygpath ()
+{
+ $debug_cmd
+
+ if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then
+ func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null`
+ if test "$?" -ne 0; then
+ # on failure, ensure result is empty
+ func_cygpath_result=
+ fi
+ else
+ func_cygpath_result=
+ func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'"
+ fi
+}
+#end: func_cygpath
+
+
+# func_convert_core_msys_to_w32 ARG
+# Convert file name or path ARG from MSYS format to w32 format. Return
+# result in func_convert_core_msys_to_w32_result.
+func_convert_core_msys_to_w32 ()
+{
+ $debug_cmd
+
+ # awkward: cmd appends spaces to result
+ func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null |
+ $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"`
+}
+#end: func_convert_core_msys_to_w32
+
+
+# func_convert_file_check ARG1 ARG2
+# Verify that ARG1 (a file name in $build format) was converted to $host
+# format in ARG2. Otherwise, emit an error message, but continue (resetting
+# func_to_host_file_result to ARG1).
+func_convert_file_check ()
+{
+ $debug_cmd
+
+ if test -z "$2" && test -n "$1"; then
+ func_error "Could not determine host file name corresponding to"
+ func_error " '$1'"
+ func_error "Continuing, but uninstalled executables may not work."
+ # Fallback:
+ func_to_host_file_result=$1
+ fi
+}
+# end func_convert_file_check
+
+
+# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH
+# Verify that FROM_PATH (a path in $build format) was converted to $host
+# format in TO_PATH. Otherwise, emit an error message, but continue, resetting
+# func_to_host_file_result to a simplistic fallback value (see below).
+func_convert_path_check ()
+{
+ $debug_cmd
+
+ if test -z "$4" && test -n "$3"; then
+ func_error "Could not determine the host path corresponding to"
+ func_error " '$3'"
+ func_error "Continuing, but uninstalled executables may not work."
+ # Fallback. This is a deliberately simplistic "conversion" and
+ # should not be "improved". See libtool.info.
+ if test "x$1" != "x$2"; then
+ lt_replace_pathsep_chars="s|$1|$2|g"
+ func_to_host_path_result=`echo "$3" |
+ $SED -e "$lt_replace_pathsep_chars"`
+ else
+ func_to_host_path_result=$3
+ fi
+ fi
+}
+# end func_convert_path_check
+
+
+# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG
+# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT
+# and appending REPL if ORIG matches BACKPAT.
+func_convert_path_front_back_pathsep ()
+{
+ $debug_cmd
+
+ case $4 in
+ $1 ) func_to_host_path_result=$3$func_to_host_path_result
+ ;;
+ esac
+ case $4 in
+ $2 ) func_append func_to_host_path_result "$3"
+ ;;
+ esac
+}
+# end func_convert_path_front_back_pathsep
+
+
+##################################################
+# $build to $host FILE NAME CONVERSION FUNCTIONS #
+##################################################
+# invoked via '$to_host_file_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# Result will be available in $func_to_host_file_result.
+
+
+# func_to_host_file ARG
+# Converts the file name ARG from $build format to $host format. Return result
+# in func_to_host_file_result.
+func_to_host_file ()
+{
+ $debug_cmd
+
+ $to_host_file_cmd "$1"
+}
+# end func_to_host_file
+
+
+# func_to_tool_file ARG LAZY
+# converts the file name ARG from $build format to toolchain format. Return
+# result in func_to_tool_file_result. If the conversion in use is listed
+# in (the comma separated) LAZY, no conversion takes place.
+func_to_tool_file ()
+{
+ $debug_cmd
+
+ case ,$2, in
+ *,"$to_tool_file_cmd",*)
+ func_to_tool_file_result=$1
+ ;;
+ *)
+ $to_tool_file_cmd "$1"
+ func_to_tool_file_result=$func_to_host_file_result
+ ;;
+ esac
+}
+# end func_to_tool_file
+
+
+# func_convert_file_noop ARG
+# Copy ARG to func_to_host_file_result.
+func_convert_file_noop ()
+{
+ func_to_host_file_result=$1
+}
+# end func_convert_file_noop
+
+
+# func_convert_file_msys_to_w32 ARG
+# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper. Returns result in
+# func_to_host_file_result.
+func_convert_file_msys_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ func_convert_core_msys_to_w32 "$1"
+ func_to_host_file_result=$func_convert_core_msys_to_w32_result
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_w32
+
+
+# func_convert_file_cygwin_to_w32 ARG
+# Convert file name ARG from Cygwin to w32 format. Returns result in
+# func_to_host_file_result.
+func_convert_file_cygwin_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ # because $build is cygwin, we call "the" cygpath in $PATH; no need to use
+ # LT_CYGPATH in this case.
+ func_to_host_file_result=`cygpath -m "$1"`
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_cygwin_to_w32
+
+
+# func_convert_file_nix_to_w32 ARG
+# Convert file name ARG from *nix to w32 format. Requires a wine environment
+# and a working winepath. Returns result in func_to_host_file_result.
+func_convert_file_nix_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ func_convert_core_file_wine_to_w32 "$1"
+ func_to_host_file_result=$func_convert_core_file_wine_to_w32_result
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_w32
+
+
+# func_convert_file_msys_to_cygwin ARG
+# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_file_msys_to_cygwin ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ func_convert_core_msys_to_w32 "$1"
+ func_cygpath -u "$func_convert_core_msys_to_w32_result"
+ func_to_host_file_result=$func_cygpath_result
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_cygwin
+
+
+# func_convert_file_nix_to_cygwin ARG
+# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed
+# in a wine environment, working winepath, and LT_CYGPATH set. Returns result
+# in func_to_host_file_result.
+func_convert_file_nix_to_cygwin ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ # convert from *nix to w32, then use cygpath to convert from w32 to cygwin.
+ func_convert_core_file_wine_to_w32 "$1"
+ func_cygpath -u "$func_convert_core_file_wine_to_w32_result"
+ func_to_host_file_result=$func_cygpath_result
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_cygwin
+
+
+#############################################
+# $build to $host PATH CONVERSION FUNCTIONS #
+#############################################
+# invoked via '$to_host_path_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# The result will be available in $func_to_host_path_result.
+#
+# Path separators are also converted from $build format to $host format. If
+# ARG begins or ends with a path separator character, it is preserved (but
+# converted to $host format) on output.
+#
+# All path conversion functions are named using the following convention:
+# file name conversion function : func_convert_file_X_to_Y ()
+# path conversion function : func_convert_path_X_to_Y ()
+# where, for any given $build/$host combination the 'X_to_Y' value is the
+# same. If conversion functions are added for new $build/$host combinations,
+# the two new functions must follow this pattern, or func_init_to_host_path_cmd
+# will break.
+
+
+# func_init_to_host_path_cmd
+# Ensures that function "pointer" variable $to_host_path_cmd is set to the
+# appropriate value, based on the value of $to_host_file_cmd.
+to_host_path_cmd=
+func_init_to_host_path_cmd ()
+{
+ $debug_cmd
+
+ if test -z "$to_host_path_cmd"; then
+ func_stripname 'func_convert_file_' '' "$to_host_file_cmd"
+ to_host_path_cmd=func_convert_path_$func_stripname_result
+ fi
+}
+
+
+# func_to_host_path ARG
+# Converts the path ARG from $build format to $host format. Return result
+# in func_to_host_path_result.
+func_to_host_path ()
+{
+ $debug_cmd
+
+ func_init_to_host_path_cmd
+ $to_host_path_cmd "$1"
+}
+# end func_to_host_path
+
+
+# func_convert_path_noop ARG
+# Copy ARG to func_to_host_path_result.
+func_convert_path_noop ()
+{
+ func_to_host_path_result=$1
+}
+# end func_convert_path_noop
+
+
+# func_convert_path_msys_to_w32 ARG
+# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper. Returns result in
+# func_to_host_path_result.
+func_convert_path_msys_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # Remove leading and trailing path separator characters from ARG. MSYS
+ # behavior is inconsistent here; cygpath turns them into '.;' and ';.';
+ # and winepath ignores them completely.
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+ func_to_host_path_result=$func_convert_core_msys_to_w32_result
+ func_convert_path_check : ";" \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+ fi
+}
+# end func_convert_path_msys_to_w32
+
+
+# func_convert_path_cygwin_to_w32 ARG
+# Convert path ARG from Cygwin to w32 format. Returns result in
+# func_to_host_file_result.
+func_convert_path_cygwin_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # See func_convert_path_msys_to_w32:
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"`
+ func_convert_path_check : ";" \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+ fi
+}
+# end func_convert_path_cygwin_to_w32
+
+
+# func_convert_path_nix_to_w32 ARG
+# Convert path ARG from *nix to w32 format. Requires a wine environment and
+# a working winepath. Returns result in func_to_host_file_result.
+func_convert_path_nix_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # See func_convert_path_msys_to_w32:
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+ func_to_host_path_result=$func_convert_core_path_wine_to_w32_result
+ func_convert_path_check : ";" \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+ fi
+}
+# end func_convert_path_nix_to_w32
+
+
+# func_convert_path_msys_to_cygwin ARG
+# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_path_msys_to_cygwin ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # See func_convert_path_msys_to_w32:
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+ func_cygpath -u -p "$func_convert_core_msys_to_w32_result"
+ func_to_host_path_result=$func_cygpath_result
+ func_convert_path_check : : \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+ fi
+}
+# end func_convert_path_msys_to_cygwin
+
+
+# func_convert_path_nix_to_cygwin ARG
+# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a
+# a wine environment, working winepath, and LT_CYGPATH set. Returns result in
+# func_to_host_file_result.
+func_convert_path_nix_to_cygwin ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # Remove leading and trailing path separator characters from
+ # ARG. msys behavior is inconsistent here, cygpath turns them
+ # into '.;' and ';.', and winepath ignores them completely.
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+ func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result"
+ func_to_host_path_result=$func_cygpath_result
+ func_convert_path_check : : \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+ fi
+}
+# end func_convert_path_nix_to_cygwin
+
+
+# func_dll_def_p FILE
+# True iff FILE is a Windows DLL '.def' file.
+# Keep in sync with _LT_DLL_DEF_P in libtool.m4
+func_dll_def_p ()
+{
+ $debug_cmd
+
+ func_dll_def_p_tmp=`$SED -n \
+ -e 's/^[ ]*//' \
+ -e '/^\(;.*\)*$/d' \
+ -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \
+ -e q \
+ "$1"`
+ test DEF = "$func_dll_def_p_tmp"
+}
+
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+ $debug_cmd
+
+ # Get the compilation command and the source file.
+ base_compile=
+ srcfile=$nonopt # always keep a non-empty value in "srcfile"
+ suppress_opt=yes
+ suppress_output=
+ arg_mode=normal
+ libobj=
+ later=
+ pie_flag=
+
+ for arg
+ do
+ case $arg_mode in
+ arg )
+ # do not "continue". Instead, add this to base_compile
+ lastarg=$arg
+ arg_mode=normal
+ ;;
+
+ target )
+ libobj=$arg
+ arg_mode=normal
+ continue
+ ;;
+
+ normal )
+ # Accept any command-line options.
+ case $arg in
+ -o)
+ test -n "$libobj" && \
+ func_fatal_error "you cannot specify '-o' more than once"
+ arg_mode=target
+ continue
+ ;;
+
+ -pie | -fpie | -fPIE)
+ func_append pie_flag " $arg"
+ continue
+ ;;
+
+ -shared | -static | -prefer-pic | -prefer-non-pic)
+ func_append later " $arg"
+ continue
+ ;;
+
+ -no-suppress)
+ suppress_opt=no
+ continue
+ ;;
+
+ -Xcompiler)
+ arg_mode=arg # the next one goes into the "base_compile" arg list
+ continue # The current "srcfile" will either be retained or
+ ;; # replaced later. I would guess that would be a bug.
+
+ -Wc,*)
+ func_stripname '-Wc,' '' "$arg"
+ args=$func_stripname_result
+ lastarg=
+ save_ifs=$IFS; IFS=,
+ for arg in $args; do
+ IFS=$save_ifs
+ func_append_quoted lastarg "$arg"
+ done
+ IFS=$save_ifs
+ func_stripname ' ' '' "$lastarg"
+ lastarg=$func_stripname_result
+
+ # Add the arguments to base_compile.
+ func_append base_compile " $lastarg"
+ continue
+ ;;
+
+ *)
+ # Accept the current argument as the source file.
+ # The previous "srcfile" becomes the current argument.
+ #
+ lastarg=$srcfile
+ srcfile=$arg
+ ;;
+ esac # case $arg
+ ;;
+ esac # case $arg_mode
+
+ # Aesthetically quote the previous argument.
+ func_append_quoted base_compile "$lastarg"
+ done # for arg
+
+ case $arg_mode in
+ arg)
+ func_fatal_error "you must specify an argument for -Xcompile"
+ ;;
+ target)
+ func_fatal_error "you must specify a target with '-o'"
+ ;;
+ *)
+ # Get the name of the library object.
+ test -z "$libobj" && {
+ func_basename "$srcfile"
+ libobj=$func_basename_result
+ }
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ case $libobj in
+ *.[cCFSifmso] | \
+ *.ada | *.adb | *.ads | *.asm | \
+ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
+ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup)
+ func_xform "$libobj"
+ libobj=$func_xform_result
+ ;;
+ esac
+
+ case $libobj in
+ *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
+ *)
+ func_fatal_error "cannot determine name of library object from '$libobj'"
+ ;;
+ esac
+
+ func_infer_tag $base_compile
+
+ for arg in $later; do
+ case $arg in
+ -shared)
+ test yes = "$build_libtool_libs" \
+ || func_fatal_configuration "cannot build a shared library"
+ build_old_libs=no
+ continue
+ ;;
+
+ -static)
+ build_libtool_libs=no
+ build_old_libs=yes
+ continue
+ ;;
+
+ -prefer-pic)
+ pic_mode=yes
+ continue
+ ;;
+
+ -prefer-non-pic)
+ pic_mode=no
+ continue
+ ;;
+ esac
+ done
+
+ func_quote_arg pretty "$libobj"
+ test "X$libobj" != "X$func_quote_arg_result" \
+ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \
+ && func_warning "libobj name '$libobj' may not contain shell special characters."
+ func_dirname_and_basename "$obj" "/" ""
+ objname=$func_basename_result
+ xdir=$func_dirname_result
+ lobj=$xdir$objdir/$objname
+
+ test -z "$base_compile" && \
+ func_fatal_help "you must specify a compilation command"
+
+ # Delete any leftover library objects.
+ if test yes = "$build_old_libs"; then
+ removelist="$obj $lobj $libobj ${libobj}T"
+ else
+ removelist="$lobj $libobj ${libobj}T"
+ fi
+
+ # On Cygwin there's no "real" PIC flag so we must build both object types
+ case $host_os in
+ cygwin* | mingw* | pw32* | os2* | cegcc*)
+ pic_mode=default
+ ;;
+ esac
+ if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then
+ # non-PIC code in shared libraries is not supported
+ pic_mode=default
+ fi
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test no = "$compiler_c_o"; then
+ output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext
+ lockfile=$output_obj.lock
+ else
+ output_obj=
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test yes = "$need_locks"; then
+ until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+ func_echo "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test warn = "$need_locks"; then
+ if test -f "$lockfile"; then
+ $ECHO "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support '-c' and '-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $opt_dry_run || $RM $removelist
+ exit $EXIT_FAILURE
+ fi
+ func_append removelist " $output_obj"
+ $ECHO "$srcfile" > "$lockfile"
+ fi
+
+ $opt_dry_run || $RM $removelist
+ func_append removelist " $lockfile"
+ trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
+
+ func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
+ srcfile=$func_to_tool_file_result
+ func_quote_arg pretty "$srcfile"
+ qsrcfile=$func_quote_arg_result
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test yes = "$build_libtool_libs"; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ if test no != "$pic_mode"; then
+ command="$base_compile $qsrcfile $pic_flag"
+ else
+ # Don't build PIC code
+ command="$base_compile $qsrcfile"
+ fi
+
+ func_mkdir_p "$xdir$objdir"
+
+ if test -z "$output_obj"; then
+ # Place PIC objects in $objdir
+ func_append command " -o $lobj"
+ fi
+
+ func_show_eval_locale "$command" \
+ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
+
+ if test warn = "$need_locks" &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support '-c' and '-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $opt_dry_run || $RM $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+ func_show_eval '$MV "$output_obj" "$lobj"' \
+ 'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+ fi
+
+ # Allow error messages only from the first compilation.
+ if test yes = "$suppress_opt"; then
+ suppress_output=' >/dev/null 2>&1'
+ fi
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test yes = "$build_old_libs"; then
+ if test yes != "$pic_mode"; then
+ # Don't build PIC code
+ command="$base_compile $qsrcfile$pie_flag"
+ else
+ command="$base_compile $qsrcfile $pic_flag"
+ fi
+ if test yes = "$compiler_c_o"; then
+ func_append command " -o $obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ func_append command "$suppress_output"
+ func_show_eval_locale "$command" \
+ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
+
+ if test warn = "$need_locks" &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support '-c' and '-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $opt_dry_run || $RM $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed
+ if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+ func_show_eval '$MV "$output_obj" "$obj"' \
+ 'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+ fi
+ fi
+
+ $opt_dry_run || {
+ func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
+
+ # Unlock the critical section if it was locked
+ if test no != "$need_locks"; then
+ removelist=$lockfile
+ $RM "$lockfile"
+ fi
+ }
+
+ exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+ test compile = "$opt_mode" && func_mode_compile ${1+"$@"}
+}
+
+func_mode_help ()
+{
+ # We need to display help for each of the modes.
+ case $opt_mode in
+ "")
+ # Generic help is extracted from the usage comments
+ # at the start of this file.
+ func_help
+ ;;
+
+ clean)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+ compile)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -no-suppress do not suppress compiler output for multiple passes
+ -prefer-pic try to build PIC objects only
+ -prefer-non-pic try to build non-PIC objects only
+ -shared do not build a '.o' file suitable for static linking
+ -static only build a '.o' file suitable for static linking
+ -Wc,FLAG
+ -Xcompiler FLAG pass FLAG directly to the compiler
+
+COMPILE-COMMAND is a command to be used in creating a 'standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix '.c' with the
+library object suffix, '.lo'."
+ ;;
+
+ execute)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to '-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+ finish)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the '--dry-run' option if you just want to see what would be executed."
+ ;;
+
+ install)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the 'install' or 'cp' program.
+
+The following components of INSTALL-COMMAND are treated specially:
+
+ -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+ link)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -bindir BINDIR specify path to binaries directory (for systems where
+ libraries must be found in the PATH setting at runtime)
+ -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-fast-install disable the fast-install mode
+ -no-install link a not-installable executable
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -objectlist FILE use a list of object files found in FILE to specify objects
+ -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes)
+ -precious-files-regex REGEX
+ don't remove output files matching REGEX
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -shared only do dynamic linking of libtool libraries
+ -shrext SUFFIX override the standard shared library file extension
+ -static do not do any dynamic linking of uninstalled libtool libraries
+ -static-libtool-libs
+ do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+ -weak LIBNAME declare that the target provides the LIBNAME interface
+ -Wc,FLAG
+ -Xcompiler FLAG pass linker-specific FLAG directly to the compiler
+ -Wa,FLAG
+ -Xassembler FLAG pass linker-specific FLAG directly to the assembler
+ -Wl,FLAG
+ -Xlinker FLAG pass linker-specific FLAG directly to the linker
+ -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC)
+
+All other options (arguments beginning with '-') are ignored.
+
+Every other argument is treated as a filename. Files ending in '.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in '.la', then a libtool library is created,
+only library objects ('.lo' files) may be specified, and '-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created
+using 'ar' and 'ranlib', or on Windows using 'lib'.
+
+If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+ uninstall)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+ *)
+ func_fatal_help "invalid operation mode '$opt_mode'"
+ ;;
+ esac
+
+ echo
+ $ECHO "Try '$progname --help' for more information about other modes."
+}
+
+# Now that we've collected a possible --mode arg, show help if necessary
+if $opt_help; then
+ if test : = "$opt_help"; then
+ func_mode_help
+ else
+ {
+ func_help noexit
+ for opt_mode in compile link execute install finish uninstall clean; do
+ func_mode_help
+ done
+ } | $SED -n '1p; 2,$s/^Usage:/ or: /p'
+ {
+ func_help noexit
+ for opt_mode in compile link execute install finish uninstall clean; do
+ echo
+ func_mode_help
+ done
+ } |
+ $SED '1d
+ /^When reporting/,/^Report/{
+ H
+ d
+ }
+ $x
+ /information about other modes/d
+ /more detailed .*MODE/d
+ s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/'
+ fi
+ exit $?
+fi
+
+
+# func_mode_execute arg...
+func_mode_execute ()
+{
+ $debug_cmd
+
+ # The first argument is the command name.
+ cmd=$nonopt
+ test -z "$cmd" && \
+ func_fatal_help "you must specify a COMMAND"
+
+ # Handle -dlopen flags immediately.
+ for file in $opt_dlopen; do
+ test -f "$file" \
+ || func_fatal_help "'$file' is not a file"
+
+ dir=
+ case $file in
+ *.la)
+ func_resolve_sysroot "$file"
+ file=$func_resolve_sysroot_result
+
+ # Check to see that this really is a libtool archive.
+ func_lalib_unsafe_p "$file" \
+ || func_fatal_help "'$lib' is not a valid libtool archive"
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+ func_source "$file"
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && \
+ func_warning "'$file' was not linked with '-export-dynamic'"
+ continue
+ fi
+
+ func_dirname "$file" "" "."
+ dir=$func_dirname_result
+
+ if test -f "$dir/$objdir/$dlname"; then
+ func_append dir "/$objdir"
+ else
+ if test ! -f "$dir/$dlname"; then
+ func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'"
+ fi
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ func_dirname "$file" "" "."
+ dir=$func_dirname_result
+ ;;
+
+ *)
+ func_warning "'-dlopen' is ignored for non-libtool libraries and objects"
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir=$absdir
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic=$magic
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case $file in
+ -* | *.la | *.lo ) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if func_ltwrapper_script_p "$file"; then
+ func_source "$file"
+ # Transform arg to wrapped name.
+ file=$progdir/$program
+ elif func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_scriptname "$file"
+ func_source "$func_ltwrapper_scriptname_result"
+ # Transform arg to wrapped name.
+ file=$progdir/$program
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ func_append_quoted args "$file"
+ done
+
+ if $opt_dry_run; then
+ # Display what would be done.
+ if test -n "$shlibpath_var"; then
+ eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
+ echo "export $shlibpath_var"
+ fi
+ $ECHO "$cmd$args"
+ exit $EXIT_SUCCESS
+ else
+ if test -n "$shlibpath_var"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+ fi
+
+ # Restore saved environment variables
+ for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+ do
+ eval "if test \"\${save_$lt_var+set}\" = set; then
+ $lt_var=\$save_$lt_var; export $lt_var
+ else
+ $lt_unset $lt_var
+ fi"
+ done
+
+ # Now prepare to actually exec the command.
+ exec_cmd=\$cmd$args
+ fi
+}
+
+test execute = "$opt_mode" && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+ $debug_cmd
+
+ libs=
+ libdirs=
+ admincmds=
+
+ for opt in "$nonopt" ${1+"$@"}
+ do
+ if test -d "$opt"; then
+ func_append libdirs " $opt"
+
+ elif test -f "$opt"; then
+ if func_lalib_unsafe_p "$opt"; then
+ func_append libs " $opt"
+ else
+ func_warning "'$opt' is not a valid libtool archive"
+ fi
+
+ else
+ func_fatal_error "invalid argument '$opt'"
+ fi
+ done
+
+ if test -n "$libs"; then
+ if test -n "$lt_sysroot"; then
+ sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"`
+ sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;"
+ else
+ sysroot_cmd=
+ fi
+
+ # Remove sysroot references
+ if $opt_dry_run; then
+ for lib in $libs; do
+ echo "removing references to $lt_sysroot and '=' prefixes from $lib"
+ done
+ else
+ tmpdir=`func_mktempdir`
+ for lib in $libs; do
+ $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \
+ > $tmpdir/tmp-la
+ mv -f $tmpdir/tmp-la $lib
+ done
+ ${RM}r "$tmpdir"
+ fi
+ fi
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
+'"$cmd"'"'
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $opt_dry_run || eval "$cmds" || func_append admincmds "
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ $opt_quiet && exit $EXIT_SUCCESS
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ echo "----------------------------------------------------------------------"
+ echo "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ $ECHO " $libdir"
+ done
+ echo
+ echo "If you ever happen to want to link against installed libraries"
+ echo "in a given directory, LIBDIR, you must either use libtool, and"
+ echo "specify the full pathname of the library, or use the '-LLIBDIR'"
+ echo "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ echo " - add LIBDIR to the '$shlibpath_var' environment variable"
+ echo " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ echo " - add LIBDIR to the '$runpath_var' environment variable"
+ echo " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ $ECHO " - use the '$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ $ECHO " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'"
+ fi
+ echo
+
+ echo "See any operating system documentation about shared libraries for"
+ case $host in
+ solaris2.[6789]|solaris2.1[0-9])
+ echo "more information, such as the ld(1), crle(1) and ld.so(8) manual"
+ echo "pages."
+ ;;
+ *)
+ echo "more information, such as the ld(1) and ld.so(8) manual pages."
+ ;;
+ esac
+ echo "----------------------------------------------------------------------"
+ fi
+ exit $EXIT_SUCCESS
+}
+
+test finish = "$opt_mode" && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+ $debug_cmd
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" ||
+ # Allow the use of GNU shtool's install command.
+ case $nonopt in *shtool*) :;; *) false;; esac
+ then
+ # Aesthetically quote it.
+ func_quote_arg pretty "$nonopt"
+ install_prog="$func_quote_arg_result "
+ arg=$1
+ shift
+ else
+ install_prog=
+ arg=$nonopt
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ func_quote_arg pretty "$arg"
+ func_append install_prog "$func_quote_arg_result"
+ install_shared_prog=$install_prog
+ case " $install_prog " in
+ *[\\\ /]cp\ *) install_cp=: ;;
+ *) install_cp=false ;;
+ esac
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=false
+ stripme=
+ no_mode=:
+ for arg
+ do
+ arg2=
+ if test -n "$dest"; then
+ func_append files " $dest"
+ dest=$arg
+ continue
+ fi
+
+ case $arg in
+ -d) isdir=: ;;
+ -f)
+ if $install_cp; then :; else
+ prev=$arg
+ fi
+ ;;
+ -g | -m | -o)
+ prev=$arg
+ ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*)
+ ;;
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ if test X-m = "X$prev" && test -n "$install_override_mode"; then
+ arg2=$install_override_mode
+ no_mode=false
+ fi
+ prev=
+ else
+ dest=$arg
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ func_quote_arg pretty "$arg"
+ func_append install_prog " $func_quote_arg_result"
+ if test -n "$arg2"; then
+ func_quote_arg pretty "$arg2"
+ fi
+ func_append install_shared_prog " $func_quote_arg_result"
+ done
+
+ test -z "$install_prog" && \
+ func_fatal_help "you must specify an install program"
+
+ test -n "$prev" && \
+ func_fatal_help "the '$prev' option requires an argument"
+
+ if test -n "$install_override_mode" && $no_mode; then
+ if $install_cp; then :; else
+ func_quote_arg pretty "$install_override_mode"
+ func_append install_shared_prog " -m $func_quote_arg_result"
+ fi
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ func_fatal_help "no file or destination specified"
+ else
+ func_fatal_help "you must specify a destination"
+ fi
+ fi
+
+ # Strip any trailing slash from the destination.
+ func_stripname '' '/' "$dest"
+ dest=$func_stripname_result
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=:
+ if $isdir; then
+ destdir=$dest
+ destname=
+ else
+ func_dirname_and_basename "$dest" "" "."
+ destdir=$func_dirname_result
+ destname=$func_basename_result
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files; shift
+ test "$#" -gt 1 && \
+ func_fatal_help "'$dest' is not a directory"
+ fi
+ case $destdir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case $file in
+ *.lo) ;;
+ *)
+ func_fatal_help "'$destdir' must be an absolute directory name"
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic=$magic
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case $file in
+ *.$libext)
+ # Do the static libraries later.
+ func_append staticlibs " $file"
+ ;;
+
+ *.la)
+ func_resolve_sysroot "$file"
+ file=$func_resolve_sysroot_result
+
+ # Check to see that this really is a libtool archive.
+ func_lalib_unsafe_p "$file" \
+ || func_fatal_help "'$file' is not a valid libtool archive"
+
+ library_names=
+ old_library=
+ relink_command=
+ func_source "$file"
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) func_append current_libdirs " $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) func_append future_libdirs " $libdir" ;;
+ esac
+ fi
+
+ func_dirname "$file" "/" ""
+ dir=$func_dirname_result
+ func_append dir "$objdir"
+
+ if test -n "$relink_command"; then
+ # Determine the prefix the user has applied to our future dir.
+ inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+ # are installed to the same prefix.
+ # At present, this check doesn't affect windows .dll's that
+ # are installed into $libdir/../bin (currently, that works fine)
+ # but it's something to keep an eye on.
+ test "$inst_prefix_dir" = "$destdir" && \
+ func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir"
+
+ if test -n "$inst_prefix_dir"; then
+ # Stick the inst_prefix_dir data into the link command.
+ relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+ else
+ relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+ fi
+
+ func_warning "relinking '$file'"
+ func_show_eval "$relink_command" \
+ 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"'
+ fi
+
+ # See the names of the shared library.
+ set dummy $library_names; shift
+ if test -n "$1"; then
+ realname=$1
+ shift
+
+ srcname=$realname
+ test -n "$relink_command" && srcname=${realname}T
+
+ # Install the shared library and build the symlinks.
+ func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \
+ 'exit $?'
+ tstripme=$stripme
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ case $realname in
+ *.dll.a)
+ tstripme=
+ ;;
+ esac
+ ;;
+ os2*)
+ case $realname in
+ *_dll.a)
+ tstripme=
+ ;;
+ esac
+ ;;
+ esac
+ if test -n "$tstripme" && test -n "$striplib"; then
+ func_show_eval "$striplib $destdir/$realname" 'exit $?'
+ fi
+
+ if test "$#" -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ # Try 'ln -sf' first, because the 'ln' binary might depend on
+ # the symlink we replace! Solaris /bin/ln does not understand -f,
+ # so we also need to try rm && ln -s.
+ for linkname
+ do
+ test "$linkname" != "$realname" \
+ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib=$destdir/$realname
+ func_execute_cmds "$postinstall_cmds" 'exit $?'
+ fi
+
+ # Install the pseudo-library for information purposes.
+ func_basename "$file"
+ name=$func_basename_result
+ instname=$dir/${name}i
+ func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && func_append staticlibs " $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile=$destdir/$destname
+ else
+ func_basename "$file"
+ destfile=$func_basename_result
+ destfile=$destdir/$destfile
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case $destfile in
+ *.lo)
+ func_lo2o "$destfile"
+ staticdest=$func_lo2o_result
+ ;;
+ *.$objext)
+ staticdest=$destfile
+ destfile=
+ ;;
+ *)
+ func_fatal_help "cannot copy a libtool object to '$destfile'"
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ test -n "$destfile" && \
+ func_show_eval "$install_prog $file $destfile" 'exit $?'
+
+ # Install the old object if enabled.
+ if test yes = "$build_old_libs"; then
+ # Deduce the name of the old-style object file.
+ func_lo2o "$file"
+ staticobj=$func_lo2o_result
+ func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile=$destdir/$destname
+ else
+ func_basename "$file"
+ destfile=$func_basename_result
+ destfile=$destdir/$destfile
+ fi
+
+ # If the file is missing, and there is a .exe on the end, strip it
+ # because it is most likely a libtool script we actually want to
+ # install
+ stripped_ext=
+ case $file in
+ *.exe)
+ if test ! -f "$file"; then
+ func_stripname '' '.exe' "$file"
+ file=$func_stripname_result
+ stripped_ext=.exe
+ fi
+ ;;
+ esac
+
+ # Do a test to see if this is really a libtool program.
+ case $host in
+ *cygwin* | *mingw*)
+ if func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_scriptname "$file"
+ wrapper=$func_ltwrapper_scriptname_result
+ else
+ func_stripname '' '.exe' "$file"
+ wrapper=$func_stripname_result
+ fi
+ ;;
+ *)
+ wrapper=$file
+ ;;
+ esac
+ if func_ltwrapper_script_p "$wrapper"; then
+ notinst_deplibs=
+ relink_command=
+
+ func_source "$wrapper"
+
+ # Check the variables that should have been set.
+ test -z "$generated_by_libtool_version" && \
+ func_fatal_error "invalid libtool wrapper script '$wrapper'"
+
+ finalize=:
+ for lib in $notinst_deplibs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ func_source "$lib"
+ fi
+ libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'`
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ func_warning "'$lib' has not been installed in '$libdir'"
+ finalize=false
+ fi
+ done
+
+ relink_command=
+ func_source "$wrapper"
+
+ outputname=
+ if test no = "$fast_install" && test -n "$relink_command"; then
+ $opt_dry_run || {
+ if $finalize; then
+ tmpdir=`func_mktempdir`
+ func_basename "$file$stripped_ext"
+ file=$func_basename_result
+ outputname=$tmpdir/$file
+ # Replace the output file specification.
+ relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
+
+ $opt_quiet || {
+ func_quote_arg expand,pretty "$relink_command"
+ eval "func_echo $func_quote_arg_result"
+ }
+ if eval "$relink_command"; then :
+ else
+ func_error "error: relink '$file' with the above command before installing it"
+ $opt_dry_run || ${RM}r "$tmpdir"
+ continue
+ fi
+ file=$outputname
+ else
+ func_warning "cannot relink '$file'"
+ fi
+ }
+ else
+ # Install the binary that we compiled earlier.
+ file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ # remove .exe since cygwin /usr/bin/install will append another
+ # one anyway
+ case $install_prog,$host in
+ */usr/bin/install*,*cygwin*)
+ case $file:$destfile in
+ *.exe:*.exe)
+ # this is ok
+ ;;
+ *.exe:*)
+ destfile=$destfile.exe
+ ;;
+ *:*.exe)
+ func_stripname '' '.exe' "$destfile"
+ destfile=$func_stripname_result
+ ;;
+ esac
+ ;;
+ esac
+ func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
+ $opt_dry_run || if test -n "$outputname"; then
+ ${RM}r "$tmpdir"
+ fi
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ func_basename "$file"
+ name=$func_basename_result
+
+ # Set up the ranlib parameters.
+ oldlib=$destdir/$name
+ func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
+ tool_oldlib=$func_to_tool_file_result
+
+ func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
+
+ if test -n "$stripme" && test -n "$old_striplib"; then
+ func_show_eval "$old_striplib $tool_oldlib" 'exit $?'
+ fi
+
+ # Do each command in the postinstall commands.
+ func_execute_cmds "$old_postinstall_cmds" 'exit $?'
+ done
+
+ test -n "$future_libdirs" && \
+ func_warning "remember to run '$progname --finish$future_libdirs'"
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ $opt_dry_run && current_libdirs=" -n$current_libdirs"
+ exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs'
+ else
+ exit $EXIT_SUCCESS
+ fi
+}
+
+test install = "$opt_mode" && func_mode_install ${1+"$@"}
+
+
+# func_generate_dlsyms outputname originator pic_p
+# Extract symbols from dlprefiles and create ${outputname}S.o with
+# a dlpreopen symbol table.
+func_generate_dlsyms ()
+{
+ $debug_cmd
+
+ my_outputname=$1
+ my_originator=$2
+ my_pic_p=${3-false}
+ my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'`
+ my_dlsyms=
+
+ if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ my_dlsyms=${my_outputname}S.c
+ else
+ func_error "not configured to extract global symbols from dlpreopened files"
+ fi
+ fi
+
+ if test -n "$my_dlsyms"; then
+ case $my_dlsyms in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist=$output_objdir/$my_outputname.nm
+
+ func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
+
+ # Parse the name list into a source file.
+ func_verbose "creating $output_objdir/$my_dlsyms"
+
+ $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
+/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */
+/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))
+#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
+#endif
+
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
+#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+/* DATA imports from DLLs on WIN32 can't be const, because runtime
+ relocations are performed -- see ld's documentation on pseudo-relocs. */
+# define LT_DLSYM_CONST
+#elif defined __osf__
+/* This system does not cope well with relocations in const data. */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0)
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test yes = "$dlself"; then
+ func_verbose "generating symbol list for '$output'"
+
+ $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+ for progfile in $progfiles; do
+ func_to_tool_file "$progfile" func_convert_file_msys_to_w32
+ func_verbose "extracting global C symbols from '$func_to_tool_file_result'"
+ $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $opt_dry_run || {
+ eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ eval '$MV "$nlist"T "$nlist"'
+ }
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $opt_dry_run || {
+ eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ eval '$MV "$nlist"T "$nlist"'
+ }
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols=$output_objdir/$outputname.exp
+ $opt_dry_run || {
+ $RM $export_symbols
+ eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ }
+ else
+ $opt_dry_run || {
+ eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+ eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+ eval '$MV "$nlist"T "$nlist"'
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ }
+ fi
+ fi
+
+ for dlprefile in $dlprefiles; do
+ func_verbose "extracting global C symbols from '$dlprefile'"
+ func_basename "$dlprefile"
+ name=$func_basename_result
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ # if an import library, we need to obtain dlname
+ if func_win32_import_lib_p "$dlprefile"; then
+ func_tr_sh "$dlprefile"
+ eval "curr_lafile=\$libfile_$func_tr_sh_result"
+ dlprefile_dlbasename=
+ if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then
+ # Use subshell, to avoid clobbering current variable values
+ dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"`
+ if test -n "$dlprefile_dlname"; then
+ func_basename "$dlprefile_dlname"
+ dlprefile_dlbasename=$func_basename_result
+ else
+ # no lafile. user explicitly requested -dlpreopen .
+ $sharedlib_from_linklib_cmd "$dlprefile"
+ dlprefile_dlbasename=$sharedlib_from_linklib_result
+ fi
+ fi
+ $opt_dry_run || {
+ if test -n "$dlprefile_dlbasename"; then
+ eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"'
+ else
+ func_warning "Could not compute DLL name from $name"
+ eval '$ECHO ": $name " >> "$nlist"'
+ fi
+ func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+ eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe |
+ $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'"
+ }
+ else # not an import lib
+ $opt_dry_run || {
+ eval '$ECHO ": $name " >> "$nlist"'
+ func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+ eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+ }
+ fi
+ ;;
+ *)
+ $opt_dry_run || {
+ eval '$ECHO ": $name " >> "$nlist"'
+ func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+ eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+ }
+ ;;
+ esac
+ done
+
+ $opt_dry_run || {
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $MV "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if $GREP -v "^: " < "$nlist" |
+ if sort -k 3 /dev/null 2>&1; then
+ sort -k 3
+ else
+ sort +2
+ fi |
+ uniq > "$nlist"S; then
+ :
+ else
+ $GREP -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
+ else
+ echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
+ fi
+
+ func_show_eval '$RM "${nlist}I"'
+ if test -n "$global_symbol_to_import"; then
+ eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I'
+ fi
+
+ echo >> "$output_objdir/$my_dlsyms" "\
+
+/* The mapping between symbol names and symbols. */
+typedef struct {
+ const char *name;
+ void *address;
+} lt_dlsymlist;
+extern LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[];\
+"
+
+ if test -s "$nlist"I; then
+ echo >> "$output_objdir/$my_dlsyms" "\
+static void lt_syminit(void)
+{
+ LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols;
+ for (; symbol->name; ++symbol)
+ {"
+ $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms"
+ echo >> "$output_objdir/$my_dlsyms" "\
+ }
+}"
+ fi
+ echo >> "$output_objdir/$my_dlsyms" "\
+LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{ {\"$my_originator\", (void *) 0},"
+
+ if test -s "$nlist"I; then
+ echo >> "$output_objdir/$my_dlsyms" "\
+ {\"@INIT@\", (void *) <_syminit},"
+ fi
+
+ case $need_lib_prefix in
+ no)
+ eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
+ ;;
+ *)
+ eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
+ ;;
+ esac
+ echo >> "$output_objdir/$my_dlsyms" "\
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_${my_prefix}_LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ } # !$opt_dry_run
+
+ pic_flag_for_symtable=
+ case "$compile_command " in
+ *" -static "*) ;;
+ *)
+ case $host in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+ pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
+ *-*-hpux*)
+ pic_flag_for_symtable=" $pic_flag" ;;
+ *)
+ $my_pic_p && pic_flag_for_symtable=" $pic_flag"
+ ;;
+ esac
+ ;;
+ esac
+ symtab_cflags=
+ for arg in $LTCFLAGS; do
+ case $arg in
+ -pie | -fpie | -fPIE) ;;
+ *) func_append symtab_cflags " $arg" ;;
+ esac
+ done
+
+ # Now compile the dynamic symbol file.
+ func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
+
+ # Clean up the generated files.
+ func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"'
+
+ # Transform the symbol file into the correct name.
+ symfileobj=$output_objdir/${my_outputname}S.$objext
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ if test -f "$output_objdir/$my_outputname.def"; then
+ compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+ finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+ else
+ compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+ finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+ fi
+ ;;
+ *)
+ compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+ finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+ ;;
+ esac
+ ;;
+ *)
+ func_fatal_error "unknown suffix for '$my_dlsyms'"
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"`
+ finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"`
+ fi
+}
+
+# func_cygming_gnu_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is a GNU/binutils-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_gnu_implib_p ()
+{
+ $debug_cmd
+
+ func_to_tool_file "$1" func_convert_file_msys_to_w32
+ func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'`
+ test -n "$func_cygming_gnu_implib_tmp"
+}
+
+# func_cygming_ms_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is an MS-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_ms_implib_p ()
+{
+ $debug_cmd
+
+ func_to_tool_file "$1" func_convert_file_msys_to_w32
+ func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'`
+ test -n "$func_cygming_ms_implib_tmp"
+}
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+# Despite the name, also deal with 64 bit binaries.
+func_win32_libid ()
+{
+ $debug_cmd
+
+ win32_libid_type=unknown
+ win32_fileres=`file -L $1 2>/dev/null`
+ case $win32_fileres in
+ *ar\ archive\ import\ library*) # definitely import
+ win32_libid_type="x86 archive import"
+ ;;
+ *ar\ archive*) # could be an import, or static
+ # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD.
+ if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
+ $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
+ case $nm_interface in
+ "MS dumpbin")
+ if func_cygming_ms_implib_p "$1" ||
+ func_cygming_gnu_implib_p "$1"
+ then
+ win32_nmres=import
+ else
+ win32_nmres=
+ fi
+ ;;
+ *)
+ func_to_tool_file "$1" func_convert_file_msys_to_w32
+ win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" |
+ $SED -n -e '
+ 1,100{
+ / I /{
+ s|.*|import|
+ p
+ q
+ }
+ }'`
+ ;;
+ esac
+ case $win32_nmres in
+ import*) win32_libid_type="x86 archive import";;
+ *) win32_libid_type="x86 archive static";;
+ esac
+ fi
+ ;;
+ *DLL*)
+ win32_libid_type="x86 DLL"
+ ;;
+ *executable*) # but shell scripts are "executable" too...
+ case $win32_fileres in
+ *MS\ Windows\ PE\ Intel*)
+ win32_libid_type="x86 DLL"
+ ;;
+ esac
+ ;;
+ esac
+ $ECHO "$win32_libid_type"
+}
+
+# func_cygming_dll_for_implib ARG
+#
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+# Invoked by eval'ing the libtool variable
+# $sharedlib_from_linklib_cmd
+# Result is available in the variable
+# $sharedlib_from_linklib_result
+func_cygming_dll_for_implib ()
+{
+ $debug_cmd
+
+ sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"`
+}
+
+# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs
+#
+# The is the core of a fallback implementation of a
+# platform-specific function to extract the name of the
+# DLL associated with the specified import library LIBNAME.
+#
+# SECTION_NAME is either .idata$6 or .idata$7, depending
+# on the platform and compiler that created the implib.
+#
+# Echos the name of the DLL associated with the
+# specified import library.
+func_cygming_dll_for_implib_fallback_core ()
+{
+ $debug_cmd
+
+ match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"`
+ $OBJDUMP -s --section "$1" "$2" 2>/dev/null |
+ $SED '/^Contents of section '"$match_literal"':/{
+ # Place marker at beginning of archive member dllname section
+ s/.*/====MARK====/
+ p
+ d
+ }
+ # These lines can sometimes be longer than 43 characters, but
+ # are always uninteresting
+ /:[ ]*file format pe[i]\{,1\}-/d
+ /^In archive [^:]*:/d
+ # Ensure marker is printed
+ /^====MARK====/p
+ # Remove all lines with less than 43 characters
+ /^.\{43\}/!d
+ # From remaining lines, remove first 43 characters
+ s/^.\{43\}//' |
+ $SED -n '
+ # Join marker and all lines until next marker into a single line
+ /^====MARK====/ b para
+ H
+ $ b para
+ b
+ :para
+ x
+ s/\n//g
+ # Remove the marker
+ s/^====MARK====//
+ # Remove trailing dots and whitespace
+ s/[\. \t]*$//
+ # Print
+ /./p' |
+ # we now have a list, one entry per line, of the stringified
+ # contents of the appropriate section of all members of the
+ # archive that possess that section. Heuristic: eliminate
+ # all those that have a first or second character that is
+ # a '.' (that is, objdump's representation of an unprintable
+ # character.) This should work for all archives with less than
+ # 0x302f exports -- but will fail for DLLs whose name actually
+ # begins with a literal '.' or a single character followed by
+ # a '.'.
+ #
+ # Of those that remain, print the first one.
+ $SED -e '/^\./d;/^.\./d;q'
+}
+
+# func_cygming_dll_for_implib_fallback ARG
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+#
+# This fallback implementation is for use when $DLLTOOL
+# does not support the --identify-strict option.
+# Invoked by eval'ing the libtool variable
+# $sharedlib_from_linklib_cmd
+# Result is available in the variable
+# $sharedlib_from_linklib_result
+func_cygming_dll_for_implib_fallback ()
+{
+ $debug_cmd
+
+ if func_cygming_gnu_implib_p "$1"; then
+ # binutils import library
+ sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"`
+ elif func_cygming_ms_implib_p "$1"; then
+ # ms-generated import library
+ sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"`
+ else
+ # unknown
+ sharedlib_from_linklib_result=
+ fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+ $debug_cmd
+
+ f_ex_an_ar_dir=$1; shift
+ f_ex_an_ar_oldlib=$1
+ if test yes = "$lock_old_archive_extraction"; then
+ lockfile=$f_ex_an_ar_oldlib.lock
+ until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+ func_echo "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ fi
+ func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \
+ 'stat=$?; rm -f "$lockfile"; exit $stat'
+ if test yes = "$lock_old_archive_extraction"; then
+ $opt_dry_run || rm -f "$lockfile"
+ fi
+ if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
+ fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+ $debug_cmd
+
+ my_gentop=$1; shift
+ my_oldlibs=${1+"$@"}
+ my_oldobjs=
+ my_xlib=
+ my_xabs=
+ my_xdir=
+
+ for my_xlib in $my_oldlibs; do
+ # Extract the objects.
+ case $my_xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;;
+ *) my_xabs=`pwd`"/$my_xlib" ;;
+ esac
+ func_basename "$my_xlib"
+ my_xlib=$func_basename_result
+ my_xlib_u=$my_xlib
+ while :; do
+ case " $extracted_archives " in
+ *" $my_xlib_u "*)
+ func_arith $extracted_serial + 1
+ extracted_serial=$func_arith_result
+ my_xlib_u=lt$extracted_serial-$my_xlib ;;
+ *) break ;;
+ esac
+ done
+ extracted_archives="$extracted_archives $my_xlib_u"
+ my_xdir=$my_gentop/$my_xlib_u
+
+ func_mkdir_p "$my_xdir"
+
+ case $host in
+ *-darwin*)
+ func_verbose "Extracting $my_xabs"
+ # Do not bother doing anything if just a dry run
+ $opt_dry_run || {
+ darwin_orig_dir=`pwd`
+ cd $my_xdir || exit $?
+ darwin_archive=$my_xabs
+ darwin_curdir=`pwd`
+ func_basename "$darwin_archive"
+ darwin_base_archive=$func_basename_result
+ darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
+ if test -n "$darwin_arches"; then
+ darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
+ darwin_arch=
+ func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
+ for darwin_arch in $darwin_arches; do
+ func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch"
+ $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive"
+ cd "unfat-$$/$darwin_base_archive-$darwin_arch"
+ func_extract_an_archive "`pwd`" "$darwin_base_archive"
+ cd "$darwin_curdir"
+ $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive"
+ done # $darwin_arches
+ ## Okay now we've a bunch of thin objects, gotta fatten them up :)
+ darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u`
+ darwin_file=
+ darwin_files=
+ for darwin_file in $darwin_filelist; do
+ darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP`
+ $LIPO -create -output "$darwin_file" $darwin_files
+ done # $darwin_filelist
+ $RM -rf unfat-$$
+ cd "$darwin_orig_dir"
+ else
+ cd $darwin_orig_dir
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ fi # $darwin_arches
+ } # !$opt_dry_run
+ ;;
+ *)
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ ;;
+ esac
+ my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP`
+ done
+
+ func_extract_archives_result=$my_oldobjs
+}
+
+
+# func_emit_wrapper [arg=no]
+#
+# Emit a libtool wrapper script on stdout.
+# Don't directly open a file because we may want to
+# incorporate the script contents within a cygwin/mingw
+# wrapper executable. Must ONLY be called from within
+# func_mode_link because it depends on a number of variables
+# set therein.
+#
+# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
+# variable will take. If 'yes', then the emitted script
+# will assume that the directory where it is stored is
+# the $objdir directory. This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
+{
+ func_emit_wrapper_arg1=${1-no}
+
+ $ECHO "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variables:
+ generated_by_libtool_version='$macro_version'
+ notinst_deplibs='$notinst_deplibs'
+else
+ # When we are sourced in execute mode, \$file and \$ECHO are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ file=\"\$0\""
+
+ func_quote_arg pretty "$ECHO"
+ qECHO=$func_quote_arg_result
+ $ECHO "\
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+ ECHO=$qECHO
+ fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ that is used only on
+# windows platforms, and (c) all begin with the string "--lt-"
+# (application programs are unlikely to have options that match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's $0 value, followed by "$@".
+lt_option_debug=
+func_parse_lt_options ()
+{
+ lt_script_arg0=\$0
+ shift
+ for lt_opt
+ do
+ case \"\$lt_opt\" in
+ --lt-debug) lt_option_debug=1 ;;
+ --lt-dump-script)
+ lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\`
+ test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=.
+ lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\`
+ cat \"\$lt_dump_D/\$lt_dump_F\"
+ exit 0
+ ;;
+ --lt-*)
+ \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+
+ # Print the debug banner immediately:
+ if test -n \"\$lt_option_debug\"; then
+ echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2
+ fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+ lt_dump_args_N=1;
+ for lt_arg
+ do
+ \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\"
+ lt_dump_args_N=\`expr \$lt_dump_args_N + 1\`
+ done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+"
+ case $host in
+ # Backslashes separate directories on plain windows
+ *-*-mingw | *-*-os2* | *-cegcc*)
+ $ECHO "\
+ if test -n \"\$lt_option_debug\"; then
+ \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2
+ func_lt_dump_args \${1+\"\$@\"} 1>&2
+ fi
+ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+ ;;
+
+ *)
+ $ECHO "\
+ if test -n \"\$lt_option_debug\"; then
+ \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2
+ func_lt_dump_args \${1+\"\$@\"} 1>&2
+ fi
+ exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $ECHO "\
+ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+ exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from \$@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+ case \" \$* \" in
+ *\\ --lt-*)
+ for lt_wr_arg
+ do
+ case \$lt_wr_arg in
+ --lt-*) ;;
+ *) set x \"\$@\" \"\$lt_wr_arg\"; shift;;
+ esac
+ shift
+ done ;;
+ esac
+ func_exec_program_core \${1+\"\$@\"}
+}
+
+ # Parse options
+ func_parse_lt_options \"\$0\" \${1+\"\$@\"}
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\`
+ done
+
+ # Usually 'no', except on cygwin/mingw when embedded into
+ # the cwrapper.
+ WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
+ if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
+ # special case for '.'
+ if test \"\$thisdir\" = \".\"; then
+ thisdir=\`pwd\`
+ fi
+ # remove .libs from thisdir
+ case \"\$thisdir\" in
+ *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;;
+ $objdir ) thisdir=. ;;
+ esac
+ fi
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test yes = "$fast_install"; then
+ $ECHO "\
+ program=lt-'$outputname'$exeext
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" ||
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $MKDIR \"\$progdir\"
+ else
+ $RM \"\$progdir/\$file\"
+ fi"
+
+ $ECHO "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+ else
+ \$ECHO \"\$relink_command_output\" >&2
+ $RM \"\$progdir/\$file\"
+ exit 1
+ fi
+ fi
+
+ $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $RM \"\$progdir/\$program\";
+ $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $RM \"\$progdir/\$file\"
+ fi"
+ else
+ $ECHO "\
+ program='$outputname'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ $ECHO "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # fixup the dll searchpath if we need to.
+ #
+ # Fix the DLL searchpath if we need to. Do this before prepending
+ # to shlibpath, because on Windows, both are PATH and uninstalled
+ # libraries must come first.
+ if test -n "$dllsearchpath"; then
+ $ECHO "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ # Export our shlibpath_var if we have one.
+ if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $ECHO "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 sed
+ $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ $ECHO "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+ func_exec_program \${1+\"\$@\"}
+ fi
+ else
+ # The program doesn't exist.
+ \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2
+ \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
+ \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
+ exit 1
+ fi
+fi\
+"
+}
+
+
+# func_emit_cwrapperexe_src
+# emit the source code for a wrapper executable on stdout
+# Must ONLY be called from within func_mode_link because
+# it depends on a number of variable set therein.
+func_emit_cwrapperexe_src ()
+{
+ cat <
+#include
+#ifdef _MSC_VER
+# include
+# include
+# include
+#else
+# include
+# include
+# ifdef __CYGWIN__
+# include
+# endif
+#endif
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0)
+
+/* declarations of non-ANSI functions */
+#if defined __MINGW32__
+# ifdef __STRICT_ANSI__
+int _putenv (const char *);
+# endif
+#elif defined __CYGWIN__
+# ifdef __STRICT_ANSI__
+char *realpath (const char *, char *);
+int putenv (char *);
+int setenv (const char *, const char *, int);
+# endif
+/* #elif defined other_platform || defined ... */
+#endif
+
+/* portability defines, excluding path handling macros */
+#if defined _MSC_VER
+# define setmode _setmode
+# define stat _stat
+# define chmod _chmod
+# define getcwd _getcwd
+# define putenv _putenv
+# define S_IXUSR _S_IEXEC
+#elif defined __MINGW32__
+# define setmode _setmode
+# define stat _stat
+# define chmod _chmod
+# define getcwd _getcwd
+# define putenv _putenv
+#elif defined __CYGWIN__
+# define HAVE_SETENV
+# define FOPEN_WB "wb"
+/* #elif defined other platforms ... */
+#endif
+
+#if defined PATH_MAX
+# define LT_PATHMAX PATH_MAX
+#elif defined MAXPATHLEN
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef S_IXOTH
+# define S_IXOTH 0
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0
+#endif
+
+/* path handling portability macros */
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \
+ defined __OS2__
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# define FOPEN_WB "wb"
+# ifndef DIR_SEPARATOR_2
+# define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+# define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#ifndef FOPEN_WB
+# define FOPEN_WB "w"
+#endif
+#ifndef _O_BINARY
+# define _O_BINARY 0
+#endif
+
+#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+ if (stale) { free (stale); stale = 0; } \
+} while (0)
+
+#if defined LT_DEBUGWRAPPER
+static int lt_debug = 1;
+#else
+static int lt_debug = 0;
+#endif
+
+const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */
+
+void *xmalloc (size_t num);
+char *xstrdup (const char *string);
+const char *base_name (const char *name);
+char *find_executable (const char *wrapper);
+char *chase_symlinks (const char *pathspec);
+int make_executable (const char *path);
+int check_executable (const char *path);
+char *strendzap (char *str, const char *pat);
+void lt_debugprintf (const char *file, int line, const char *fmt, ...);
+void lt_fatal (const char *file, int line, const char *message, ...);
+static const char *nonnull (const char *s);
+static const char *nonempty (const char *s);
+void lt_setenv (const char *name, const char *value);
+char *lt_extend_str (const char *orig_value, const char *add, int to_end);
+void lt_update_exe_path (const char *name, const char *value);
+void lt_update_lib_path (const char *name, const char *value);
+char **prepare_spawn (char **argv);
+void lt_dump_script (FILE *f);
+EOF
+
+ cat <= 0)
+ && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+ return 1;
+ else
+ return 0;
+}
+
+int
+make_executable (const char *path)
+{
+ int rval = 0;
+ struct stat st;
+
+ lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n",
+ nonempty (path));
+ if ((!path) || (!*path))
+ return 0;
+
+ if (stat (path, &st) >= 0)
+ {
+ rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
+ }
+ return rval;
+}
+
+/* Searches for the full path of the wrapper. Returns
+ newly allocated full path name if found, NULL otherwise
+ Does not chase symlinks, even on platforms that support them.
+*/
+char *
+find_executable (const char *wrapper)
+{
+ int has_slash = 0;
+ const char *p;
+ const char *p_next;
+ /* static buffer for getcwd */
+ char tmp[LT_PATHMAX + 1];
+ size_t tmp_len;
+ char *concat_name;
+
+ lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n",
+ nonempty (wrapper));
+
+ if ((wrapper == NULL) || (*wrapper == '\0'))
+ return NULL;
+
+ /* Absolute path? */
+#if defined HAVE_DOS_BASED_FILE_SYSTEM
+ if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ }
+ else
+ {
+#endif
+ if (IS_DIR_SEPARATOR (wrapper[0]))
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ }
+#if defined HAVE_DOS_BASED_FILE_SYSTEM
+ }
+#endif
+
+ for (p = wrapper; *p; p++)
+ if (*p == '/')
+ {
+ has_slash = 1;
+ break;
+ }
+ if (!has_slash)
+ {
+ /* no slashes; search PATH */
+ const char *path = getenv ("PATH");
+ if (path != NULL)
+ {
+ for (p = path; *p; p = p_next)
+ {
+ const char *q;
+ size_t p_len;
+ for (q = p; *q; q++)
+ if (IS_PATH_SEPARATOR (*q))
+ break;
+ p_len = (size_t) (q - p);
+ p_next = (*q == '\0' ? q : q + 1);
+ if (p_len == 0)
+ {
+ /* empty path: current directory */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+ nonnull (strerror (errno)));
+ tmp_len = strlen (tmp);
+ concat_name =
+ XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+ }
+ else
+ {
+ concat_name =
+ XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
+ memcpy (concat_name, p, p_len);
+ concat_name[p_len] = '/';
+ strcpy (concat_name + p_len + 1, wrapper);
+ }
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ }
+ }
+ /* not found in PATH; assume curdir */
+ }
+ /* Relative path | not found in path: prepend cwd */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+ nonnull (strerror (errno)));
+ tmp_len = strlen (tmp);
+ concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ return NULL;
+}
+
+char *
+chase_symlinks (const char *pathspec)
+{
+#ifndef S_ISLNK
+ return xstrdup (pathspec);
+#else
+ char buf[LT_PATHMAX];
+ struct stat s;
+ char *tmp_pathspec = xstrdup (pathspec);
+ char *p;
+ int has_symlinks = 0;
+ while (strlen (tmp_pathspec) && !has_symlinks)
+ {
+ lt_debugprintf (__FILE__, __LINE__,
+ "checking path component for symlinks: %s\n",
+ tmp_pathspec);
+ if (lstat (tmp_pathspec, &s) == 0)
+ {
+ if (S_ISLNK (s.st_mode) != 0)
+ {
+ has_symlinks = 1;
+ break;
+ }
+
+ /* search backwards for last DIR_SEPARATOR */
+ p = tmp_pathspec + strlen (tmp_pathspec) - 1;
+ while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+ p--;
+ if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+ {
+ /* no more DIR_SEPARATORS left */
+ break;
+ }
+ *p = '\0';
+ }
+ else
+ {
+ lt_fatal (__FILE__, __LINE__,
+ "error accessing file \"%s\": %s",
+ tmp_pathspec, nonnull (strerror (errno)));
+ }
+ }
+ XFREE (tmp_pathspec);
+
+ if (!has_symlinks)
+ {
+ return xstrdup (pathspec);
+ }
+
+ tmp_pathspec = realpath (pathspec, buf);
+ if (tmp_pathspec == 0)
+ {
+ lt_fatal (__FILE__, __LINE__,
+ "could not follow symlinks for %s", pathspec);
+ }
+ return xstrdup (tmp_pathspec);
+#endif
+}
+
+char *
+strendzap (char *str, const char *pat)
+{
+ size_t len, patlen;
+
+ assert (str != NULL);
+ assert (pat != NULL);
+
+ len = strlen (str);
+ patlen = strlen (pat);
+
+ if (patlen <= len)
+ {
+ str += len - patlen;
+ if (STREQ (str, pat))
+ *str = '\0';
+ }
+ return str;
+}
+
+void
+lt_debugprintf (const char *file, int line, const char *fmt, ...)
+{
+ va_list args;
+ if (lt_debug)
+ {
+ (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line);
+ va_start (args, fmt);
+ (void) vfprintf (stderr, fmt, args);
+ va_end (args);
+ }
+}
+
+static void
+lt_error_core (int exit_status, const char *file,
+ int line, const char *mode,
+ const char *message, va_list ap)
+{
+ fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode);
+ vfprintf (stderr, message, ap);
+ fprintf (stderr, ".\n");
+
+ if (exit_status >= 0)
+ exit (exit_status);
+}
+
+void
+lt_fatal (const char *file, int line, const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap);
+ va_end (ap);
+}
+
+static const char *
+nonnull (const char *s)
+{
+ return s ? s : "(null)";
+}
+
+static const char *
+nonempty (const char *s)
+{
+ return (s && !*s) ? "(empty)" : nonnull (s);
+}
+
+void
+lt_setenv (const char *name, const char *value)
+{
+ lt_debugprintf (__FILE__, __LINE__,
+ "(lt_setenv) setting '%s' to '%s'\n",
+ nonnull (name), nonnull (value));
+ {
+#ifdef HAVE_SETENV
+ /* always make a copy, for consistency with !HAVE_SETENV */
+ char *str = xstrdup (value);
+ setenv (name, str, 1);
+#else
+ size_t len = strlen (name) + 1 + strlen (value) + 1;
+ char *str = XMALLOC (char, len);
+ sprintf (str, "%s=%s", name, value);
+ if (putenv (str) != EXIT_SUCCESS)
+ {
+ XFREE (str);
+ }
+#endif
+ }
+}
+
+char *
+lt_extend_str (const char *orig_value, const char *add, int to_end)
+{
+ char *new_value;
+ if (orig_value && *orig_value)
+ {
+ size_t orig_value_len = strlen (orig_value);
+ size_t add_len = strlen (add);
+ new_value = XMALLOC (char, add_len + orig_value_len + 1);
+ if (to_end)
+ {
+ strcpy (new_value, orig_value);
+ strcpy (new_value + orig_value_len, add);
+ }
+ else
+ {
+ strcpy (new_value, add);
+ strcpy (new_value + add_len, orig_value);
+ }
+ }
+ else
+ {
+ new_value = xstrdup (add);
+ }
+ return new_value;
+}
+
+void
+lt_update_exe_path (const char *name, const char *value)
+{
+ lt_debugprintf (__FILE__, __LINE__,
+ "(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
+ nonnull (name), nonnull (value));
+
+ if (name && *name && value && *value)
+ {
+ char *new_value = lt_extend_str (getenv (name), value, 0);
+ /* some systems can't cope with a ':'-terminated path #' */
+ size_t len = strlen (new_value);
+ while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
+ {
+ new_value[--len] = '\0';
+ }
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ }
+}
+
+void
+lt_update_lib_path (const char *name, const char *value)
+{
+ lt_debugprintf (__FILE__, __LINE__,
+ "(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
+ nonnull (name), nonnull (value));
+
+ if (name && *name && value && *value)
+ {
+ char *new_value = lt_extend_str (getenv (name), value, 0);
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ }
+}
+
+EOF
+ case $host_os in
+ mingw*)
+ cat <<"EOF"
+
+/* Prepares an argument vector before calling spawn().
+ Note that spawn() does not by itself call the command interpreter
+ (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
+ ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&v);
+ v.dwPlatformId == VER_PLATFORM_WIN32_NT;
+ }) ? "cmd.exe" : "command.com").
+ Instead it simply concatenates the arguments, separated by ' ', and calls
+ CreateProcess(). We must quote the arguments since Win32 CreateProcess()
+ interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
+ special way:
+ - Space and tab are interpreted as delimiters. They are not treated as
+ delimiters if they are surrounded by double quotes: "...".
+ - Unescaped double quotes are removed from the input. Their only effect is
+ that within double quotes, space and tab are treated like normal
+ characters.
+ - Backslashes not followed by double quotes are not special.
+ - But 2*n+1 backslashes followed by a double quote become
+ n backslashes followed by a double quote (n >= 0):
+ \" -> "
+ \\\" -> \"
+ \\\\\" -> \\"
+ */
+#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+char **
+prepare_spawn (char **argv)
+{
+ size_t argc;
+ char **new_argv;
+ size_t i;
+
+ /* Count number of arguments. */
+ for (argc = 0; argv[argc] != NULL; argc++)
+ ;
+
+ /* Allocate new argument vector. */
+ new_argv = XMALLOC (char *, argc + 1);
+
+ /* Put quoted arguments into the new argument vector. */
+ for (i = 0; i < argc; i++)
+ {
+ const char *string = argv[i];
+
+ if (string[0] == '\0')
+ new_argv[i] = xstrdup ("\"\"");
+ else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
+ {
+ int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
+ size_t length;
+ unsigned int backslashes;
+ const char *s;
+ char *quoted_string;
+ char *p;
+
+ length = 0;
+ backslashes = 0;
+ if (quote_around)
+ length++;
+ for (s = string; *s != '\0'; s++)
+ {
+ char c = *s;
+ if (c == '"')
+ length += backslashes + 1;
+ length++;
+ if (c == '\\')
+ backslashes++;
+ else
+ backslashes = 0;
+ }
+ if (quote_around)
+ length += backslashes + 1;
+
+ quoted_string = XMALLOC (char, length + 1);
+
+ p = quoted_string;
+ backslashes = 0;
+ if (quote_around)
+ *p++ = '"';
+ for (s = string; *s != '\0'; s++)
+ {
+ char c = *s;
+ if (c == '"')
+ {
+ unsigned int j;
+ for (j = backslashes + 1; j > 0; j--)
+ *p++ = '\\';
+ }
+ *p++ = c;
+ if (c == '\\')
+ backslashes++;
+ else
+ backslashes = 0;
+ }
+ if (quote_around)
+ {
+ unsigned int j;
+ for (j = backslashes; j > 0; j--)
+ *p++ = '\\';
+ *p++ = '"';
+ }
+ *p = '\0';
+
+ new_argv[i] = quoted_string;
+ }
+ else
+ new_argv[i] = (char *) string;
+ }
+ new_argv[argc] = NULL;
+
+ return new_argv;
+}
+EOF
+ ;;
+ esac
+
+ cat <<"EOF"
+void lt_dump_script (FILE* f)
+{
+EOF
+ func_emit_wrapper yes |
+ $SED -n -e '
+s/^\(.\{79\}\)\(..*\)/\1\
+\2/
+h
+s/\([\\"]\)/\\\1/g
+s/$/\\n/
+s/\([^\n]*\).*/ fputs ("\1", f);/p
+g
+D'
+ cat <<"EOF"
+}
+EOF
+}
+# end: func_emit_cwrapperexe_src
+
+# func_win32_import_lib_p ARG
+# True if ARG is an import lib, as indicated by $file_magic_cmd
+func_win32_import_lib_p ()
+{
+ $debug_cmd
+
+ case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in
+ *import*) : ;;
+ *) false ;;
+ esac
+}
+
+# func_suncc_cstd_abi
+# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!!
+# Several compiler flags select an ABI that is incompatible with the
+# Cstd library. Avoid specifying it if any are in CXXFLAGS.
+func_suncc_cstd_abi ()
+{
+ $debug_cmd
+
+ case " $compile_command " in
+ *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*)
+ suncc_use_cstd_abi=no
+ ;;
+ *)
+ suncc_use_cstd_abi=yes
+ ;;
+ esac
+}
+
+# func_mode_link arg...
+func_mode_link ()
+{
+ $debug_cmd
+
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # what system we are compiling for in order to pass an extra
+ # flag for every libtool invocation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll that has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ libtool_args=$nonopt
+ base_compile="$nonopt $@"
+ compile_command=$nonopt
+ finalize_command=$nonopt
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ old_deplibs=
+ compiler_flags=
+ linker_flags=
+ dllsearchpath=
+ lib_search_path=`pwd`
+ inst_prefix_dir=
+ new_inherited_linker_flags=
+
+ avoid_version=no
+ bindir=
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ ltlibs=
+ module=no
+ no_install=no
+ objs=
+ os2dllname=
+ non_pic_objects=
+ precious_files_regex=
+ prefer_static_libs=no
+ preload=false
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+ vinfo_number=no
+ weak_libs=
+ single_module=$wl-single_module
+ func_infer_tag $base_compile
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case $arg in
+ -shared)
+ test yes != "$build_libtool_libs" \
+ && func_fatal_configuration "cannot build a shared library"
+ build_old_libs=no
+ break
+ ;;
+ -all-static | -static | -static-libtool-libs)
+ case $arg in
+ -all-static)
+ if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then
+ func_warning "complete static linking is impossible in this configuration"
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ ;;
+ -static)
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=built
+ ;;
+ -static-libtool-libs)
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ ;;
+ esac
+ build_libtool_libs=no
+ build_old_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test "$#" -gt 0; do
+ arg=$1
+ shift
+ func_quote_arg pretty,unquoted "$arg"
+ qarg=$func_quote_arg_unquoted_result
+ func_append libtool_args " $func_quote_arg_result"
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ output)
+ func_append compile_command " @OUTPUT@"
+ func_append finalize_command " @OUTPUT@"
+ ;;
+ esac
+
+ case $prev in
+ bindir)
+ bindir=$arg
+ prev=
+ continue
+ ;;
+ dlfiles|dlprefiles)
+ $preload || {
+ # Add the symbol object into the linking commands.
+ func_append compile_command " @SYMFILE@"
+ func_append finalize_command " @SYMFILE@"
+ preload=:
+ }
+ case $arg in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test no = "$dlself"; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test dlprefiles = "$prev"; then
+ dlself=yes
+ elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test dlfiles = "$prev"; then
+ func_append dlfiles " $arg"
+ else
+ func_append dlprefiles " $arg"
+ fi
+ prev=
+ continue
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols=$arg
+ test -f "$arg" \
+ || func_fatal_error "symbol file '$arg' does not exist"
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex=$arg
+ prev=
+ continue
+ ;;
+ framework)
+ case $host in
+ *-*-darwin*)
+ case "$deplibs " in
+ *" $qarg.ltframework "*) ;;
+ *) func_append deplibs " $qarg.ltframework" # this is fixed later
+ ;;
+ esac
+ ;;
+ esac
+ prev=
+ continue
+ ;;
+ inst_prefix)
+ inst_prefix_dir=$arg
+ prev=
+ continue
+ ;;
+ mllvm)
+ # Clang does not use LLVM to link, so we can simply discard any
+ # '-mllvm $arg' options when doing the link step.
+ prev=
+ continue
+ ;;
+ objectlist)
+ if test -f "$arg"; then
+ save_arg=$arg
+ moreargs=
+ for fil in `cat "$save_arg"`
+ do
+# func_append moreargs " $fil"
+ arg=$fil
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if func_lalib_unsafe_p "$arg"; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ func_source "$arg"
+
+ if test -z "$pic_object" ||
+ test -z "$non_pic_object" ||
+ test none = "$pic_object" &&
+ test none = "$non_pic_object"; then
+ func_fatal_error "cannot find name of object for '$arg'"
+ fi
+
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir=$func_dirname_result
+
+ if test none != "$pic_object"; then
+ # Prepend the subdirectory the object is found in.
+ pic_object=$xdir$pic_object
+
+ if test dlfiles = "$prev"; then
+ if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then
+ func_append dlfiles " $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test dlprefiles = "$prev"; then
+ # Preload the old-style object.
+ func_append dlprefiles " $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ func_append libobjs " $pic_object"
+ arg=$pic_object
+ fi
+
+ # Non-PIC object.
+ if test none != "$non_pic_object"; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object=$xdir$non_pic_object
+
+ # A standard non-PIC object
+ func_append non_pic_objects " $non_pic_object"
+ if test -z "$pic_object" || test none = "$pic_object"; then
+ arg=$non_pic_object
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object=$pic_object
+ func_append non_pic_objects " $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if $opt_dry_run; then
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir=$func_dirname_result
+
+ func_lo2o "$arg"
+ pic_object=$xdir$objdir/$func_lo2o_result
+ non_pic_object=$xdir$func_lo2o_result
+ func_append libobjs " $pic_object"
+ func_append non_pic_objects " $non_pic_object"
+ else
+ func_fatal_error "'$arg' is not a valid libtool object"
+ fi
+ fi
+ done
+ else
+ func_fatal_error "link input file '$arg' does not exist"
+ fi
+ arg=$save_arg
+ prev=
+ continue
+ ;;
+ os2dllname)
+ os2dllname=$arg
+ prev=
+ continue
+ ;;
+ precious_regex)
+ precious_files_regex=$arg
+ prev=
+ continue
+ ;;
+ release)
+ release=-$arg
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case $arg in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ func_fatal_error "only absolute run-paths are allowed"
+ ;;
+ esac
+ if test rpath = "$prev"; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) func_append rpath " $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) func_append xrpath " $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ shrext)
+ shrext_cmds=$arg
+ prev=
+ continue
+ ;;
+ weak)
+ func_append weak_libs " $arg"
+ prev=
+ continue
+ ;;
+ xassembler)
+ func_append compiler_flags " -Xassembler $qarg"
+ prev=
+ func_append compile_command " -Xassembler $qarg"
+ func_append finalize_command " -Xassembler $qarg"
+ continue
+ ;;
+ xcclinker)
+ func_append linker_flags " $qarg"
+ func_append compiler_flags " $qarg"
+ prev=
+ func_append compile_command " $qarg"
+ func_append finalize_command " $qarg"
+ continue
+ ;;
+ xcompiler)
+ func_append compiler_flags " $qarg"
+ prev=
+ func_append compile_command " $qarg"
+ func_append finalize_command " $qarg"
+ continue
+ ;;
+ xlinker)
+ func_append linker_flags " $qarg"
+ func_append compiler_flags " $wl$qarg"
+ prev=
+ func_append compile_command " $wl$qarg"
+ func_append finalize_command " $wl$qarg"
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi # test -n "$prev"
+
+ prevarg=$arg
+
+ case $arg in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ # See comment for -static flag below, for more details.
+ func_append compile_command " $link_static_flag"
+ func_append finalize_command " $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ func_fatal_error "'-allow-undefined' must not be used because it is the default"
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -bindir)
+ prev=bindir
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ func_fatal_error "more than one -exported-symbols argument is not allowed"
+ fi
+ if test X-export-symbols = "X$arg"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -framework)
+ prev=framework
+ continue
+ ;;
+
+ -inst-prefix-dir)
+ prev=inst_prefix
+ continue
+ ;;
+
+ # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+ # so, if we see these flags be careful not to treat them like -L
+ -L[A-Z][A-Z]*:*)
+ case $with_gcc/$host in
+ no/*-*-irix* | /*-*-irix*)
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ ;;
+ esac
+ continue
+ ;;
+
+ -L*)
+ func_stripname "-L" '' "$arg"
+ if test -z "$func_stripname_result"; then
+ if test "$#" -gt 0; then
+ func_fatal_error "require no space between '-L' and '$1'"
+ else
+ func_fatal_error "need path for '-L' option"
+ fi
+ fi
+ func_resolve_sysroot "$func_stripname_result"
+ dir=$func_resolve_sysroot_result
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ test -z "$absdir" && \
+ func_fatal_error "cannot determine absolute directory name of '$dir'"
+ dir=$absdir
+ ;;
+ esac
+ case "$deplibs " in
+ *" -L$dir "* | *" $arg "*)
+ # Will only happen for absolute or sysroot arguments
+ ;;
+ *)
+ # Preserve sysroot, but never include relative directories
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;;
+ *) func_append deplibs " -L$dir" ;;
+ esac
+ func_append lib_search_path " $dir"
+ ;;
+ esac
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+ testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$dir:"*) ;;
+ ::) dllsearchpath=$dir;;
+ *) func_append dllsearchpath ":$dir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ ::) dllsearchpath=$testbindir;;
+ *) func_append dllsearchpath ":$testbindir";;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+
+ -l*)
+ if test X-lc = "X$arg" || test X-lm = "X$arg"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)
+ # These systems don't actually have a C or math library (as such)
+ continue
+ ;;
+ *-*-os2*)
+ # These systems don't actually have a C library (as such)
+ test X-lc = "X$arg" && continue
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*)
+ # Do not include libc due to us having libc/libc_r.
+ test X-lc = "X$arg" && continue
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C and math libraries are in the System framework
+ func_append deplibs " System.ltframework"
+ continue
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ test X-lc = "X$arg" && continue
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ test X-lc = "X$arg" && continue
+ ;;
+ esac
+ elif test X-lc_r = "X$arg"; then
+ case $host in
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig* | *-*-midnightbsd*)
+ # Do not include libc_r directly, use -pthread flag.
+ continue
+ ;;
+ esac
+ fi
+ func_append deplibs " $arg"
+ continue
+ ;;
+
+ -mllvm)
+ prev=mllvm
+ continue
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ # Tru64 UNIX uses -model [arg] to determine the layout of C++
+ # classes, name mangling, and exception handling.
+ # Darwin uses the -arch flag to determine output architecture.
+ -model|-arch|-isysroot|--sysroot)
+ func_append compiler_flags " $arg"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ prev=xcompiler
+ continue
+ ;;
+ # Solaris ld rejects as of 11.4. Refer to Oracle bug 22985199.
+ -pthread)
+ case $host in
+ *solaris2*) ;;
+ *)
+ case "$new_inherited_linker_flags " in
+ *" $arg "*) ;;
+ * ) func_append new_inherited_linker_flags " $arg" ;;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+ -mt|-mthreads|-kthread|-Kthread|-pthreads|--thread-safe \
+ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+ func_append compiler_flags " $arg"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ case "$new_inherited_linker_flags " in
+ *" $arg "*) ;;
+ * ) func_append new_inherited_linker_flags " $arg" ;;
+ esac
+ continue
+ ;;
+
+ -multi_module)
+ single_module=$wl-multi_module
+ continue
+ ;;
+
+ -no-fast-install)
+ fast_install=no
+ continue
+ ;;
+
+ -no-install)
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
+ # The PATH hackery in wrapper scripts is required on Windows
+ # and Darwin in order for the loader to find any dlls it needs.
+ func_warning "'-no-install' is ignored for $host"
+ func_warning "assuming '-no-fast-install' instead"
+ fast_install=no
+ ;;
+ *) no_install=yes ;;
+ esac
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -objectlist)
+ prev=objectlist
+ continue
+ ;;
+
+ -os2dllname)
+ prev=os2dllname
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -precious-files-regex)
+ prev=precious_regex
+ continue
+ ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ func_stripname '-R' '' "$arg"
+ dir=$func_stripname_result
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ =*)
+ func_stripname '=' '' "$dir"
+ dir=$lt_sysroot$func_stripname_result
+ ;;
+ *)
+ func_fatal_error "only absolute run-paths are allowed"
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) func_append xrpath " $dir" ;;
+ esac
+ continue
+ ;;
+
+ -shared)
+ # The effects of -shared are defined in a previous loop.
+ continue
+ ;;
+
+ -shrext)
+ prev=shrext
+ continue
+ ;;
+
+ -static | -static-libtool-libs)
+ # The effects of -static are defined in a previous loop.
+ # We used to do the same as -all-static on platforms that
+ # didn't have a PIC flag, but the assumption that the effects
+ # would be equivalent was wrong. It would break on at least
+ # Digital Unix and AIX.
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+
+ -version-number)
+ prev=vinfo
+ vinfo_number=yes
+ continue
+ ;;
+
+ -weak)
+ prev=weak
+ continue
+ ;;
+
+ -Wc,*)
+ func_stripname '-Wc,' '' "$arg"
+ args=$func_stripname_result
+ arg=
+ save_ifs=$IFS; IFS=,
+ for flag in $args; do
+ IFS=$save_ifs
+ func_quote_arg pretty "$flag"
+ func_append arg " $func_quote_arg_result"
+ func_append compiler_flags " $func_quote_arg_result"
+ done
+ IFS=$save_ifs
+ func_stripname ' ' '' "$arg"
+ arg=$func_stripname_result
+ ;;
+
+ -Wl,*)
+ func_stripname '-Wl,' '' "$arg"
+ args=$func_stripname_result
+ arg=
+ save_ifs=$IFS; IFS=,
+ for flag in $args; do
+ IFS=$save_ifs
+ func_quote_arg pretty "$flag"
+ func_append arg " $wl$func_quote_arg_result"
+ func_append compiler_flags " $wl$func_quote_arg_result"
+ func_append linker_flags " $func_quote_arg_result"
+ done
+ IFS=$save_ifs
+ func_stripname ' ' '' "$arg"
+ arg=$func_stripname_result
+ ;;
+
+ -Xassembler)
+ prev=xassembler
+ continue
+ ;;
+
+ -Xcompiler)
+ prev=xcompiler
+ continue
+ ;;
+
+ -Xlinker)
+ prev=xlinker
+ continue
+ ;;
+
+ -XCClinker)
+ prev=xcclinker
+ continue
+ ;;
+
+ # -msg_* for osf cc
+ -msg_*)
+ func_quote_arg pretty "$arg"
+ arg=$func_quote_arg_result
+ ;;
+
+ # Flags to be passed through unchanged, with rationale:
+ # -64, -mips[0-9] enable 64-bit mode for the SGI compiler
+ # -r[0-9][0-9]* specify processor for the SGI compiler
+ # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler
+ # +DA*, +DD* enable 64-bit mode for the HP compiler
+ # -q* compiler args for the IBM compiler
+ # -m*, -t[45]*, -txscale* architecture-specific flags for GCC
+ # -F/path path to uninstalled frameworks, gcc on darwin
+ # -p, -pg, --coverage, -fprofile-* profiling flags for GCC
+ # -fstack-protector* stack protector flags for GCC
+ # @file GCC response files
+ # -tp=* Portland pgcc target processor selection
+ # --sysroot=* for sysroot support
+ # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
+ # -specs=* GCC specs files
+ # -stdlib=* select c++ std lib with clang
+ # -fsanitize=* Clang/GCC memory and address sanitizer
+ # -fuse-ld=* Linker select flags for GCC
+ # -static-* direct GCC to link specific libraries statically
+ # -fcilkplus Cilk Plus language extension features for C/C++
+ # -Wa,* Pass flags directly to the assembler
+ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
+ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \
+ -specs=*|-fsanitize=*|-fuse-ld=*|-static-*|-fcilkplus|-Wa,*)
+ func_quote_arg pretty "$arg"
+ arg=$func_quote_arg_result
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ func_append compiler_flags " $arg"
+ continue
+ ;;
+
+ -Z*)
+ if test os2 = "`expr $host : '.*\(os2\)'`"; then
+ # OS/2 uses -Zxxx to specify OS/2-specific options
+ compiler_flags="$compiler_flags $arg"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ case $arg in
+ -Zlinker | -Zstack)
+ prev=xcompiler
+ ;;
+ esac
+ continue
+ else
+ # Otherwise treat like 'Some other compiler flag' below
+ func_quote_arg pretty "$arg"
+ arg=$func_quote_arg_result
+ fi
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ func_quote_arg pretty "$arg"
+ arg=$func_quote_arg_result
+ ;;
+
+ *.$objext)
+ # A standard object.
+ func_append objs " $arg"
+ ;;
+
+ *.lo)
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if func_lalib_unsafe_p "$arg"; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ func_source "$arg"
+
+ if test -z "$pic_object" ||
+ test -z "$non_pic_object" ||
+ test none = "$pic_object" &&
+ test none = "$non_pic_object"; then
+ func_fatal_error "cannot find name of object for '$arg'"
+ fi
+
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir=$func_dirname_result
+
+ test none = "$pic_object" || {
+ # Prepend the subdirectory the object is found in.
+ pic_object=$xdir$pic_object
+
+ if test dlfiles = "$prev"; then
+ if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then
+ func_append dlfiles " $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test dlprefiles = "$prev"; then
+ # Preload the old-style object.
+ func_append dlprefiles " $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ func_append libobjs " $pic_object"
+ arg=$pic_object
+ }
+
+ # Non-PIC object.
+ if test none != "$non_pic_object"; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object=$xdir$non_pic_object
+
+ # A standard non-PIC object
+ func_append non_pic_objects " $non_pic_object"
+ if test -z "$pic_object" || test none = "$pic_object"; then
+ arg=$non_pic_object
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object=$pic_object
+ func_append non_pic_objects " $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if $opt_dry_run; then
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir=$func_dirname_result
+
+ func_lo2o "$arg"
+ pic_object=$xdir$objdir/$func_lo2o_result
+ non_pic_object=$xdir$func_lo2o_result
+ func_append libobjs " $pic_object"
+ func_append non_pic_objects " $non_pic_object"
+ else
+ func_fatal_error "'$arg' is not a valid libtool object"
+ fi
+ fi
+ ;;
+
+ *.$libext)
+ # An archive.
+ func_append deplibs " $arg"
+ func_append old_deplibs " $arg"
+ continue
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ func_resolve_sysroot "$arg"
+ if test dlfiles = "$prev"; then
+ # This library was specified with -dlopen.
+ func_append dlfiles " $func_resolve_sysroot_result"
+ prev=
+ elif test dlprefiles = "$prev"; then
+ # The library was specified with -dlpreopen.
+ func_append dlprefiles " $func_resolve_sysroot_result"
+ prev=
+ else
+ func_append deplibs " $func_resolve_sysroot_result"
+ fi
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ func_quote_arg pretty "$arg"
+ arg=$func_quote_arg_result
+ ;;
+ esac # arg
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ fi
+ done # argument parsing loop
+
+ test -n "$prev" && \
+ func_fatal_help "the '$prevarg' option requires an argument"
+
+ if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ fi
+
+ oldlibs=
+ # calculate the name of the file, without its directory
+ func_basename "$output"
+ outputname=$func_basename_result
+ libobjs_save=$libobjs
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\`
+ else
+ shlib_search_path=
+ fi
+ eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ # Definition is injected by LT_CONFIG during libtool generation.
+ func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH"
+
+ func_dirname "$output" "/" ""
+ output_objdir=$func_dirname_result$objdir
+ func_to_tool_file "$output_objdir/"
+ tool_output_objdir=$func_to_tool_file_result
+ # Create the object directory.
+ func_mkdir_p "$output_objdir"
+
+ # Determine the type of output
+ case $output in
+ "")
+ func_fatal_help "you must specify an output file"
+ ;;
+ *.$libext) linkmode=oldlib ;;
+ *.lo | *.$objext) linkmode=obj ;;
+ *.la) linkmode=lib ;;
+ *) linkmode=prog ;; # Anything else should be a program.
+ esac
+
+ specialdeplibs=
+
+ libs=
+ # Find all interdependent deplibs by searching for libraries
+ # that are linked more than once (e.g. -la -lb -la)
+ for deplib in $deplibs; do
+ if $opt_preserve_dup_deps; then
+ case "$libs " in
+ *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+ esac
+ fi
+ func_append libs " $deplib"
+ done
+
+ if test lib = "$linkmode"; then
+ libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+ # Compute libraries that are listed more than once in $predeps
+ # $postdeps and mark them as special (i.e., whose duplicates are
+ # not to be eliminated).
+ pre_post_deps=
+ if $opt_duplicate_compiler_generated_deps; then
+ for pre_post_dep in $predeps $postdeps; do
+ case "$pre_post_deps " in
+ *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;;
+ esac
+ func_append pre_post_deps " $pre_post_dep"
+ done
+ fi
+ pre_post_deps=
+ fi
+
+ deplibs=
+ newdependency_libs=
+ newlib_search_path=
+ need_relink=no # whether we're linking any uninstalled libtool libraries
+ notinst_deplibs= # not-installed libtool libraries
+ notinst_path= # paths that contain not-installed libtool libraries
+
+ case $linkmode in
+ lib)
+ passes="conv dlpreopen link"
+ for file in $dlfiles $dlprefiles; do
+ case $file in
+ *.la) ;;
+ *)
+ func_fatal_help "libraries can '-dlopen' only libtool libraries: $file"
+ ;;
+ esac
+ done
+ ;;
+ prog)
+ compile_deplibs=
+ finalize_deplibs=
+ alldeplibs=false
+ newdlfiles=
+ newdlprefiles=
+ passes="conv scan dlopen dlpreopen link"
+ ;;
+ *) passes="conv"
+ ;;
+ esac
+
+ for pass in $passes; do
+ # The preopen pass in lib mode reverses $deplibs; put it back here
+ # so that -L comes before libs that need it for instance...
+ if test lib,link = "$linkmode,$pass"; then
+ ## FIXME: Find the place where the list is rebuilt in the wrong
+ ## order, and fix it there properly
+ tmp_deplibs=
+ for deplib in $deplibs; do
+ tmp_deplibs="$deplib $tmp_deplibs"
+ done
+ deplibs=$tmp_deplibs
+ fi
+
+ if test lib,link = "$linkmode,$pass" ||
+ test prog,scan = "$linkmode,$pass"; then
+ libs=$deplibs
+ deplibs=
+ fi
+ if test prog = "$linkmode"; then
+ case $pass in
+ dlopen) libs=$dlfiles ;;
+ dlpreopen) libs=$dlprefiles ;;
+ link)
+ libs="$deplibs %DEPLIBS%"
+ test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
+ ;;
+ esac
+ fi
+ if test lib,dlpreopen = "$linkmode,$pass"; then
+ # Collect and forward deplibs of preopened libtool libs
+ for lib in $dlprefiles; do
+ # Ignore non-libtool-libs
+ dependency_libs=
+ func_resolve_sysroot "$lib"
+ case $lib in
+ *.la) func_source "$func_resolve_sysroot_result" ;;
+ esac
+
+ # Collect preopened libtool deplibs, except any this library
+ # has declared as weak libs
+ for deplib in $dependency_libs; do
+ func_basename "$deplib"
+ deplib_base=$func_basename_result
+ case " $weak_libs " in
+ *" $deplib_base "*) ;;
+ *) func_append deplibs " $deplib" ;;
+ esac
+ done
+ done
+ libs=$dlprefiles
+ fi
+ if test dlopen = "$pass"; then
+ # Collect dlpreopened libraries
+ save_deplibs=$deplibs
+ deplibs=
+ fi
+
+ for deplib in $libs; do
+ lib=
+ found=false
+ case $deplib in
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
+ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ func_append compiler_flags " $deplib"
+ if test lib = "$linkmode"; then
+ case "$new_inherited_linker_flags " in
+ *" $deplib "*) ;;
+ * ) func_append new_inherited_linker_flags " $deplib" ;;
+ esac
+ fi
+ fi
+ continue
+ ;;
+ -l*)
+ if test lib != "$linkmode" && test prog != "$linkmode"; then
+ func_warning "'-l' is ignored for archives/objects"
+ continue
+ fi
+ func_stripname '-l' '' "$deplib"
+ name=$func_stripname_result
+ if test lib = "$linkmode"; then
+ searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
+ else
+ searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
+ fi
+ for searchdir in $searchdirs; do
+ for search_ext in .la $std_shrext .so .a; do
+ # Search the libtool library
+ lib=$searchdir/lib$name$search_ext
+ if test -f "$lib"; then
+ if test .la = "$search_ext"; then
+ found=:
+ else
+ found=false
+ fi
+ break 2
+ fi
+ done
+ done
+ if $found; then
+ # deplib is a libtool library
+ # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+ # We need to do some special things here, and not later.
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ case " $predeps $postdeps " in
+ *" $deplib "*)
+ if func_lalib_p "$lib"; then
+ library_names=
+ old_library=
+ func_source "$lib"
+ for l in $old_library $library_names; do
+ ll=$l
+ done
+ if test "X$ll" = "X$old_library"; then # only static version available
+ found=false
+ func_dirname "$lib" "" "."
+ ladir=$func_dirname_result
+ lib=$ladir/$old_library
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+ fi
+ else
+ # deplib doesn't seem to be a libtool library
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ ;; # -l
+ *.ltframework)
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ if test lib = "$linkmode"; then
+ case "$new_inherited_linker_flags " in
+ *" $deplib "*) ;;
+ * ) func_append new_inherited_linker_flags " $deplib" ;;
+ esac
+ fi
+ fi
+ continue
+ ;;
+ -L*)
+ case $linkmode in
+ lib)
+ deplibs="$deplib $deplibs"
+ test conv = "$pass" && continue
+ newdependency_libs="$deplib $newdependency_libs"
+ func_stripname '-L' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result"
+ func_append newlib_search_path " $func_resolve_sysroot_result"
+ ;;
+ prog)
+ if test conv = "$pass"; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ if test scan = "$pass"; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ func_stripname '-L' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result"
+ func_append newlib_search_path " $func_resolve_sysroot_result"
+ ;;
+ *)
+ func_warning "'-L' is ignored for archives/objects"
+ ;;
+ esac # linkmode
+ continue
+ ;; # -L
+ -R*)
+ if test link = "$pass"; then
+ func_stripname '-R' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result"
+ dir=$func_resolve_sysroot_result
+ # Make sure the xrpath contains only unique directories.
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) func_append xrpath " $dir" ;;
+ esac
+ fi
+ deplibs="$deplib $deplibs"
+ continue
+ ;;
+ *.la)
+ func_resolve_sysroot "$deplib"
+ lib=$func_resolve_sysroot_result
+ ;;
+ *.$libext)
+ if test conv = "$pass"; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ case $linkmode in
+ lib)
+ # Linking convenience modules into shared libraries is allowed,
+ # but linking other static libraries is non-portable.
+ case " $dlpreconveniencelibs " in
+ *" $deplib "*) ;;
+ *)
+ valid_a_lib=false
+ case $deplibs_check_method in
+ match_pattern*)
+ set dummy $deplibs_check_method; shift
+ match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+ if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ valid_a_lib=:
+ fi
+ ;;
+ pass_all)
+ valid_a_lib=:
+ ;;
+ esac
+ if $valid_a_lib; then
+ echo
+ $ECHO "*** Warning: Linking the shared library $output against the"
+ $ECHO "*** static library $deplib is not portable!"
+ deplibs="$deplib $deplibs"
+ else
+ echo
+ $ECHO "*** Warning: Trying to link with static lib archive $deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because the file extensions .$libext of this argument makes me believe"
+ echo "*** that it is just a static archive that I should not use here."
+ fi
+ ;;
+ esac
+ continue
+ ;;
+ prog)
+ if test link != "$pass"; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ continue
+ ;;
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+ if test conv = "$pass"; then
+ deplibs="$deplib $deplibs"
+ elif test prog = "$linkmode"; then
+ if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then
+ # If there is no dlopen support or we're linking statically,
+ # we need to preload.
+ func_append newdlprefiles " $deplib"
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ func_append newdlfiles " $deplib"
+ fi
+ fi
+ continue
+ ;;
+ %DEPLIBS%)
+ alldeplibs=:
+ continue
+ ;;
+ esac # case $deplib
+
+ $found || test -f "$lib" \
+ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'"
+
+ # Check to see that this really is a libtool archive.
+ func_lalib_unsafe_p "$lib" \
+ || func_fatal_error "'$lib' is not a valid libtool archive"
+
+ func_dirname "$lib" "" "."
+ ladir=$func_dirname_result
+
+ dlname=
+ dlopen=
+ dlpreopen=
+ libdir=
+ library_names=
+ old_library=
+ inherited_linker_flags=
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variables installed, or shouldnotlink
+ installed=yes
+ shouldnotlink=no
+ avoidtemprpath=
+
+
+ # Read the .la file
+ func_source "$lib"
+
+ # Convert "-framework foo" to "foo.ltframework"
+ if test -n "$inherited_linker_flags"; then
+ tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'`
+ for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
+ case " $new_inherited_linker_flags " in
+ *" $tmp_inherited_linker_flag "*) ;;
+ *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";;
+ esac
+ done
+ fi
+ dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ if test lib,link = "$linkmode,$pass" ||
+ test prog,scan = "$linkmode,$pass" ||
+ { test prog != "$linkmode" && test lib != "$linkmode"; }; then
+ test -n "$dlopen" && func_append dlfiles " $dlopen"
+ test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen"
+ fi
+
+ if test conv = "$pass"; then
+ # Only check for convenience libraries
+ deplibs="$lib $deplibs"
+ if test -z "$libdir"; then
+ if test -z "$old_library"; then
+ func_fatal_error "cannot find name of link library for '$lib'"
+ fi
+ # It is a libtool convenience library, so add in its objects.
+ func_append convenience " $ladir/$objdir/$old_library"
+ func_append old_convenience " $ladir/$objdir/$old_library"
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ if $opt_preserve_dup_deps; then
+ case "$tmp_libs " in
+ *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+ esac
+ fi
+ func_append tmp_libs " $deplib"
+ done
+ elif test prog != "$linkmode" && test lib != "$linkmode"; then
+ func_fatal_error "'$lib' is not a convenience library"
+ fi
+ continue
+ fi # $pass = conv
+
+
+ # Get the name of the library we link against.
+ linklib=
+ if test -n "$old_library" &&
+ { test yes = "$prefer_static_libs" ||
+ test built,no = "$prefer_static_libs,$installed"; }; then
+ linklib=$old_library
+ else
+ for l in $old_library $library_names; do
+ linklib=$l
+ done
+ fi
+ if test -z "$linklib"; then
+ func_fatal_error "cannot find name of link library for '$lib'"
+ fi
+
+ # This library was specified with -dlopen.
+ if test dlopen = "$pass"; then
+ test -z "$libdir" \
+ && func_fatal_error "cannot -dlopen a convenience library: '$lib'"
+ if test -z "$dlname" ||
+ test yes != "$dlopen_support" ||
+ test no = "$build_libtool_libs"
+ then
+ # If there is no dlname, no dlopen support or we're linking
+ # statically, we need to preload. We also need to preload any
+ # dependent libraries so libltdl's deplib preloader doesn't
+ # bomb out in the load deplibs phase.
+ func_append dlprefiles " $lib $dependency_libs"
+ else
+ func_append newdlfiles " $lib"
+ fi
+ continue
+ fi # $pass = dlopen
+
+ # We need an absolute path.
+ case $ladir in
+ [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;;
+ *)
+ abs_ladir=`cd "$ladir" && pwd`
+ if test -z "$abs_ladir"; then
+ func_warning "cannot determine absolute directory name of '$ladir'"
+ func_warning "passing it literally to the linker, although it might fail"
+ abs_ladir=$ladir
+ fi
+ ;;
+ esac
+ func_basename "$lib"
+ laname=$func_basename_result
+
+ # Find the relevant object directory and library name.
+ if test yes = "$installed"; then
+ if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ func_warning "library '$lib' was moved."
+ dir=$ladir
+ absdir=$abs_ladir
+ libdir=$abs_ladir
+ else
+ dir=$lt_sysroot$libdir
+ absdir=$lt_sysroot$libdir
+ fi
+ test yes = "$hardcode_automatic" && avoidtemprpath=yes
+ else
+ if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ dir=$ladir
+ absdir=$abs_ladir
+ # Remove this search path later
+ func_append notinst_path " $abs_ladir"
+ else
+ dir=$ladir/$objdir
+ absdir=$abs_ladir/$objdir
+ # Remove this search path later
+ func_append notinst_path " $abs_ladir"
+ fi
+ fi # $installed = yes
+ func_stripname 'lib' '.la' "$laname"
+ name=$func_stripname_result
+
+ # This library was specified with -dlpreopen.
+ if test dlpreopen = "$pass"; then
+ if test -z "$libdir" && test prog = "$linkmode"; then
+ func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'"
+ fi
+ case $host in
+ # special handling for platforms with PE-DLLs.
+ *cygwin* | *mingw* | *cegcc* )
+ # Linker will automatically link against shared library if both
+ # static and shared are present. Therefore, ensure we extract
+ # symbols from the import library if a shared library is present
+ # (otherwise, the dlopen module name will be incorrect). We do
+ # this by putting the import library name into $newdlprefiles.
+ # We recover the dlopen module name by 'saving' the la file
+ # name in a special purpose variable, and (later) extracting the
+ # dlname from the la file.
+ if test -n "$dlname"; then
+ func_tr_sh "$dir/$linklib"
+ eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname"
+ func_append newdlprefiles " $dir/$linklib"
+ else
+ func_append newdlprefiles " $dir/$old_library"
+ # Keep a list of preopened convenience libraries to check
+ # that they are being used correctly in the link pass.
+ test -z "$libdir" && \
+ func_append dlpreconveniencelibs " $dir/$old_library"
+ fi
+ ;;
+ * )
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ func_append newdlprefiles " $dir/$old_library"
+ # Keep a list of preopened convenience libraries to check
+ # that they are being used correctly in the link pass.
+ test -z "$libdir" && \
+ func_append dlpreconveniencelibs " $dir/$old_library"
+ # Otherwise, use the dlname, so that lt_dlopen finds it.
+ elif test -n "$dlname"; then
+ func_append newdlprefiles " $dir/$dlname"
+ else
+ func_append newdlprefiles " $dir/$linklib"
+ fi
+ ;;
+ esac
+ fi # $pass = dlpreopen
+
+ if test -z "$libdir"; then
+ # Link the convenience library
+ if test lib = "$linkmode"; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$dir/$old_library $compile_deplibs"
+ finalize_deplibs="$dir/$old_library $finalize_deplibs"
+ else
+ deplibs="$lib $deplibs" # used for prog,scan pass
+ fi
+ continue
+ fi
+
+
+ if test prog = "$linkmode" && test link != "$pass"; then
+ func_append newlib_search_path " $ladir"
+ deplibs="$lib $deplibs"
+
+ linkalldeplibs=false
+ if test no != "$link_all_deplibs" || test -z "$library_names" ||
+ test no = "$build_libtool_libs"; then
+ linkalldeplibs=:
+ fi
+
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) func_stripname '-L' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result"
+ func_append newlib_search_path " $func_resolve_sysroot_result"
+ ;;
+ esac
+ # Need to link against all dependency_libs?
+ if $linkalldeplibs; then
+ deplibs="$deplib $deplibs"
+ else
+ # Need to hardcode shared library paths
+ # or/and link against static libraries
+ newdependency_libs="$deplib $newdependency_libs"
+ fi
+ if $opt_preserve_dup_deps; then
+ case "$tmp_libs " in
+ *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+ esac
+ fi
+ func_append tmp_libs " $deplib"
+ done # for deplib
+ continue
+ fi # $linkmode = prog...
+
+ if test prog,link = "$linkmode,$pass"; then
+ if test -n "$library_names" &&
+ { { test no = "$prefer_static_libs" ||
+ test built,yes = "$prefer_static_libs,$installed"; } ||
+ test -z "$old_library"; }; then
+ # We need to hardcode the library path
+ if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then
+ # Make sure the rpath contains only unique directories.
+ case $temp_rpath: in
+ *"$absdir:"*) ;;
+ *) func_append temp_rpath "$absdir:" ;;
+ esac
+ fi
+
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) func_append compile_rpath " $absdir" ;;
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_rpath " $libdir" ;;
+ esac
+ ;;
+ esac
+ fi # $linkmode,$pass = prog,link...
+
+ if $alldeplibs &&
+ { test pass_all = "$deplibs_check_method" ||
+ { test yes = "$build_libtool_libs" &&
+ test -n "$library_names"; }; }; then
+ # We only need to search for static libraries
+ continue
+ fi
+ fi
+
+ link_static=no # Whether the deplib will be linked statically
+ use_static_libs=$prefer_static_libs
+ if test built = "$use_static_libs" && test yes = "$installed"; then
+ use_static_libs=no
+ fi
+ if test -n "$library_names" &&
+ { test no = "$use_static_libs" || test -z "$old_library"; }; then
+ case $host in
+ *cygwin* | *mingw* | *cegcc* | *os2*)
+ # No point in relinking DLLs because paths are not encoded
+ func_append notinst_deplibs " $lib"
+ need_relink=no
+ ;;
+ *)
+ if test no = "$installed"; then
+ func_append notinst_deplibs " $lib"
+ need_relink=yes
+ fi
+ ;;
+ esac
+ # This is a shared library
+
+ # Warn about portability, can't link against -module's on some
+ # systems (darwin). Don't bleat about dlopened modules though!
+ dlopenmodule=
+ for dlpremoduletest in $dlprefiles; do
+ if test "X$dlpremoduletest" = "X$lib"; then
+ dlopenmodule=$dlpremoduletest
+ break
+ fi
+ done
+ if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then
+ echo
+ if test prog = "$linkmode"; then
+ $ECHO "*** Warning: Linking the executable $output against the loadable module"
+ else
+ $ECHO "*** Warning: Linking the shared library $output against the loadable module"
+ fi
+ $ECHO "*** $linklib is not portable!"
+ fi
+ if test lib = "$linkmode" &&
+ test yes = "$hardcode_into_libs"; then
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) func_append compile_rpath " $absdir" ;;
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_rpath " $libdir" ;;
+ esac
+ ;;
+ esac
+ fi
+
+ if test -n "$old_archive_from_expsyms_cmds"; then
+ # figure out the soname
+ set dummy $library_names
+ shift
+ realname=$1
+ shift
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ # use dlname if we got it. it's perfectly good, no?
+ if test -n "$dlname"; then
+ soname=$dlname
+ elif test -n "$soname_spec"; then
+ # bleh windows
+ case $host in
+ *cygwin* | mingw* | *cegcc* | *os2*)
+ func_arith $current - $age
+ major=$func_arith_result
+ versuffix=-$major
+ ;;
+ esac
+ eval soname=\"$soname_spec\"
+ else
+ soname=$realname
+ fi
+
+ # Make a new name for the extract_expsyms_cmds to use
+ soroot=$soname
+ func_basename "$soroot"
+ soname=$func_basename_result
+ func_stripname 'lib' '.dll' "$soname"
+ newlib=libimp-$func_stripname_result.a
+
+ # If the library has no export list, then create one now
+ if test -f "$output_objdir/$soname-def"; then :
+ else
+ func_verbose "extracting exported symbol list from '$soname'"
+ func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
+ fi
+
+ # Create $newlib
+ if test -f "$output_objdir/$newlib"; then :; else
+ func_verbose "generating import library for '$soname'"
+ func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
+ fi
+ # make sure the library variables are pointing to the new library
+ dir=$output_objdir
+ linklib=$newlib
+ fi # test -n "$old_archive_from_expsyms_cmds"
+
+ if test prog = "$linkmode" || test relink != "$opt_mode"; then
+ add_shlibpath=
+ add_dir=
+ add=
+ lib_linked=yes
+ case $hardcode_action in
+ immediate | unsupported)
+ if test no = "$hardcode_direct"; then
+ add=$dir/$linklib
+ case $host in
+ *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;;
+ *-*-sysv4*uw2*) add_dir=-L$dir ;;
+ *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+ *-*-unixware7*) add_dir=-L$dir ;;
+ *-*-darwin* )
+ # if the lib is a (non-dlopened) module then we cannot
+ # link against it, someone is ignoring the earlier warnings
+ if /usr/bin/file -L $add 2> /dev/null |
+ $GREP ": [^:]* bundle" >/dev/null; then
+ if test "X$dlopenmodule" != "X$lib"; then
+ $ECHO "*** Warning: lib $linklib is a module, not a shared library"
+ if test -z "$old_library"; then
+ echo
+ echo "*** And there doesn't seem to be a static archive available"
+ echo "*** The link will probably fail, sorry"
+ else
+ add=$dir/$old_library
+ fi
+ elif test -n "$old_library"; then
+ add=$dir/$old_library
+ fi
+ fi
+ esac
+ elif test no = "$hardcode_minus_L"; then
+ case $host in
+ *-*-sunos*) add_shlibpath=$dir ;;
+ esac
+ add_dir=-L$dir
+ add=-l$name
+ elif test no = "$hardcode_shlibpath_var"; then
+ add_shlibpath=$dir
+ add=-l$name
+ else
+ lib_linked=no
+ fi
+ ;;
+ relink)
+ if test yes = "$hardcode_direct" &&
+ test no = "$hardcode_direct_absolute"; then
+ add=$dir/$linklib
+ elif test yes = "$hardcode_minus_L"; then
+ add_dir=-L$absdir
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ func_append add_dir " -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add=-l$name
+ elif test yes = "$hardcode_shlibpath_var"; then
+ add_shlibpath=$dir
+ add=-l$name
+ else
+ lib_linked=no
+ fi
+ ;;
+ *) lib_linked=no ;;
+ esac
+
+ if test yes != "$lib_linked"; then
+ func_fatal_configuration "unsupported hardcode properties"
+ fi
+
+ if test -n "$add_shlibpath"; then
+ case :$compile_shlibpath: in
+ *":$add_shlibpath:"*) ;;
+ *) func_append compile_shlibpath "$add_shlibpath:" ;;
+ esac
+ fi
+ if test prog = "$linkmode"; then
+ test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+ test -n "$add" && compile_deplibs="$add $compile_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ if test yes != "$hardcode_direct" &&
+ test yes != "$hardcode_minus_L" &&
+ test yes = "$hardcode_shlibpath_var"; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) func_append finalize_shlibpath "$libdir:" ;;
+ esac
+ fi
+ fi
+ fi
+
+ if test prog = "$linkmode" || test relink = "$opt_mode"; then
+ add_shlibpath=
+ add_dir=
+ add=
+ # Finalize command for both is simple: just hardcode it.
+ if test yes = "$hardcode_direct" &&
+ test no = "$hardcode_direct_absolute"; then
+ add=$libdir/$linklib
+ elif test yes = "$hardcode_minus_L"; then
+ add_dir=-L$libdir
+ add=-l$name
+ elif test yes = "$hardcode_shlibpath_var"; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) func_append finalize_shlibpath "$libdir:" ;;
+ esac
+ add=-l$name
+ elif test yes = "$hardcode_automatic"; then
+ if test -n "$inst_prefix_dir" &&
+ test -f "$inst_prefix_dir$libdir/$linklib"; then
+ add=$inst_prefix_dir$libdir/$linklib
+ else
+ add=$libdir/$linklib
+ fi
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ add_dir=-L$libdir
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ func_append add_dir " -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add=-l$name
+ fi
+
+ if test prog = "$linkmode"; then
+ test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+ test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ fi
+ fi
+ elif test prog = "$linkmode"; then
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test unsupported != "$hardcode_direct"; then
+ test -n "$old_library" && linklib=$old_library
+ compile_deplibs="$dir/$linklib $compile_deplibs"
+ finalize_deplibs="$dir/$linklib $finalize_deplibs"
+ else
+ compile_deplibs="-l$name -L$dir $compile_deplibs"
+ finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+ fi
+ elif test yes = "$build_libtool_libs"; then
+ # Not a shared library
+ if test pass_all != "$deplibs_check_method"; then
+ # We're trying link a shared library against a static one
+ # but the system doesn't support it.
+
+ # Just print a warning and add the library to dependency_libs so
+ # that the program can be linked against the static library.
+ echo
+ $ECHO "*** Warning: This system cannot link to static lib archive $lib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ if test yes = "$module"; then
+ echo "*** But as you try to build a module library, libtool will still create "
+ echo "*** a static module, that should work as long as the dlopening application"
+ echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+ if test -z "$global_symbol_pipe"; then
+ echo
+ echo "*** However, this would only work if libtool was able to extract symbol"
+ echo "*** lists from a program, using 'nm' or equivalent, but libtool could"
+ echo "*** not find such a program. So, this module is probably useless."
+ echo "*** 'nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test no = "$build_old_libs"; then
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ else
+ deplibs="$dir/$old_library $deplibs"
+ link_static=yes
+ fi
+ fi # link shared/static library?
+
+ if test lib = "$linkmode"; then
+ if test -n "$dependency_libs" &&
+ { test yes != "$hardcode_into_libs" ||
+ test yes = "$build_old_libs" ||
+ test yes = "$link_static"; }; then
+ # Extract -R from dependency_libs
+ temp_deplibs=
+ for libdir in $dependency_libs; do
+ case $libdir in
+ -R*) func_stripname '-R' '' "$libdir"
+ temp_xrpath=$func_stripname_result
+ case " $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) func_append xrpath " $temp_xrpath";;
+ esac;;
+ *) func_append temp_deplibs " $libdir";;
+ esac
+ done
+ dependency_libs=$temp_deplibs
+ fi
+
+ func_append newlib_search_path " $absdir"
+ # Link against this library
+ test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+ # ... and its dependency_libs
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ newdependency_libs="$deplib $newdependency_libs"
+ case $deplib in
+ -L*) func_stripname '-L' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result";;
+ *) func_resolve_sysroot "$deplib" ;;
+ esac
+ if $opt_preserve_dup_deps; then
+ case "$tmp_libs " in
+ *" $func_resolve_sysroot_result "*)
+ func_append specialdeplibs " $func_resolve_sysroot_result" ;;
+ esac
+ fi
+ func_append tmp_libs " $func_resolve_sysroot_result"
+ done
+
+ if test no != "$link_all_deplibs"; then
+ # Add the search paths of all dependency libraries
+ for deplib in $dependency_libs; do
+ path=
+ case $deplib in
+ -L*) path=$deplib ;;
+ *.la)
+ func_resolve_sysroot "$deplib"
+ deplib=$func_resolve_sysroot_result
+ func_dirname "$deplib" "" "."
+ dir=$func_dirname_result
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ func_warning "cannot determine absolute directory name of '$dir'"
+ absdir=$dir
+ fi
+ ;;
+ esac
+ if $GREP "^installed=no" $deplib > /dev/null; then
+ case $host in
+ *-*-darwin*)
+ depdepl=
+ eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+ if test -n "$deplibrary_names"; then
+ for tmp in $deplibrary_names; do
+ depdepl=$tmp
+ done
+ if test -f "$absdir/$objdir/$depdepl"; then
+ depdepl=$absdir/$objdir/$depdepl
+ darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+ if test -z "$darwin_install_name"; then
+ darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+ fi
+ func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl"
+ func_append linker_flags " -dylib_file $darwin_install_name:$depdepl"
+ path=
+ fi
+ fi
+ ;;
+ *)
+ path=-L$absdir/$objdir
+ ;;
+ esac
+ else
+ eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ test -z "$libdir" && \
+ func_fatal_error "'$deplib' is not a valid libtool archive"
+ test "$absdir" != "$libdir" && \
+ func_warning "'$deplib' seems to be moved"
+
+ path=-L$absdir
+ fi
+ ;;
+ esac
+ case " $deplibs " in
+ *" $path "*) ;;
+ *) deplibs="$path $deplibs" ;;
+ esac
+ done
+ fi # link_all_deplibs != no
+ fi # linkmode = lib
+ done # for deplib in $libs
+ if test link = "$pass"; then
+ if test prog = "$linkmode"; then
+ compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
+ finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
+ else
+ compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ fi
+ fi
+ dependency_libs=$newdependency_libs
+ if test dlpreopen = "$pass"; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
+ fi
+ if test dlopen != "$pass"; then
+ test conv = "$pass" || {
+ # Make sure lib_search_path contains only unique directories.
+ lib_search_path=
+ for dir in $newlib_search_path; do
+ case "$lib_search_path " in
+ *" $dir "*) ;;
+ *) func_append lib_search_path " $dir" ;;
+ esac
+ done
+ newlib_search_path=
+ }
+
+ if test prog,link = "$linkmode,$pass"; then
+ vars="compile_deplibs finalize_deplibs"
+ else
+ vars=deplibs
+ fi
+ for var in $vars dependency_libs; do
+ # Add libraries to $var in reverse order
+ eval tmp_libs=\"\$$var\"
+ new_libs=
+ for deplib in $tmp_libs; do
+ # FIXME: Pedantically, this is the right thing to do, so
+ # that some nasty dependency loop isn't accidentally
+ # broken:
+ #new_libs="$deplib $new_libs"
+ # Pragmatically, this seems to cause very few problems in
+ # practice:
+ case $deplib in
+ -L*) new_libs="$deplib $new_libs" ;;
+ -R*) ;;
+ *)
+ # And here is the reason: when a library appears more
+ # than once as an explicit dependence of a library, or
+ # is implicitly linked in more than once by the
+ # compiler, it is considered special, and multiple
+ # occurrences thereof are not removed. Compare this
+ # with having the same library being listed as a
+ # dependency of multiple other libraries: in this case,
+ # we know (pedantically, we assume) the library does not
+ # need to be listed more than once, so we keep only the
+ # last copy. This is not always right, but it is rare
+ # enough that we require users that really mean to play
+ # such unportable linking tricks to link the library
+ # using -Wl,-lname, so that libtool does not consider it
+ # for duplicate removal.
+ case " $specialdeplibs " in
+ *" $deplib "*) new_libs="$deplib $new_libs" ;;
+ *)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$deplib $new_libs" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ tmp_libs=
+ for deplib in $new_libs; do
+ case $deplib in
+ -L*)
+ case " $tmp_libs " in
+ *" $deplib "*) ;;
+ *) func_append tmp_libs " $deplib" ;;
+ esac
+ ;;
+ *) func_append tmp_libs " $deplib" ;;
+ esac
+ done
+ eval $var=\"$tmp_libs\"
+ done # for var
+ fi
+
+ # Add Sun CC postdeps if required:
+ test CXX = "$tagname" && {
+ case $host_os in
+ linux*)
+ case `$CC -V 2>&1 | $SED 5q` in
+ *Sun\ C*) # Sun C++ 5.9
+ func_suncc_cstd_abi
+
+ if test no != "$suncc_use_cstd_abi"; then
+ func_append postdeps ' -library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+
+ solaris*)
+ func_cc_basename "$CC"
+ case $func_cc_basename_result in
+ CC* | sunCC*)
+ func_suncc_cstd_abi
+
+ if test no != "$suncc_use_cstd_abi"; then
+ func_append postdeps ' -library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ }
+
+ # Last step: remove runtime libs from dependency_libs
+ # (they stay in deplibs)
+ tmp_libs=
+ for i in $dependency_libs; do
+ case " $predeps $postdeps $compiler_lib_search_path " in
+ *" $i "*)
+ i=
+ ;;
+ esac
+ if test -n "$i"; then
+ func_append tmp_libs " $i"
+ fi
+ done
+ dependency_libs=$tmp_libs
+ done # for pass
+ if test prog = "$linkmode"; then
+ dlfiles=$newdlfiles
+ fi
+ if test prog = "$linkmode" || test lib = "$linkmode"; then
+ dlprefiles=$newdlprefiles
+ fi
+
+ case $linkmode in
+ oldlib)
+ if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
+ func_warning "'-dlopen' is ignored for archives"
+ fi
+
+ case " $deplibs" in
+ *\ -l* | *\ -L*)
+ func_warning "'-l' and '-L' are ignored for archives" ;;
+ esac
+
+ test -n "$rpath" && \
+ func_warning "'-rpath' is ignored for archives"
+
+ test -n "$xrpath" && \
+ func_warning "'-R' is ignored for archives"
+
+ test -n "$vinfo" && \
+ func_warning "'-version-info/-version-number' is ignored for archives"
+
+ test -n "$release" && \
+ func_warning "'-release' is ignored for archives"
+
+ test -n "$export_symbols$export_symbols_regex" && \
+ func_warning "'-export-symbols' is ignored for archives"
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs=$output
+ func_append objs "$old_deplibs"
+ ;;
+
+ lib)
+ # Make sure we only generate libraries of the form 'libNAME.la'.
+ case $outputname in
+ lib*)
+ func_stripname 'lib' '.la' "$outputname"
+ name=$func_stripname_result
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ test no = "$module" \
+ && func_fatal_help "libtool library '$output' must begin with 'lib'"
+
+ if test no != "$need_lib_prefix"; then
+ # Add the "lib" prefix for modules if required
+ func_stripname '' '.la' "$outputname"
+ name=$func_stripname_result
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ else
+ func_stripname '' '.la' "$outputname"
+ libname=$func_stripname_result
+ fi
+ ;;
+ esac
+
+ if test -n "$objs"; then
+ if test pass_all != "$deplibs_check_method"; then
+ func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs"
+ else
+ echo
+ $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
+ $ECHO "*** objects $objs is not portable!"
+ func_append libobjs " $objs"
+ fi
+ fi
+
+ test no = "$dlself" \
+ || func_warning "'-dlopen self' is ignored for libtool libraries"
+
+ set dummy $rpath
+ shift
+ test 1 -lt "$#" \
+ && func_warning "ignoring multiple '-rpath's for a libtool library"
+
+ install_libdir=$1
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test yes = "$build_libtool_libs"; then
+ # Building a libtool convenience library.
+ # Some compilers have problems with a '.al' extension so
+ # convenience libraries should have the same extension an
+ # archive normally would.
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+
+ test -n "$vinfo" && \
+ func_warning "'-version-info/-version-number' is ignored for convenience libraries"
+
+ test -n "$release" && \
+ func_warning "'-release' is ignored for convenience libraries"
+ else
+
+ # Parse the version information argument.
+ save_ifs=$IFS; IFS=:
+ set dummy $vinfo 0 0 0
+ shift
+ IFS=$save_ifs
+
+ test -n "$7" && \
+ func_fatal_help "too many parameters to '-version-info'"
+
+ # convert absolute version numbers to libtool ages
+ # this retains compatibility with .la files and attempts
+ # to make the code below a bit more comprehensible
+
+ case $vinfo_number in
+ yes)
+ number_major=$1
+ number_minor=$2
+ number_revision=$3
+ #
+ # There are really only two kinds -- those that
+ # use the current revision as the major version
+ # and those that subtract age and use age as
+ # a minor version. But, then there is irix
+ # that has an extra 1 added just for fun
+ #
+ case $version_type in
+ # correct linux to gnu/linux during the next big refactor
+ darwin|freebsd-elf|linux|midnightbsd-elf|osf|windows|none)
+ func_arith $number_major + $number_minor
+ current=$func_arith_result
+ age=$number_minor
+ revision=$number_revision
+ ;;
+ freebsd-aout|qnx|sunos)
+ current=$number_major
+ revision=$number_minor
+ age=0
+ ;;
+ irix|nonstopux)
+ func_arith $number_major + $number_minor
+ current=$func_arith_result
+ age=$number_minor
+ revision=$number_minor
+ lt_irix_increment=no
+ ;;
+ *)
+ func_fatal_configuration "$modename: unknown library version type '$version_type'"
+ ;;
+ esac
+ ;;
+ no)
+ current=$1
+ revision=$2
+ age=$3
+ ;;
+ esac
+
+ # Check that each of the things are valid numbers.
+ case $current in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ func_error "CURRENT '$current' must be a nonnegative integer"
+ func_fatal_error "'$vinfo' is not valid version information"
+ ;;
+ esac
+
+ case $revision in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ func_error "REVISION '$revision' must be a nonnegative integer"
+ func_fatal_error "'$vinfo' is not valid version information"
+ ;;
+ esac
+
+ case $age in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ func_error "AGE '$age' must be a nonnegative integer"
+ func_fatal_error "'$vinfo' is not valid version information"
+ ;;
+ esac
+
+ if test "$age" -gt "$current"; then
+ func_error "AGE '$age' is greater than the current interface number '$current'"
+ func_fatal_error "'$vinfo' is not valid version information"
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case $version_type in
+ none) ;;
+
+ darwin)
+ # Like Linux, but with the current version available in
+ # verstring for coding it into the library header
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix=$major.$age.$revision
+ # Darwin ld doesn't like 0 for these options...
+ func_arith $current + 1
+ minor_current=$func_arith_result
+ xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision"
+ verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+ # On Darwin other compilers
+ case $CC in
+ nagfor*)
+ verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision"
+ ;;
+ *)
+ verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+ ;;
+ esac
+ ;;
+
+ freebsd-aout)
+ major=.$current
+ versuffix=.$current.$revision
+ ;;
+
+ freebsd-elf | midnightbsd-elf)
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix=$major.$age.$revision
+ ;;
+
+ irix | nonstopux)
+ if test no = "$lt_irix_increment"; then
+ func_arith $current - $age
+ else
+ func_arith $current - $age + 1
+ fi
+ major=$func_arith_result
+
+ case $version_type in
+ nonstopux) verstring_prefix=nonstopux ;;
+ *) verstring_prefix=sgi ;;
+ esac
+ verstring=$verstring_prefix$major.$revision
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test 0 -ne "$loop"; do
+ func_arith $revision - $loop
+ iface=$func_arith_result
+ func_arith $loop - 1
+ loop=$func_arith_result
+ verstring=$verstring_prefix$major.$iface:$verstring
+ done
+
+ # Before this point, $major must not contain '.'.
+ major=.$major
+ versuffix=$major.$revision
+ ;;
+
+ linux) # correct to gnu/linux during the next big refactor
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix=$major.$age.$revision
+ ;;
+
+ osf)
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix=.$current.$age.$revision
+ verstring=$current.$age.$revision
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test 0 -ne "$loop"; do
+ func_arith $current - $loop
+ iface=$func_arith_result
+ func_arith $loop - 1
+ loop=$func_arith_result
+ verstring=$verstring:$iface.0
+ done
+
+ # Make executables depend on our current version.
+ func_append verstring ":$current.0"
+ ;;
+
+ qnx)
+ major=.$current
+ versuffix=.$current
+ ;;
+
+ sco)
+ major=.$current
+ versuffix=.$current
+ ;;
+
+ sunos)
+ major=.$current
+ versuffix=.$current.$revision
+ ;;
+
+ windows)
+ # Use '-' rather than '.', since we only want one
+ # extension on DOS 8.3 file systems.
+ func_arith $current - $age
+ major=$func_arith_result
+ versuffix=-$major
+ ;;
+
+ *)
+ func_fatal_configuration "unknown library version type '$version_type'"
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ case $version_type in
+ darwin)
+ # we can't check for "0.0" in archive_cmds due to quoting
+ # problems, so we reset it completely
+ verstring=
+ ;;
+ *)
+ verstring=0.0
+ ;;
+ esac
+ if test no = "$need_version"; then
+ versuffix=
+ else
+ versuffix=.0.0
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test yes,no = "$avoid_version,$need_version"; then
+ major=
+ versuffix=
+ verstring=
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test yes = "$allow_undefined"; then
+ if test unsupported = "$allow_undefined_flag"; then
+ if test yes = "$build_old_libs"; then
+ func_warning "undefined symbols not allowed in $host shared libraries; building static only"
+ build_libtool_libs=no
+ else
+ func_fatal_error "can't build $host shared library unless -no-undefined is specified"
+ fi
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag=$no_undefined_flag
+ fi
+
+ fi
+
+ func_generate_dlsyms "$libname" "$libname" :
+ func_append libobjs " $symfileobj"
+ test " " = "$libobjs" && libobjs=
+
+ if test relink != "$opt_mode"; then
+ # Remove our outputs, but don't remove object files since they
+ # may have been created when compiling PIC objects.
+ removelist=
+ tempremovelist=`$ECHO "$output_objdir/*"`
+ for p in $tempremovelist; do
+ case $p in
+ *.$objext | *.gcno)
+ ;;
+ $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*)
+ if test -n "$precious_files_regex"; then
+ if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+ then
+ continue
+ fi
+ fi
+ func_append removelist " $p"
+ ;;
+ *) ;;
+ esac
+ done
+ test -n "$removelist" && \
+ func_show_eval "${RM}r \$removelist"
+ fi
+
+ # Now set the variables for building old libraries.
+ if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then
+ func_append oldlibs " $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP`
+ fi
+
+ # Eliminate all temporary directories.
+ #for path in $notinst_path; do
+ # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"`
+ # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"`
+ # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"`
+ #done
+
+ if test -n "$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ temp_xrpath=
+ for libdir in $xrpath; do
+ func_replace_sysroot "$libdir"
+ func_append temp_xrpath " -R$func_replace_sysroot_result"
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_rpath " $libdir" ;;
+ esac
+ done
+ if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+ fi
+
+ # Make sure dlfiles contains only unique files that won't be dlpreopened
+ old_dlfiles=$dlfiles
+ dlfiles=
+ for lib in $old_dlfiles; do
+ case " $dlprefiles $dlfiles " in
+ *" $lib "*) ;;
+ *) func_append dlfiles " $lib" ;;
+ esac
+ done
+
+ # Make sure dlprefiles contains only unique files
+ old_dlprefiles=$dlprefiles
+ dlprefiles=
+ for lib in $old_dlprefiles; do
+ case "$dlprefiles " in
+ *" $lib "*) ;;
+ *) func_append dlprefiles " $lib" ;;
+ esac
+ done
+
+ if test yes = "$build_libtool_libs"; then
+ if test -n "$rpath"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C library is in the System framework
+ func_append deplibs " System.ltframework"
+ ;;
+ *-*-netbsd*)
+ # Don't link with libc until the a.out ld.so is fixed.
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-midnightbsd*)
+ # Do not include libc due to us having libc/libc_r.
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ ;;
+ *)
+ # Add libc to deplibs on all other systems if necessary.
+ if test yes = "$build_libtool_need_lc"; then
+ func_append deplibs " -lc"
+ fi
+ ;;
+ esac
+ fi
+
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=
+ versuffix=
+ major=
+ newdeplibs=
+ droppeddeps=no
+ case $deplibs_check_method in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behavior.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $opt_dry_run || $RM conftest.c
+ cat > conftest.c </dev/null`
+ $nocaseglob
+ else
+ potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+ fi
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potent_lib" 2>/dev/null |
+ $GREP " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib=$potent_lib
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | $SED 's/.* -> //'`
+ case $potliblink in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;;
+ *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
+ $SED -e 10q |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ func_append newdeplibs " $a_deplib"
+ a_deplib=
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib"; then
+ droppeddeps=yes
+ echo
+ $ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib"; then
+ $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
+ else
+ $ECHO "*** with $libname and none of the candidates passed a file format test"
+ $ECHO "*** using a file magic. Last file checked: $potlib"
+ fi
+ fi
+ ;;
+ *)
+ # Add a -L argument.
+ func_append newdeplibs " $a_deplib"
+ ;;
+ esac
+ done # Gone through all deplibs.
+ ;;
+ match_pattern*)
+ set dummy $deplibs_check_method; shift
+ match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+ for a_deplib in $deplibs; do
+ case $a_deplib in
+ -l*)
+ func_stripname -l '' "$a_deplib"
+ name=$func_stripname_result
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ func_append newdeplibs " $a_deplib"
+ a_deplib=
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib"; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ potlib=$potent_lib # see symlink-check above in file_magic test
+ if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \
+ $EGREP "$match_pattern_regex" > /dev/null; then
+ func_append newdeplibs " $a_deplib"
+ a_deplib=
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib"; then
+ droppeddeps=yes
+ echo
+ $ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib"; then
+ $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
+ else
+ $ECHO "*** with $libname and none of the candidates passed a file format test"
+ $ECHO "*** using a regex pattern. Last file checked: $potlib"
+ fi
+ fi
+ ;;
+ *)
+ # Add a -L argument.
+ func_append newdeplibs " $a_deplib"
+ ;;
+ esac
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=
+ tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ for i in $predeps $postdeps; do
+ # can't use Xsed below, because $i might contain '/'
+ tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"`
+ done
+ fi
+ case $tmp_deplibs in
+ *[!\ \ ]*)
+ echo
+ if test none = "$deplibs_check_method"; then
+ echo "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ echo "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ echo "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ ;;
+ esac
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library with the System framework
+ newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'`
+ ;;
+ esac
+
+ if test yes = "$droppeddeps"; then
+ if test yes = "$module"; then
+ echo
+ echo "*** Warning: libtool could not satisfy all declared inter-library"
+ $ECHO "*** dependencies of module $libname. Therefore, libtool will create"
+ echo "*** a static module, that should work as long as the dlopening"
+ echo "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ echo
+ echo "*** However, this would only work if libtool was able to extract symbol"
+ echo "*** lists from a program, using 'nm' or equivalent, but libtool could"
+ echo "*** not find such a program. So, this module is probably useless."
+ echo "*** 'nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test no = "$build_old_libs"; then
+ oldlibs=$output_objdir/$libname.$libext
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ echo "*** The inter-library dependencies that have been dropped here will be"
+ echo "*** automatically added whenever a program is linked with this library"
+ echo "*** or is declared to -dlopen it."
+
+ if test no = "$allow_undefined"; then
+ echo
+ echo "*** Since this library must not contain undefined symbols,"
+ echo "*** because either the platform does not support them or"
+ echo "*** it was explicitly requested with -no-undefined,"
+ echo "*** libtool will only create a static version of it."
+ if test no = "$build_old_libs"; then
+ oldlibs=$output_objdir/$libname.$libext
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+ # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+ case $host in
+ *-*-darwin*)
+ newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ ;;
+ esac
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $deplibs " in
+ *" -L$path/$objdir "*)
+ func_append new_libs " -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) func_append new_libs " $deplib" ;;
+ esac
+ ;;
+ *) func_append new_libs " $deplib" ;;
+ esac
+ done
+ deplibs=$new_libs
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test yes = "$build_libtool_libs"; then
+ # Remove $wl instances when linking with ld.
+ # FIXME: should test the right _cmds variable.
+ case $archive_cmds in
+ *\$LD\ *) wl= ;;
+ esac
+ if test yes = "$hardcode_into_libs"; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+ rpath=$finalize_rpath
+ test relink = "$opt_mode" || rpath=$compile_rpath$rpath
+ for libdir in $rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ func_replace_sysroot "$libdir"
+ libdir=$func_replace_sysroot_result
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs=$libdir
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ func_append dep_rpath " $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) func_append perm_rpath " $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir=$hardcode_libdirs
+ eval "dep_rpath=\"$hardcode_libdir_flag_spec\""
+ fi
+ if test -n "$runpath_var" && test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ func_append rpath "$dir:"
+ done
+ eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+ fi
+ test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+ fi
+
+ shlibpath=$finalize_shlibpath
+ test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath
+ if test -n "$shlibpath"; then
+ eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+ fi
+
+ # Get the real and link names of the library.
+ eval shared_ext=\"$shrext_cmds\"
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ shift
+ realname=$1
+ shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname=$realname
+ fi
+ if test -z "$dlname"; then
+ dlname=$soname
+ fi
+
+ lib=$output_objdir/$realname
+ linknames=
+ for link
+ do
+ func_append linknames " $link"
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+ test "X$libobjs" = "X " && libobjs=
+
+ delfiles=
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
+ export_symbols=$output_objdir/$libname.uexp
+ func_append delfiles " $export_symbols"
+ fi
+
+ orig_export_symbols=
+ case $host_os in
+ cygwin* | mingw* | cegcc*)
+ if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
+ # exporting using user supplied symfile
+ func_dll_def_p "$export_symbols" || {
+ # and it's NOT already a .def file. Must figure out
+ # which of the given symbols are data symbols and tag
+ # them as such. So, trigger use of export_symbols_cmds.
+ # export_symbols gets reassigned inside the "prepare
+ # the list of exported symbols" if statement, so the
+ # include_expsyms logic still works.
+ orig_export_symbols=$export_symbols
+ export_symbols=
+ always_export_symbols=yes
+ }
+ fi
+ ;;
+ esac
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then
+ func_verbose "generating symbol list for '$libname.la'"
+ export_symbols=$output_objdir/$libname.exp
+ $opt_dry_run || $RM $export_symbols
+ cmds=$export_symbols_cmds
+ save_ifs=$IFS; IFS='~'
+ for cmd1 in $cmds; do
+ IFS=$save_ifs
+ # Take the normal branch if the nm_file_list_spec branch
+ # doesn't work or if tool conversion is not needed.
+ case $nm_file_list_spec~$to_tool_file_cmd in
+ *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*)
+ try_normal_branch=yes
+ eval cmd=\"$cmd1\"
+ func_len " $cmd"
+ len=$func_len_result
+ ;;
+ *)
+ try_normal_branch=no
+ ;;
+ esac
+ if test yes = "$try_normal_branch" \
+ && { test "$len" -lt "$max_cmd_len" \
+ || test "$max_cmd_len" -le -1; }
+ then
+ func_show_eval "$cmd" 'exit $?'
+ skipped_export=false
+ elif test -n "$nm_file_list_spec"; then
+ func_basename "$output"
+ output_la=$func_basename_result
+ save_libobjs=$libobjs
+ save_output=$output
+ output=$output_objdir/$output_la.nm
+ func_to_tool_file "$output"
+ libobjs=$nm_file_list_spec$func_to_tool_file_result
+ func_append delfiles " $output"
+ func_verbose "creating $NM input file list: $output"
+ for obj in $save_libobjs; do
+ func_to_tool_file "$obj"
+ $ECHO "$func_to_tool_file_result"
+ done > "$output"
+ eval cmd=\"$cmd1\"
+ func_show_eval "$cmd" 'exit $?'
+ output=$save_output
+ libobjs=$save_libobjs
+ skipped_export=false
+ else
+ # The command line is too long to execute in one step.
+ func_verbose "using reloadable object file for export list..."
+ skipped_export=:
+ # Break out early, otherwise skipped_export may be
+ # set to false by a later but shorter cmd.
+ break
+ fi
+ done
+ IFS=$save_ifs
+ if test -n "$export_symbols_regex" && test : != "$skipped_export"; then
+ func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ tmp_export_symbols=$export_symbols
+ test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols
+ $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
+ fi
+
+ if test : != "$skipped_export" && test -n "$orig_export_symbols"; then
+ # The given exports_symbols file has to be filtered, so filter it.
+ func_verbose "filter symbol list for '$libname.la' to tag DATA exports"
+ # FIXME: $output_objdir/$libname.filter potentially contains lots of
+ # 's' commands, which not all seds can handle. GNU sed should be fine
+ # though. Also, the filter scales superlinearly with the number of
+ # global variables. join(1) would be nice here, but unfortunately
+ # isn't a blessed tool.
+ $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+ func_append delfiles " $export_symbols $output_objdir/$libname.filter"
+ export_symbols=$output_objdir/$libname.def
+ $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+ fi
+
+ tmp_deplibs=
+ for test_deplib in $deplibs; do
+ case " $convenience " in
+ *" $test_deplib "*) ;;
+ *)
+ func_append tmp_deplibs " $test_deplib"
+ ;;
+ esac
+ done
+ deplibs=$tmp_deplibs
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec" &&
+ test yes = "$compiler_needs_object" &&
+ test -z "$libobjs"; then
+ # extract the archives, so we have objects to list.
+ # TODO: could optimize this to just extract one archive.
+ whole_archive_flag_spec=
+ fi
+ if test -n "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ test "X$libobjs" = "X " && libobjs=
+ else
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $convenience
+ func_append libobjs " $func_extract_archives_result"
+ test "X$libobjs" = "X " && libobjs=
+ fi
+ fi
+
+ if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ func_append linker_flags " $flag"
+ fi
+
+ # Make a backup of the uninstalled library when relinking
+ if test relink = "$opt_mode"; then
+ $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
+ fi
+
+ # Do each of the archive commands.
+ if test yes = "$module" && test -n "$module_cmds"; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ eval test_cmds=\"$module_expsym_cmds\"
+ cmds=$module_expsym_cmds
+ else
+ eval test_cmds=\"$module_cmds\"
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval test_cmds=\"$archive_expsym_cmds\"
+ cmds=$archive_expsym_cmds
+ else
+ eval test_cmds=\"$archive_cmds\"
+ cmds=$archive_cmds
+ fi
+ fi
+
+ if test : != "$skipped_export" &&
+ func_len " $test_cmds" &&
+ len=$func_len_result &&
+ test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ :
+ else
+ # The command line is too long to link in one step, link piecewise
+ # or, if using GNU ld and skipped_export is not :, use a linker
+ # script.
+
+ # Save the value of $output and $libobjs because we want to
+ # use them later. If we have whole_archive_flag_spec, we
+ # want to use save_libobjs as it was before
+ # whole_archive_flag_spec was expanded, because we can't
+ # assume the linker understands whole_archive_flag_spec.
+ # This may have to be revisited, in case too many
+ # convenience libraries get linked in and end up exceeding
+ # the spec.
+ if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ fi
+ save_output=$output
+ func_basename "$output"
+ output_la=$func_basename_result
+
+ # Clear the reloadable object creation command queue and
+ # initialize k to one.
+ test_cmds=
+ concat_cmds=
+ objlist=
+ last_robj=
+ k=1
+
+ if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then
+ output=$output_objdir/$output_la.lnkscript
+ func_verbose "creating GNU ld script: $output"
+ echo 'INPUT (' > $output
+ for obj in $save_libobjs
+ do
+ func_to_tool_file "$obj"
+ $ECHO "$func_to_tool_file_result" >> $output
+ done
+ echo ')' >> $output
+ func_append delfiles " $output"
+ func_to_tool_file "$output"
+ output=$func_to_tool_file_result
+ elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then
+ output=$output_objdir/$output_la.lnk
+ func_verbose "creating linker input file list: $output"
+ : > $output
+ set x $save_libobjs
+ shift
+ firstobj=
+ if test yes = "$compiler_needs_object"; then
+ firstobj="$1 "
+ shift
+ fi
+ for obj
+ do
+ func_to_tool_file "$obj"
+ $ECHO "$func_to_tool_file_result" >> $output
+ done
+ func_append delfiles " $output"
+ func_to_tool_file "$output"
+ output=$firstobj\"$file_list_spec$func_to_tool_file_result\"
+ else
+ if test -n "$save_libobjs"; then
+ func_verbose "creating reloadable object files..."
+ output=$output_objdir/$output_la-$k.$objext
+ eval test_cmds=\"$reload_cmds\"
+ func_len " $test_cmds"
+ len0=$func_len_result
+ len=$len0
+
+ # Loop over the list of objects to be linked.
+ for obj in $save_libobjs
+ do
+ func_len " $obj"
+ func_arith $len + $func_len_result
+ len=$func_arith_result
+ if test -z "$objlist" ||
+ test "$len" -lt "$max_cmd_len"; then
+ func_append objlist " $obj"
+ else
+ # The command $test_cmds is almost too long, add a
+ # command to the queue.
+ if test 1 -eq "$k"; then
+ # The first file doesn't have a previous command to add.
+ reload_objs=$objlist
+ eval concat_cmds=\"$reload_cmds\"
+ else
+ # All subsequent reloadable object files will link in
+ # the last one created.
+ reload_objs="$objlist $last_robj"
+ eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\"
+ fi
+ last_robj=$output_objdir/$output_la-$k.$objext
+ func_arith $k + 1
+ k=$func_arith_result
+ output=$output_objdir/$output_la-$k.$objext
+ objlist=" $obj"
+ func_len " $last_robj"
+ func_arith $len0 + $func_len_result
+ len=$func_arith_result
+ fi
+ done
+ # Handle the remaining objects by creating one last
+ # reloadable object file. All subsequent reloadable object
+ # files will link in the last one created.
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ reload_objs="$objlist $last_robj"
+ eval concat_cmds=\"\$concat_cmds$reload_cmds\"
+ if test -n "$last_robj"; then
+ eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+ fi
+ func_append delfiles " $output"
+
+ else
+ output=
+ fi
+
+ ${skipped_export-false} && {
+ func_verbose "generating symbol list for '$libname.la'"
+ export_symbols=$output_objdir/$libname.exp
+ $opt_dry_run || $RM $export_symbols
+ libobjs=$output
+ # Append the command to create the export file.
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
+ if test -n "$last_robj"; then
+ eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+ fi
+ }
+
+ test -n "$save_libobjs" &&
+ func_verbose "creating a temporary reloadable object file: $output"
+
+ # Loop through the commands generated above and execute them.
+ save_ifs=$IFS; IFS='~'
+ for cmd in $concat_cmds; do
+ IFS=$save_ifs
+ $opt_quiet || {
+ func_quote_arg expand,pretty "$cmd"
+ eval "func_echo $func_quote_arg_result"
+ }
+ $opt_dry_run || eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test relink = "$opt_mode"; then
+ ( cd "$output_objdir" && \
+ $RM "${realname}T" && \
+ $MV "${realname}U" "$realname" )
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS=$save_ifs
+
+ if test -n "$export_symbols_regex" && ${skipped_export-false}; then
+ func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+
+ ${skipped_export-false} && {
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ tmp_export_symbols=$export_symbols
+ test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols
+ $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
+ fi
+
+ if test -n "$orig_export_symbols"; then
+ # The given exports_symbols file has to be filtered, so filter it.
+ func_verbose "filter symbol list for '$libname.la' to tag DATA exports"
+ # FIXME: $output_objdir/$libname.filter potentially contains lots of
+ # 's' commands, which not all seds can handle. GNU sed should be fine
+ # though. Also, the filter scales superlinearly with the number of
+ # global variables. join(1) would be nice here, but unfortunately
+ # isn't a blessed tool.
+ $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+ func_append delfiles " $export_symbols $output_objdir/$libname.filter"
+ export_symbols=$output_objdir/$libname.def
+ $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+ fi
+ }
+
+ libobjs=$output
+ # Restore the value of output.
+ output=$save_output
+
+ if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ test "X$libobjs" = "X " && libobjs=
+ fi
+ # Expand the library linking commands again to reset the
+ # value of $libobjs for piecewise linking.
+
+ # Do each of the archive commands.
+ if test yes = "$module" && test -n "$module_cmds"; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ cmds=$module_expsym_cmds
+ else
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ cmds=$archive_expsym_cmds
+ else
+ cmds=$archive_cmds
+ fi
+ fi
+ fi
+
+ if test -n "$delfiles"; then
+ # Append the command to remove temporary files to $cmds.
+ eval cmds=\"\$cmds~\$RM $delfiles\"
+ fi
+
+ # Add any objects from preloaded convenience libraries
+ if test -n "$dlprefiles"; then
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $dlprefiles
+ func_append libobjs " $func_extract_archives_result"
+ test "X$libobjs" = "X " && libobjs=
+ fi
+
+ save_ifs=$IFS; IFS='~'
+ for cmd in $cmds; do
+ IFS=$sp$nl
+ eval cmd=\"$cmd\"
+ IFS=$save_ifs
+ $opt_quiet || {
+ func_quote_arg expand,pretty "$cmd"
+ eval "func_echo $func_quote_arg_result"
+ }
+ $opt_dry_run || eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test relink = "$opt_mode"; then
+ ( cd "$output_objdir" && \
+ $RM "${realname}T" && \
+ $MV "${realname}U" "$realname" )
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS=$save_ifs
+
+ # Restore the uninstalled library and exit
+ if test relink = "$opt_mode"; then
+ $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
+
+ if test -n "$convenience"; then
+ if test -z "$whole_archive_flag_spec"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test yes = "$module" || test yes = "$export_dynamic"; then
+ # On all known operating systems, these are identical.
+ dlname=$soname
+ fi
+ fi
+ ;;
+
+ obj)
+ if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
+ func_warning "'-dlopen' is ignored for objects"
+ fi
+
+ case " $deplibs" in
+ *\ -l* | *\ -L*)
+ func_warning "'-l' and '-L' are ignored for objects" ;;
+ esac
+
+ test -n "$rpath" && \
+ func_warning "'-rpath' is ignored for objects"
+
+ test -n "$xrpath" && \
+ func_warning "'-R' is ignored for objects"
+
+ test -n "$vinfo" && \
+ func_warning "'-version-info' is ignored for objects"
+
+ test -n "$release" && \
+ func_warning "'-release' is ignored for objects"
+
+ case $output in
+ *.lo)
+ test -n "$objs$old_deplibs" && \
+ func_fatal_error "cannot build library object '$output' from non-libtool objects"
+
+ libobj=$output
+ func_lo2o "$libobj"
+ obj=$func_lo2o_result
+ ;;
+ *)
+ libobj=
+ obj=$output
+ ;;
+ esac
+
+ # Delete the old objects.
+ $opt_dry_run || $RM $obj $libobj
+
+ # Objects from convenience libraries. This assumes
+ # single-version convenience libraries. Whenever we create
+ # different ones for PIC/non-PIC, this we'll have to duplicate
+ # the extraction.
+ reload_conv_objs=
+ gentop=
+ # if reload_cmds runs $LD directly, get rid of -Wl from
+ # whole_archive_flag_spec and hope we can get by with turning comma
+ # into space.
+ case $reload_cmds in
+ *\$LD[\ \$]*) wl= ;;
+ esac
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+ test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
+ reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags
+ else
+ gentop=$output_objdir/${obj}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $convenience
+ reload_conv_objs="$reload_objs $func_extract_archives_result"
+ fi
+ fi
+
+ # If we're not building shared, we need to use non_pic_objs
+ test yes = "$build_libtool_libs" || libobjs=$non_pic_objects
+
+ # Create the old-style object.
+ reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs
+
+ output=$obj
+ func_execute_cmds "$reload_cmds" 'exit $?'
+
+ # Exit if we aren't doing a library object file.
+ if test -z "$libobj"; then
+ if test -n "$gentop"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ test yes = "$build_libtool_libs" || {
+ if test -n "$gentop"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ # $show "echo timestamp > $libobj"
+ # $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
+ exit $EXIT_SUCCESS
+ }
+
+ if test -n "$pic_flag" || test default != "$pic_mode"; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs $reload_conv_objs"
+ output=$libobj
+ func_execute_cmds "$reload_cmds" 'exit $?'
+ fi
+
+ if test -n "$gentop"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ prog)
+ case $host in
+ *cygwin*) func_stripname '' '.exe' "$output"
+ output=$func_stripname_result.exe;;
+ esac
+ test -n "$vinfo" && \
+ func_warning "'-version-info' is ignored for programs"
+
+ test -n "$release" && \
+ func_warning "'-release' is ignored for programs"
+
+ $preload \
+ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \
+ && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support."
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'`
+ finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'`
+ ;;
+ esac
+
+ case $host in
+ *-*-darwin*)
+ # Don't allow lazy linking, it breaks C++ global constructors
+ # But is supposedly fixed on 10.4 or later (yay!).
+ if test CXX = "$tagname"; then
+ case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
+ 10.[0123])
+ func_append compile_command " $wl-bind_at_load"
+ func_append finalize_command " $wl-bind_at_load"
+ ;;
+ esac
+ fi
+ # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+ compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ ;;
+ esac
+
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $compile_deplibs " in
+ *" -L$path/$objdir "*)
+ func_append new_libs " -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $compile_deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) func_append new_libs " $deplib" ;;
+ esac
+ ;;
+ *) func_append new_libs " $deplib" ;;
+ esac
+ done
+ compile_deplibs=$new_libs
+
+
+ func_append compile_command " $compile_deplibs"
+ func_append finalize_command " $finalize_deplibs"
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_rpath " $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs=$libdir
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ func_append rpath " $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) func_append perm_rpath " $libdir" ;;
+ esac
+ fi
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+ testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$libdir:"*) ;;
+ ::) dllsearchpath=$libdir;;
+ *) func_append dllsearchpath ":$libdir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ ::) dllsearchpath=$testbindir;;
+ *) func_append dllsearchpath ":$testbindir";;
+ esac
+ ;;
+ esac
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir=$hardcode_libdirs
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath=$rpath
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs=$libdir
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ func_append rpath " $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_perm_rpath " $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir=$hardcode_libdirs
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath=$rpath
+
+ if test -n "$libobjs" && test yes = "$build_old_libs"; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+ finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+ fi
+
+ func_generate_dlsyms "$outputname" "@PROGRAM@" false
+
+ # template prelinking step
+ if test -n "$prelink_cmds"; then
+ func_execute_cmds "$prelink_cmds" 'exit $?'
+ fi
+
+ wrappers_required=:
+ case $host in
+ *cegcc* | *mingw32ce*)
+ # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
+ wrappers_required=false
+ ;;
+ *cygwin* | *mingw* )
+ test yes = "$build_libtool_libs" || wrappers_required=false
+ ;;
+ *)
+ if test no = "$need_relink" || test yes != "$build_libtool_libs"; then
+ wrappers_required=false
+ fi
+ ;;
+ esac
+ $wrappers_required || {
+ # Replace the output file specification.
+ compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+ link_command=$compile_command$compile_rpath
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ exit_status=0
+ func_show_eval "$link_command" 'exit_status=$?'
+
+ if test -n "$postlink_cmds"; then
+ func_to_tool_file "$output"
+ postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+ func_execute_cmds "$postlink_cmds" 'exit $?'
+ fi
+
+ # Delete the generated files.
+ if test -f "$output_objdir/${outputname}S.$objext"; then
+ func_show_eval '$RM "$output_objdir/${outputname}S.$objext"'
+ fi
+
+ exit $exit_status
+ }
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ func_append rpath "$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ func_append rpath "$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test yes = "$no_install"; then
+ # We don't need to create a wrapper script.
+ link_command=$compile_var$compile_command$compile_rpath
+ # Replace the output file specification.
+ link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+ # Delete the old output file.
+ $opt_dry_run || $RM $output
+ # Link the executable and exit
+ func_show_eval "$link_command" 'exit $?'
+
+ if test -n "$postlink_cmds"; then
+ func_to_tool_file "$output"
+ postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+ func_execute_cmds "$postlink_cmds" 'exit $?'
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ case $hardcode_action,$fast_install in
+ relink,*)
+ # Fast installation is not supported
+ link_command=$compile_var$compile_command$compile_rpath
+ relink_command=$finalize_var$finalize_command$finalize_rpath
+
+ func_warning "this platform does not like uninstalled shared libraries"
+ func_warning "'$output' will be relinked during installation"
+ ;;
+ *,yes)
+ link_command=$finalize_var$compile_command$finalize_rpath
+ relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
+ ;;
+ *,no)
+ link_command=$compile_var$compile_command$compile_rpath
+ relink_command=$finalize_var$finalize_command$finalize_rpath
+ ;;
+ *,needless)
+ link_command=$finalize_var$compile_command$finalize_rpath
+ relink_command=
+ ;;
+ esac
+
+ # Replace the output file specification.
+ link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ func_show_eval "$link_command" 'exit $?'
+
+ if test -n "$postlink_cmds"; then
+ func_to_tool_file "$output_objdir/$outputname"
+ postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+ func_execute_cmds "$postlink_cmds" 'exit $?'
+ fi
+
+ # Now create the wrapper script.
+ func_verbose "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ func_quote_arg pretty "$var_value"
+ relink_command="$var=$func_quote_arg_result; export $var; $relink_command"
+ fi
+ done
+ func_quote eval cd "`pwd`"
+ func_quote_arg pretty,unquoted "($func_quote_result; $relink_command)"
+ relink_command=$func_quote_arg_unquoted_result
+ fi
+
+ # Only actually do things if not in dry run mode.
+ $opt_dry_run || {
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) func_stripname '' '.exe' "$output"
+ output=$func_stripname_result ;;
+ esac
+ # test for cygwin because mv fails w/o .exe extensions
+ case $host in
+ *cygwin*)
+ exeext=.exe
+ func_stripname '' '.exe' "$outputname"
+ outputname=$func_stripname_result ;;
+ *) exeext= ;;
+ esac
+ case $host in
+ *cygwin* | *mingw* )
+ func_dirname_and_basename "$output" "" "."
+ output_name=$func_basename_result
+ output_path=$func_dirname_result
+ cwrappersource=$output_path/$objdir/lt-$output_name.c
+ cwrapper=$output_path/$output_name.exe
+ $RM $cwrappersource $cwrapper
+ trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+ func_emit_cwrapperexe_src > $cwrappersource
+
+ # The wrapper executable is built using the $host compiler,
+ # because it contains $host paths and files. If cross-
+ # compiling, it, like the target executable, must be
+ # executed on the $host or under an emulation environment.
+ $opt_dry_run || {
+ $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
+ $STRIP $cwrapper
+ }
+
+ # Now, create the wrapper script for func_source use:
+ func_ltwrapper_scriptname $cwrapper
+ $RM $func_ltwrapper_scriptname_result
+ trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
+ $opt_dry_run || {
+ # note: this script will not be executed, so do not chmod.
+ if test "x$build" = "x$host"; then
+ $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
+ else
+ func_emit_wrapper no > $func_ltwrapper_scriptname_result
+ fi
+ }
+ ;;
+ * )
+ $RM $output
+ trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
+
+ func_emit_wrapper no > $output
+ chmod +x $output
+ ;;
+ esac
+ }
+ exit $EXIT_SUCCESS
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ case $build_libtool_libs in
+ convenience)
+ oldobjs="$libobjs_save $symfileobj"
+ addlibs=$convenience
+ build_libtool_libs=no
+ ;;
+ module)
+ oldobjs=$libobjs_save
+ addlibs=$old_convenience
+ build_libtool_libs=no
+ ;;
+ *)
+ oldobjs="$old_deplibs $non_pic_objects"
+ $preload && test -f "$symfileobj" \
+ && func_append oldobjs " $symfileobj"
+ addlibs=$old_convenience
+ ;;
+ esac
+
+ if test -n "$addlibs"; then
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $addlibs
+ func_append oldobjs " $func_extract_archives_result"
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then
+ cmds=$old_archive_from_new_cmds
+ else
+
+ # Add any objects from preloaded convenience libraries
+ if test -n "$dlprefiles"; then
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $dlprefiles
+ func_append oldobjs " $func_extract_archives_result"
+ fi
+
+ # POSIX demands no paths to be encoded in archives. We have
+ # to avoid creating archives with duplicate basenames if we
+ # might have to extract them afterwards, e.g., when creating a
+ # static archive out of a convenience library, or when linking
+ # the entirety of a libtool archive into another (currently
+ # not supported by libtool).
+ if (for obj in $oldobjs
+ do
+ func_basename "$obj"
+ $ECHO "$func_basename_result"
+ done | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ echo "copying selected object files to avoid basename conflicts..."
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+ func_mkdir_p "$gentop"
+ save_oldobjs=$oldobjs
+ oldobjs=
+ counter=1
+ for obj in $save_oldobjs
+ do
+ func_basename "$obj"
+ objbase=$func_basename_result
+ case " $oldobjs " in
+ " ") oldobjs=$obj ;;
+ *[\ /]"$objbase "*)
+ while :; do
+ # Make sure we don't pick an alternate name that also
+ # overlaps.
+ newobj=lt$counter-$objbase
+ func_arith $counter + 1
+ counter=$func_arith_result
+ case " $oldobjs " in
+ *[\ /]"$newobj "*) ;;
+ *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+ esac
+ done
+ func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+ func_append oldobjs " $gentop/$newobj"
+ ;;
+ *) func_append oldobjs " $obj" ;;
+ esac
+ done
+ fi
+ func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
+ tool_oldlib=$func_to_tool_file_result
+ eval cmds=\"$old_archive_cmds\"
+
+ func_len " $cmds"
+ len=$func_len_result
+ if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ cmds=$old_archive_cmds
+ elif test -n "$archiver_list_spec"; then
+ func_verbose "using command file archive linking..."
+ for obj in $oldobjs
+ do
+ func_to_tool_file "$obj"
+ $ECHO "$func_to_tool_file_result"
+ done > $output_objdir/$libname.libcmd
+ func_to_tool_file "$output_objdir/$libname.libcmd"
+ oldobjs=" $archiver_list_spec$func_to_tool_file_result"
+ cmds=$old_archive_cmds
+ else
+ # the command line is too long to link in one step, link in parts
+ func_verbose "using piecewise archive linking..."
+ save_RANLIB=$RANLIB
+ RANLIB=:
+ objlist=
+ concat_cmds=
+ save_oldobjs=$oldobjs
+ oldobjs=
+ # Is there a better way of finding the last object in the list?
+ for obj in $save_oldobjs
+ do
+ last_oldobj=$obj
+ done
+ eval test_cmds=\"$old_archive_cmds\"
+ func_len " $test_cmds"
+ len0=$func_len_result
+ len=$len0
+ for obj in $save_oldobjs
+ do
+ func_len " $obj"
+ func_arith $len + $func_len_result
+ len=$func_arith_result
+ func_append objlist " $obj"
+ if test "$len" -lt "$max_cmd_len"; then
+ :
+ else
+ # the above command should be used before it gets too long
+ oldobjs=$objlist
+ if test "$obj" = "$last_oldobj"; then
+ RANLIB=$save_RANLIB
+ fi
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\$concat_cmds$old_archive_cmds\"
+ objlist=
+ len=$len0
+ fi
+ done
+ RANLIB=$save_RANLIB
+ oldobjs=$objlist
+ if test -z "$oldobjs"; then
+ eval cmds=\"\$concat_cmds\"
+ else
+ eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+ fi
+ fi
+ fi
+ func_execute_cmds "$cmds" 'exit $?'
+ done
+
+ test -n "$generated" && \
+ func_show_eval "${RM}r$generated"
+
+ # Now create the libtool archive.
+ case $output in
+ *.la)
+ old_library=
+ test yes = "$build_old_libs" && old_library=$libname.$libext
+ func_verbose "creating $output"
+
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ func_quote_arg pretty,unquoted "$var_value"
+ relink_command="$var=$func_quote_arg_unquoted_result; export $var; $relink_command"
+ fi
+ done
+ # Quote the link command for shipping.
+ func_quote eval cd "`pwd`"
+ relink_command="($func_quote_result; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+ func_quote_arg pretty,unquoted "$relink_command"
+ relink_command=$func_quote_arg_unquoted_result
+ if test yes = "$hardcode_automatic"; then
+ relink_command=
+ fi
+
+ # Only create the output if not a dry run.
+ $opt_dry_run || {
+ for installed in no yes; do
+ if test yes = "$installed"; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output=$output_objdir/${outputname}i
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ *.la)
+ func_basename "$deplib"
+ name=$func_basename_result
+ func_resolve_sysroot "$deplib"
+ eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result`
+ test -z "$libdir" && \
+ func_fatal_error "'$deplib' is not a valid libtool archive"
+ func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name"
+ ;;
+ -L*)
+ func_stripname -L '' "$deplib"
+ func_replace_sysroot "$func_stripname_result"
+ func_append newdependency_libs " -L$func_replace_sysroot_result"
+ ;;
+ -R*)
+ func_stripname -R '' "$deplib"
+ func_replace_sysroot "$func_stripname_result"
+ func_append newdependency_libs " -R$func_replace_sysroot_result"
+ ;;
+ *) func_append newdependency_libs " $deplib" ;;
+ esac
+ done
+ dependency_libs=$newdependency_libs
+ newdlfiles=
+
+ for lib in $dlfiles; do
+ case $lib in
+ *.la)
+ func_basename "$lib"
+ name=$func_basename_result
+ eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ test -z "$libdir" && \
+ func_fatal_error "'$lib' is not a valid libtool archive"
+ func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name"
+ ;;
+ *) func_append newdlfiles " $lib" ;;
+ esac
+ done
+ dlfiles=$newdlfiles
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ *.la)
+ # Only pass preopened files to the pseudo-archive (for
+ # eventual linking with the app. that links it) if we
+ # didn't already link the preopened objects directly into
+ # the library:
+ func_basename "$lib"
+ name=$func_basename_result
+ eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ test -z "$libdir" && \
+ func_fatal_error "'$lib' is not a valid libtool archive"
+ func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name"
+ ;;
+ esac
+ done
+ dlprefiles=$newdlprefiles
+ else
+ newdlfiles=
+ for lib in $dlfiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ func_append newdlfiles " $abs"
+ done
+ dlfiles=$newdlfiles
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ func_append newdlprefiles " $abs"
+ done
+ dlprefiles=$newdlprefiles
+ fi
+ $RM $output
+ # place dlname in correct position for cygwin
+ # In fact, it would be nice if we could use this code for all target
+ # systems that can't hard-code library paths into their executables
+ # and that have no shared library path variable independent of PATH,
+ # but it turns out we can't easily determine that from inspecting
+ # libtool variables, so we have to hard-code the OSs to which it
+ # applies here; at the moment, that means platforms that use the PE
+ # object format with DLL files. See the long comment at the top of
+ # tests/bindir.at for full details.
+ tdlname=$dlname
+ case $host,$output,$installed,$module,$dlname in
+ *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)
+ # If a -bindir argument was supplied, place the dll there.
+ if test -n "$bindir"; then
+ func_relative_path "$install_libdir" "$bindir"
+ tdlname=$func_relative_path_result/$dlname
+ else
+ # Otherwise fall back on heuristic.
+ tdlname=../bin/$dlname
+ fi
+ ;;
+ esac
+ $ECHO > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Linker flags that cannot go in dependency_libs.
+inherited_linker_flags='$new_inherited_linker_flags'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Names of additional weak libraries provided by this library
+weak_library_names='$weak_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+ if test no,yes = "$installed,$need_relink"; then
+ $ECHO >> $output "\
+relink_command=\"$relink_command\""
+ fi
+ done
+ }
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
+ ;;
+ esac
+ exit $EXIT_SUCCESS
+}
+
+if test link = "$opt_mode" || test relink = "$opt_mode"; then
+ func_mode_link ${1+"$@"}
+fi
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+ $debug_cmd
+
+ RM=$nonopt
+ files=
+ rmforce=false
+ exit_status=0
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic=$magic
+
+ for arg
+ do
+ case $arg in
+ -f) func_append RM " $arg"; rmforce=: ;;
+ -*) func_append RM " $arg" ;;
+ *) func_append files " $arg" ;;
+ esac
+ done
+
+ test -z "$RM" && \
+ func_fatal_help "you must specify an RM program"
+
+ rmdirs=
+
+ for file in $files; do
+ func_dirname "$file" "" "."
+ dir=$func_dirname_result
+ if test . = "$dir"; then
+ odir=$objdir
+ else
+ odir=$dir/$objdir
+ fi
+ func_basename "$file"
+ name=$func_basename_result
+ test uninstall = "$opt_mode" && odir=$dir
+
+ # Remember odir for removal later, being careful to avoid duplicates
+ if test clean = "$opt_mode"; then
+ case " $rmdirs " in
+ *" $odir "*) ;;
+ *) func_append rmdirs " $odir" ;;
+ esac
+ fi
+
+ # Don't error if the file doesn't exist and rm -f was used.
+ if { test -L "$file"; } >/dev/null 2>&1 ||
+ { test -h "$file"; } >/dev/null 2>&1 ||
+ test -f "$file"; then
+ :
+ elif test -d "$file"; then
+ exit_status=1
+ continue
+ elif $rmforce; then
+ continue
+ fi
+
+ rmfiles=$file
+
+ case $name in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if func_lalib_p "$file"; then
+ func_source $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ func_append rmfiles " $odir/$n"
+ done
+ test -n "$old_library" && func_append rmfiles " $odir/$old_library"
+
+ case $opt_mode in
+ clean)
+ case " $library_names " in
+ *" $dlname "*) ;;
+ *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;;
+ esac
+ test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i"
+ ;;
+ uninstall)
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1'
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1'
+ fi
+ # FIXME: should reinstall the best remaining shared library.
+ ;;
+ esac
+ fi
+ ;;
+
+ *.lo)
+ # Possibly a libtool object, so verify it.
+ if func_lalib_p "$file"; then
+
+ # Read the .lo file
+ func_source $dir/$name
+
+ # Add PIC object to the list of files to remove.
+ if test -n "$pic_object" && test none != "$pic_object"; then
+ func_append rmfiles " $dir/$pic_object"
+ fi
+
+ # Add non-PIC object to the list of files to remove.
+ if test -n "$non_pic_object" && test none != "$non_pic_object"; then
+ func_append rmfiles " $dir/$non_pic_object"
+ fi
+ fi
+ ;;
+
+ *)
+ if test clean = "$opt_mode"; then
+ noexename=$name
+ case $file in
+ *.exe)
+ func_stripname '' '.exe' "$file"
+ file=$func_stripname_result
+ func_stripname '' '.exe' "$name"
+ noexename=$func_stripname_result
+ # $file with .exe has already been added to rmfiles,
+ # add $file without .exe
+ func_append rmfiles " $file"
+ ;;
+ esac
+ # Do a test to see if this is a libtool program.
+ if func_ltwrapper_p "$file"; then
+ if func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_scriptname "$file"
+ relink_command=
+ func_source $func_ltwrapper_scriptname_result
+ func_append rmfiles " $func_ltwrapper_scriptname_result"
+ else
+ relink_command=
+ func_source $dir/$noexename
+ fi
+
+ # note $name still contains .exe if it was in $file originally
+ # as does the version of $file that was added into $rmfiles
+ func_append rmfiles " $odir/$name $odir/${name}S.$objext"
+ if test yes = "$fast_install" && test -n "$relink_command"; then
+ func_append rmfiles " $odir/lt-$name"
+ fi
+ if test "X$noexename" != "X$name"; then
+ func_append rmfiles " $odir/lt-$noexename.c"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ func_show_eval "$RM $rmfiles" 'exit_status=1'
+ done
+
+ # Try to remove the $objdir's in the directories where we deleted files
+ for dir in $rmdirs; do
+ if test -d "$dir"; then
+ func_show_eval "rmdir $dir >/dev/null 2>&1"
+ fi
+ done
+
+ exit $exit_status
+}
+
+if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then
+ func_mode_uninstall ${1+"$@"}
+fi
+
+test -z "$opt_mode" && {
+ help=$generic_help
+ func_fatal_help "you must specify a MODE"
+}
+
+test -z "$exec_cmd" && \
+ func_fatal_help "invalid operation mode '$opt_mode'"
+
+if test -n "$exec_cmd"; then
+ eval exec "$exec_cmd"
+ exit $EXIT_FAILURE
+fi
+
+exit $exit_status
+
+
+# The TAGs below are defined such that we never get into a situation
+# where we disable both kinds of libraries. Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them. This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration. But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4
new file mode 100644
index 0000000..9f35d13
--- /dev/null
+++ b/m4/ax_pthread.m4
@@ -0,0 +1,522 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_pthread.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+#
+# DESCRIPTION
+#
+# This macro figures out how to build C programs using POSIX threads. It
+# sets the PTHREAD_LIBS output variable to the threads library and linker
+# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
+# flags that are needed. (The user can also force certain compiler
+# flags/libs to be tested by setting these environment variables.)
+#
+# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
+# needed for multi-threaded programs (defaults to the value of CC
+# respectively CXX otherwise). (This is necessary on e.g. AIX to use the
+# special cc_r/CC_r compiler alias.)
+#
+# NOTE: You are assumed to not only compile your program with these flags,
+# but also to link with them as well. For example, you might link with
+# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
+# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
+#
+# If you are only building threaded programs, you may wish to use these
+# variables in your default LIBS, CFLAGS, and CC:
+#
+# LIBS="$PTHREAD_LIBS $LIBS"
+# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
+# CC="$PTHREAD_CC"
+# CXX="$PTHREAD_CXX"
+#
+# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
+# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
+# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+#
+# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
+# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
+# PTHREAD_CFLAGS.
+#
+# ACTION-IF-FOUND is a list of shell commands to run if a threads library
+# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
+# is not found. If ACTION-IF-FOUND is not specified, the default action
+# will define HAVE_PTHREAD.
+#
+# Please let the authors know if this macro fails on any platform, or if
+# you have any other suggestions or comments. This macro was based on work
+# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
+# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
+# Alejandro Forero Cuervo to the autoconf macro repository. We are also
+# grateful for the helpful feedback of numerous users.
+#
+# Updated for Autoconf 2.68 by Daniel Richard G.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Steven G. Johnson
+# Copyright (c) 2011 Daniel Richard G.
+# Copyright (c) 2019 Marc Stevens
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see .
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 31
+
+AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
+AC_DEFUN([AX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([AC_PROG_SED])
+AC_LANG_PUSH([C])
+ax_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on Tru64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
+ ax_pthread_save_CC="$CC"
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ ax_pthread_save_LIBS="$LIBS"
+ AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
+ AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
+ AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
+ AC_MSG_RESULT([$ax_pthread_ok])
+ if test "x$ax_pthread_ok" = "xno"; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ CC="$ax_pthread_save_CC"
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ LIBS="$ax_pthread_save_LIBS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items with a "," contain both
+# C compiler flags (before ",") and linker flags (after ","). Other items
+# starting with a "-" are C compiler flags, and remaining items are
+# library names, except for "none" which indicates that we try without
+# any flags at all, and "pthread-config" which is a program returning
+# the flags for the Pth emulation library.
+
+ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
+# (Note: HP C rejects this with "bad form for `-t' option")
+# -pthreads: Solaris/gcc (Note: HP C also rejects)
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads and
+# -D_REENTRANT too), HP C (must be checked before -lpthread, which
+# is present but should not be used directly; and before -mthreads,
+# because the compiler interprets this as "-mt" + "-hreads")
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case $host_os in
+
+ freebsd*)
+
+ # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+ # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+
+ ax_pthread_flags="-kthread lthread $ax_pthread_flags"
+ ;;
+
+ hpux*)
+
+ # From the cc(1) man page: "[-mt] Sets various -D flags to enable
+ # multi-threading and also sets -lpthread."
+
+ ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
+ ;;
+
+ openedition*)
+
+ # IBM z/OS requires a feature-test macro to be defined in order to
+ # enable POSIX threads at all, so give the user a hint if this is
+ # not set. (We don't define these ourselves, as they can affect
+ # other portions of the system API in unpredictable ways.)
+
+ AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
+ [
+# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
+ AX_PTHREAD_ZOS_MISSING
+# endif
+ ],
+ [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
+ ;;
+
+ solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (N.B.: The stubs are missing
+ # pthread_cleanup_push, or rather a function called by this macro,
+ # so we could check for that, but who knows whether they'll stub
+ # that too in a future libc.) So we'll check first for the
+ # standard Solaris way of linking pthreads (-mt -lpthread).
+
+ ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
+ ;;
+esac
+
+# Are we compiling with Clang?
+
+AC_CACHE_CHECK([whether $CC is Clang],
+ [ax_cv_PTHREAD_CLANG],
+ [ax_cv_PTHREAD_CLANG=no
+ # Note that Autoconf sets GCC=yes for Clang as well as GCC
+ if test "x$GCC" = "xyes"; then
+ AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
+ [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
+# if defined(__clang__) && defined(__llvm__)
+ AX_PTHREAD_CC_IS_CLANG
+# endif
+ ],
+ [ax_cv_PTHREAD_CLANG=yes])
+ fi
+ ])
+ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
+
+
+# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
+
+# Note that for GCC and Clang -pthread generally implies -lpthread,
+# except when -nostdlib is passed.
+# This is problematic using libtool to build C++ shared libraries with pthread:
+# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
+# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
+# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
+# To solve this, first try -pthread together with -lpthread for GCC
+
+AS_IF([test "x$GCC" = "xyes"],
+ [ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
+
+# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
+
+AS_IF([test "x$ax_pthread_clang" = "xyes"],
+ [ax_pthread_flags="-pthread,-lpthread -pthread"])
+
+
+# The presence of a feature test macro requesting re-entrant function
+# definitions is, on some systems, a strong hint that pthreads support is
+# correctly enabled
+
+case $host_os in
+ darwin* | hpux* | linux* | osf* | solaris*)
+ ax_pthread_check_macro="_REENTRANT"
+ ;;
+
+ aix*)
+ ax_pthread_check_macro="_THREAD_SAFE"
+ ;;
+
+ *)
+ ax_pthread_check_macro="--"
+ ;;
+esac
+AS_IF([test "x$ax_pthread_check_macro" = "x--"],
+ [ax_pthread_check_cond=0],
+ [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
+
+
+if test "x$ax_pthread_ok" = "xno"; then
+for ax_pthread_try_flag in $ax_pthread_flags; do
+
+ case $ax_pthread_try_flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ *,*)
+ PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
+ PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
+ AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
+ PTHREAD_CFLAGS="$ax_pthread_try_flag"
+ ;;
+
+ pthread-config)
+ AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
+ AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
+ PTHREAD_CFLAGS="`pthread-config --cflags`"
+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
+ PTHREAD_LIBS="-l$ax_pthread_try_flag"
+ ;;
+ esac
+
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ ax_pthread_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include
+# if $ax_pthread_check_cond
+# error "$ax_pthread_check_macro must be defined"
+# endif
+ static void *some_global = NULL;
+ static void routine(void *a)
+ {
+ /* To avoid any unused-parameter or
+ unused-but-set-parameter warning. */
+ some_global = a;
+ }
+ static void *start_routine(void *a) { return a; }],
+ [pthread_t th; pthread_attr_t attr;
+ pthread_create(&th, 0, start_routine, 0);
+ pthread_join(th, 0);
+ pthread_attr_init(&attr);
+ pthread_cleanup_push(routine, 0);
+ pthread_cleanup_pop(0) /* ; */])],
+ [ax_pthread_ok=yes],
+ [])
+
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ LIBS="$ax_pthread_save_LIBS"
+
+ AC_MSG_RESULT([$ax_pthread_ok])
+ AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+
+# Clang needs special handling, because older versions handle the -pthread
+# option in a rather... idiosyncratic way
+
+if test "x$ax_pthread_clang" = "xyes"; then
+
+ # Clang takes -pthread; it has never supported any other flag
+
+ # (Note 1: This will need to be revisited if a system that Clang
+ # supports has POSIX threads in a separate library. This tends not
+ # to be the way of modern systems, but it's conceivable.)
+
+ # (Note 2: On some systems, notably Darwin, -pthread is not needed
+ # to get POSIX threads support; the API is always present and
+ # active. We could reasonably leave PTHREAD_CFLAGS empty. But
+ # -pthread does define _REENTRANT, and while the Darwin headers
+ # ignore this macro, third-party headers might not.)
+
+ # However, older versions of Clang make a point of warning the user
+ # that, in an invocation where only linking and no compilation is
+ # taking place, the -pthread option has no effect ("argument unused
+ # during compilation"). They expect -pthread to be passed in only
+ # when source code is being compiled.
+ #
+ # Problem is, this is at odds with the way Automake and most other
+ # C build frameworks function, which is that the same flags used in
+ # compilation (CFLAGS) are also used in linking. Many systems
+ # supported by AX_PTHREAD require exactly this for POSIX threads
+ # support, and in fact it is often not straightforward to specify a
+ # flag that is used only in the compilation phase and not in
+ # linking. Such a scenario is extremely rare in practice.
+ #
+ # Even though use of the -pthread flag in linking would only print
+ # a warning, this can be a nuisance for well-run software projects
+ # that build with -Werror. So if the active version of Clang has
+ # this misfeature, we search for an option to squash it.
+
+ AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
+ [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
+ [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
+ # Create an alternate version of $ac_link that compiles and
+ # links in two steps (.c -> .o, .o -> exe) instead of one
+ # (.c -> exe), because the warning occurs only in the second
+ # step
+ ax_pthread_save_ac_link="$ac_link"
+ ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
+ ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"`
+ ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
+ AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
+ CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
+ ac_link="$ax_pthread_save_ac_link"
+ AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
+ [ac_link="$ax_pthread_2step_ac_link"
+ AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
+ [break])
+ ])
+ done
+ ac_link="$ax_pthread_save_ac_link"
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
+ ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
+ ])
+
+ case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
+ no | unknown) ;;
+ *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
+ esac
+
+fi # $ax_pthread_clang = yes
+
+
+
+# Various other checks:
+if test "x$ax_pthread_ok" = "xyes"; then
+ ax_pthread_save_CFLAGS="$CFLAGS"
+ ax_pthread_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+
+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+ AC_CACHE_CHECK([for joinable pthread attribute],
+ [ax_cv_PTHREAD_JOINABLE_ATTR],
+ [ax_cv_PTHREAD_JOINABLE_ATTR=unknown
+ for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ],
+ [int attr = $ax_pthread_attr; return attr /* ; */])],
+ [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
+ [])
+ done
+ ])
+ AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
+ test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
+ test "x$ax_pthread_joinable_attr_defined" != "xyes"],
+ [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
+ [$ax_cv_PTHREAD_JOINABLE_ATTR],
+ [Define to necessary symbol if this constant
+ uses a non-standard name on your system.])
+ ax_pthread_joinable_attr_defined=yes
+ ])
+
+ AC_CACHE_CHECK([whether more special flags are required for pthreads],
+ [ax_cv_PTHREAD_SPECIAL_FLAGS],
+ [ax_cv_PTHREAD_SPECIAL_FLAGS=no
+ case $host_os in
+ solaris*)
+ ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
+ ;;
+ esac
+ ])
+ AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
+ test "x$ax_pthread_special_flags_added" != "xyes"],
+ [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
+ ax_pthread_special_flags_added=yes])
+
+ AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
+ [ax_cv_PTHREAD_PRIO_INHERIT],
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]],
+ [[int i = PTHREAD_PRIO_INHERIT;
+ return i;]])],
+ [ax_cv_PTHREAD_PRIO_INHERIT=yes],
+ [ax_cv_PTHREAD_PRIO_INHERIT=no])
+ ])
+ AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
+ test "x$ax_pthread_prio_inherit_defined" != "xyes"],
+ [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
+ ax_pthread_prio_inherit_defined=yes
+ ])
+
+ CFLAGS="$ax_pthread_save_CFLAGS"
+ LIBS="$ax_pthread_save_LIBS"
+
+ # More AIX lossage: compile with *_r variant
+ if test "x$GCC" != "xyes"; then
+ case $host_os in
+ aix*)
+ AS_CASE(["x/$CC"],
+ [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
+ [#handle absolute path differently from PATH based program lookup
+ AS_CASE(["x$CC"],
+ [x/*],
+ [
+ AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])
+ AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])])
+ ],
+ [
+ AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])
+ AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])
+ ]
+ )
+ ])
+ ;;
+ esac
+ fi
+fi
+
+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
+
+AC_SUBST([PTHREAD_LIBS])
+AC_SUBST([PTHREAD_CFLAGS])
+AC_SUBST([PTHREAD_CC])
+AC_SUBST([PTHREAD_CXX])
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test "x$ax_pthread_ok" = "xyes"; then
+ ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
+ :
+else
+ ax_pthread_ok=no
+ $2
+fi
+AC_LANG_POP
+])dnl AX_PTHREAD
diff --git a/m4/libtool.m4 b/m4/libtool.m4
new file mode 100644
index 0000000..e7b6833
--- /dev/null
+++ b/m4/libtool.m4
@@ -0,0 +1,8427 @@
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+# Copyright (C) 1996-2001, 2003-2019, 2021-2022 Free Software
+# Foundation, Inc.
+# Written by Gordon Matzigkeit, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+m4_define([_LT_COPYING], [dnl
+# Copyright (C) 2014 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions. There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program or library that is built
+# using GNU Libtool, you may include this file under the same
+# distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+])
+
+# serial 59 LT_INIT
+
+
+# LT_PREREQ(VERSION)
+# ------------------
+# Complain and exit if this libtool version is less that VERSION.
+m4_defun([LT_PREREQ],
+[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+ [m4_default([$3],
+ [m4_fatal([Libtool version $1 or higher is required],
+ 63)])],
+ [$2])])
+
+
+# _LT_CHECK_BUILDDIR
+# ------------------
+# Complain if the absolute build directory name contains unusual characters
+m4_defun([_LT_CHECK_BUILDDIR],
+[case `pwd` in
+ *\ * | *\ *)
+ AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+esac
+])
+
+
+# LT_INIT([OPTIONS])
+# ------------------
+AC_DEFUN([LT_INIT],
+[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK
+AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+AC_BEFORE([$0], [LT_LANG])dnl
+AC_BEFORE([$0], [LT_OUTPUT])dnl
+AC_BEFORE([$0], [LTDL_INIT])dnl
+m4_require([_LT_CHECK_BUILDDIR])dnl
+
+dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+dnl unless we require an AC_DEFUNed macro:
+AC_REQUIRE([LTOPTIONS_VERSION])dnl
+AC_REQUIRE([LTSUGAR_VERSION])dnl
+AC_REQUIRE([LTVERSION_VERSION])dnl
+AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+m4_require([_LT_PROG_LTMAIN])dnl
+
+_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
+
+dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS=$ltmain
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+_LT_SETUP
+
+# Only expand once:
+m4_define([LT_INIT])
+])# LT_INIT
+
+# Old names:
+AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+
+
+# _LT_PREPARE_CC_BASENAME
+# -----------------------
+m4_defun([_LT_PREPARE_CC_BASENAME], [
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+ for cc_temp in @S|@*""; do
+ case $cc_temp in
+ compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+ distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+ done
+ func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+])# _LT_PREPARE_CC_BASENAME
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME,
+# but that macro is also expanded into generated libtool script, which
+# arranges for $SED and $ECHO to be set by different means.
+m4_defun([_LT_CC_BASENAME],
+[m4_require([_LT_PREPARE_CC_BASENAME])dnl
+AC_REQUIRE([_LT_DECL_SED])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+func_cc_basename $1
+cc_basename=$func_cc_basename_result
+])
+
+
+# _LT_FILEUTILS_DEFAULTS
+# ----------------------
+# It is okay to use these file commands and assume they have been set
+# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'.
+m4_defun([_LT_FILEUTILS_DEFAULTS],
+[: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+])# _LT_FILEUTILS_DEFAULTS
+
+
+# _LT_SETUP
+# ---------
+m4_defun([_LT_SETUP],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+
+_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
+dnl
+_LT_DECL([], [host_alias], [0], [The host system])dnl
+_LT_DECL([], [host], [0])dnl
+_LT_DECL([], [host_os], [0])dnl
+dnl
+_LT_DECL([], [build_alias], [0], [The build system])dnl
+_LT_DECL([], [build], [0])dnl
+_LT_DECL([], [build_os], [0])dnl
+dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+test -z "$LN_S" && LN_S="ln -s"
+_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+dnl
+AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
+m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_DECL_FILECMD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_WITH_SYSROOT])dnl
+m4_require([_LT_CMD_TRUNCATE])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options that allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+fi
+])
+if test -n "${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+fi
+
+_LT_CHECK_OBJDIR
+
+m4_require([_LT_TAG_COMPILER])dnl
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test set != "${COLLECT_NAMES+set}"; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a '.a' archive for static linking (except MSVC and
+# ICC, which need '.lib').
+libext=a
+
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+old_CC=$CC
+old_CFLAGS=$CFLAGS
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ _LT_PATH_MAGIC
+ fi
+ ;;
+esac
+
+# Use C for the default configuration in the libtool script
+LT_SUPPORTED_TAG([CC])
+_LT_LANG_C_CONFIG
+_LT_LANG_DEFAULT_CONFIG
+_LT_CONFIG_COMMANDS
+])# _LT_SETUP
+
+
+# _LT_PREPARE_SED_QUOTE_VARS
+# --------------------------
+# Define a few sed substitution that help us do robust quoting.
+m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
+[# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+])
+
+# _LT_PROG_LTMAIN
+# ---------------
+# Note that this code is called both from 'configure', and 'config.status'
+# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably,
+# 'config.status' has no value for ac_aux_dir unless we are using Automake,
+# so we pass a copy along to make sure it has a sensible value anyway.
+m4_defun([_LT_PROG_LTMAIN],
+[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+ltmain=$ac_aux_dir/ltmain.sh
+])# _LT_PROG_LTMAIN
+
+
+## ------------------------------------- ##
+## Accumulate code for creating libtool. ##
+## ------------------------------------- ##
+
+# So that we can recreate a full libtool script including additional
+# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+# in macros and then make a single call at the end using the 'libtool'
+# label.
+
+
+# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+# ----------------------------------------
+# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL_INIT],
+[m4_ifval([$1],
+ [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+ [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+
+
+# _LT_CONFIG_LIBTOOL([COMMANDS])
+# ------------------------------
+# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL],
+[m4_ifval([$1],
+ [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+ [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+
+
+# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+# -----------------------------------------------------
+m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+[_LT_CONFIG_LIBTOOL([$1])
+_LT_CONFIG_LIBTOOL_INIT([$2])
+])
+
+
+# _LT_FORMAT_COMMENT([COMMENT])
+# -----------------------------
+# Add leading comment marks to the start of each line, and a trailing
+# full-stop to the whole comment if one is not present already.
+m4_define([_LT_FORMAT_COMMENT],
+[m4_ifval([$1], [
+m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+ [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+)])
+
+
+
+## ------------------------ ##
+## FIXME: Eliminate VARNAME ##
+## ------------------------ ##
+
+
+# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+# -------------------------------------------------------------------
+# CONFIGNAME is the name given to the value in the libtool script.
+# VARNAME is the (base) name used in the configure script.
+# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+# VARNAME. Any other value will be used directly.
+m4_define([_LT_DECL],
+[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+ [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+ [m4_ifval([$1], [$1], [$2])])
+ lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+ m4_ifval([$4],
+ [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+ lt_dict_add_subkey([lt_decl_dict], [$2],
+ [tagged?], [m4_ifval([$5], [yes], [no])])])
+])
+
+
+# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+# --------------------------------------------------------
+m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+
+
+# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_tag_varnames],
+[_lt_decl_filter([tagged?], [yes], $@)])
+
+
+# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+# ---------------------------------------------------------
+m4_define([_lt_decl_filter],
+[m4_case([$#],
+ [0], [m4_fatal([$0: too few arguments: $#])],
+ [1], [m4_fatal([$0: too few arguments: $#: $1])],
+ [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+ [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+ [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+])
+
+
+# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+# --------------------------------------------------
+m4_define([lt_decl_quote_varnames],
+[_lt_decl_filter([value], [1], $@)])
+
+
+# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_dquote_varnames],
+[_lt_decl_filter([value], [2], $@)])
+
+
+# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_varnames_tagged],
+[m4_assert([$# <= 2])dnl
+_$0(m4_quote(m4_default([$1], [[, ]])),
+ m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
+ m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
+m4_define([_lt_decl_varnames_tagged],
+[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
+
+
+# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_all_varnames],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+ m4_if([$2], [],
+ m4_quote(lt_decl_varnames),
+ m4_quote(m4_shift($@))))[]dnl
+])
+m4_define([_lt_decl_all_varnames],
+[lt_join($@, lt_decl_varnames_tagged([$1],
+ lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+])
+
+
+# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+# ------------------------------------
+# Quote a variable value, and forward it to 'config.status' so that its
+# declaration there will have the same value as in 'configure'. VARNAME
+# must have a single quote delimited value for this to work.
+m4_define([_LT_CONFIG_STATUS_DECLARE],
+[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
+
+
+# _LT_CONFIG_STATUS_DECLARATIONS
+# ------------------------------
+# We delimit libtool config variables with single quotes, so when
+# we write them to config.status, we have to be sure to quote all
+# embedded single quotes properly. In configure, this macro expands
+# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+#
+# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`'
+m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+ [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAGS
+# ----------------
+# Output comment and list of tags supported by the script
+m4_defun([_LT_LIBTOOL_TAGS],
+[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+available_tags='_LT_TAGS'dnl
+])
+
+
+# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+# -----------------------------------
+# Extract the dictionary values for VARNAME (optionally with TAG) and
+# expand to a commented shell variable setting:
+#
+# # Some comment about what VAR is for.
+# visible_name=$lt_internal_name
+m4_define([_LT_LIBTOOL_DECLARE],
+[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+ [description])))[]dnl
+m4_pushdef([_libtool_name],
+ m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+ [0], [_libtool_name=[$]$1],
+ [1], [_libtool_name=$lt_[]$1],
+ [2], [_libtool_name=$lt_[]$1],
+ [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+])
+
+
+# _LT_LIBTOOL_CONFIG_VARS
+# -----------------------
+# Produce commented declarations of non-tagged libtool config variables
+# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool'
+# script. Tagged libtool config variables (even for the LIBTOOL CONFIG
+# section) are produced by _LT_LIBTOOL_TAG_VARS.
+m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+[m4_foreach([_lt_var],
+ m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+ [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAG_VARS(TAG)
+# -------------------------
+m4_define([_LT_LIBTOOL_TAG_VARS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+ [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+
+
+# _LT_TAGVAR(VARNAME, [TAGNAME])
+# ------------------------------
+m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+
+
+# _LT_CONFIG_COMMANDS
+# -------------------
+# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of
+# variables for single and double quote escaping we saved from calls
+# to _LT_DECL, we can put quote escaped variables declarations
+# into 'config.status', and then the shell code to quote escape them in
+# for loops in 'config.status'. Finally, any additional code accumulated
+# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+m4_defun([_LT_CONFIG_COMMANDS],
+[AC_PROVIDE_IFELSE([LT_OUTPUT],
+ dnl If the libtool generation code has been placed in $CONFIG_LT,
+ dnl instead of duplicating it all over again into config.status,
+ dnl then we will have config.status run $CONFIG_LT later, so it
+ dnl needs to know what name is stored there:
+ [AC_CONFIG_COMMANDS([libtool],
+ [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+ dnl If the libtool generation code is destined for config.status,
+ dnl expand the accumulated commands and init code now:
+ [AC_CONFIG_COMMANDS([libtool],
+ [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+])#_LT_CONFIG_COMMANDS
+
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+[
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+_LT_CONFIG_STATUS_DECLARATIONS
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+\$[]1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[[\\\\\\\`\\"\\\$]]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Double-quote double-evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_dquote_varnames); do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[[\\\\\\\`\\"\\\$]]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+_LT_OUTPUT_LIBTOOL_INIT
+])
+
+# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
+# ------------------------------------
+# Generate a child script FILE with all initialization necessary to
+# reuse the environment learned by the parent script, and make the
+# file executable. If COMMENT is supplied, it is inserted after the
+# '#!' sequence but before initialization text begins. After this
+# macro, additional text can be appended to FILE to form the body of
+# the child script. The macro ends with non-zero status if the
+# file could not be fully written (such as if the disk is full).
+m4_ifdef([AS_INIT_GENERATED],
+[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
+[m4_defun([_LT_GENERATED_FILE_INIT],
+[m4_require([AS_PREPARE])]dnl
+[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
+[lt_write_fail=0
+cat >$1 <<_ASEOF || lt_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+$2
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$1 <<\_ASEOF || lt_write_fail=1
+AS_SHELL_SANITIZE
+_AS_PREPARE
+exec AS_MESSAGE_FD>&1
+_ASEOF
+test 0 = "$lt_write_fail" && chmod +x $1[]dnl
+m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
+
+# LT_OUTPUT
+# ---------
+# This macro allows early generation of the libtool script (before
+# AC_OUTPUT is called), incase it is used in configure for compilation
+# tests.
+AC_DEFUN([LT_OUTPUT],
+[: ${CONFIG_LT=./config.lt}
+AC_MSG_NOTICE([creating $CONFIG_LT])
+_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
+[# Run this file to recreate a libtool stub with the current configuration.])
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+lt_cl_silent=false
+exec AS_MESSAGE_LOG_FD>>config.log
+{
+ echo
+ AS_BOX([Running $as_me.])
+} >&AS_MESSAGE_LOG_FD
+
+lt_cl_help="\
+'$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $[0] [[OPTIONS]]
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+
+Report bugs to ."
+
+lt_cl_version="\
+m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+configured by $[0], generated by m4_PACKAGE_STRING.
+
+Copyright (C) 2011 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test 0 != $[#]
+do
+ case $[1] in
+ --version | --v* | -V )
+ echo "$lt_cl_version"; exit 0 ;;
+ --help | --h* | -h )
+ echo "$lt_cl_help"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --quiet | --q* | --silent | --s* | -q )
+ lt_cl_silent=: ;;
+
+ -*) AC_MSG_ERROR([unrecognized option: $[1]
+Try '$[0] --help' for more information.]) ;;
+
+ *) AC_MSG_ERROR([unrecognized argument: $[1]
+Try '$[0] --help' for more information.]) ;;
+ esac
+ shift
+done
+
+if $lt_cl_silent; then
+ exec AS_MESSAGE_FD>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AC_MSG_NOTICE([creating $ofile])
+_LT_OUTPUT_LIBTOOL_COMMANDS
+AS_EXIT(0)
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure. Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+lt_cl_success=:
+test yes = "$silent" &&
+ lt_config_lt_args="$lt_config_lt_args --quiet"
+exec AS_MESSAGE_LOG_FD>/dev/null
+$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+exec AS_MESSAGE_LOG_FD>>config.log
+$lt_cl_success || AS_EXIT(1)
+])# LT_OUTPUT
+
+
+# _LT_CONFIG(TAG)
+# ---------------
+# If TAG is the built-in tag, create an initial libtool script with a
+# default configuration from the untagged config vars. Otherwise add code
+# to config.status for appending the configuration named by TAG from the
+# matching tagged config vars.
+m4_defun([_LT_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_CONFIG_SAVE_COMMANDS([
+ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+ m4_if(_LT_TAG, [C], [
+ # See if we are running on zsh, and set the options that allow our
+ # commands through without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+ fi
+
+ cfgfile=${ofile}T
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+ $RM "$cfgfile"
+
+ cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+# Generated automatically by $as_me ($PACKAGE) $VERSION
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit, 1996
+
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# Configured defaults for sys_lib_dlsearch_path munging.
+: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+ cat <<'_LT_EOF' >> "$cfgfile"
+
+# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_PREPARE_MUNGE_PATH_LIST
+_LT_PREPARE_CC_BASENAME
+
+# ### END FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_EOF
+
+ case $host_os in
+ aix3*)
+ cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test set != "${COLLECT_NAMES+set}"; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+_LT_EOF
+ ;;
+ esac
+
+ _LT_PROG_LTMAIN
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ $SED '$q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" ||
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+],
+[cat <<_LT_EOF >> "$ofile"
+
+dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+dnl in a comment (ie after a #).
+# ### BEGIN LIBTOOL TAG CONFIG: $1
+_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+# ### END LIBTOOL TAG CONFIG: $1
+_LT_EOF
+])dnl /m4_if
+],
+[m4_if([$1], [], [
+ PACKAGE='$PACKAGE'
+ VERSION='$VERSION'
+ RM='$RM'
+ ofile='$ofile'], [])
+])dnl /_LT_CONFIG_SAVE_COMMANDS
+])# _LT_CONFIG
+
+
+# LT_SUPPORTED_TAG(TAG)
+# ---------------------
+# Trace this macro to discover what tags are supported by the libtool
+# --tag option, using:
+# autoconf --trace 'LT_SUPPORTED_TAG:$1'
+AC_DEFUN([LT_SUPPORTED_TAG], [])
+
+
+# C support is built-in for now
+m4_define([_LT_LANG_C_enabled], [])
+m4_define([_LT_TAGS], [])
+
+
+# LT_LANG(LANG)
+# -------------
+# Enable libtool support for the given language if not already enabled.
+AC_DEFUN([LT_LANG],
+[AC_BEFORE([$0], [LT_OUTPUT])dnl
+m4_case([$1],
+ [C], [_LT_LANG(C)],
+ [C++], [_LT_LANG(CXX)],
+ [Go], [_LT_LANG(GO)],
+ [Java], [_LT_LANG(GCJ)],
+ [Fortran 77], [_LT_LANG(F77)],
+ [Fortran], [_LT_LANG(FC)],
+ [Windows Resource], [_LT_LANG(RC)],
+ [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+ [_LT_LANG($1)],
+ [m4_fatal([$0: unsupported language: "$1"])])])dnl
+])# LT_LANG
+
+
+# _LT_LANG(LANGNAME)
+# ------------------
+m4_defun([_LT_LANG],
+[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+ [LT_SUPPORTED_TAG([$1])dnl
+ m4_append([_LT_TAGS], [$1 ])dnl
+ m4_define([_LT_LANG_]$1[_enabled], [])dnl
+ _LT_LANG_$1_CONFIG($1)])dnl
+])# _LT_LANG
+
+
+m4_ifndef([AC_PROG_GO], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_GO. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+############################################################
+m4_defun([AC_PROG_GO],
+[AC_LANG_PUSH(Go)dnl
+AC_ARG_VAR([GOC], [Go compiler command])dnl
+AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
+_AC_ARG_VAR_LDFLAGS()dnl
+AC_CHECK_TOOL(GOC, gccgo)
+if test -z "$GOC"; then
+ if test -n "$ac_tool_prefix"; then
+ AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
+ fi
+fi
+if test -z "$GOC"; then
+ AC_CHECK_PROG(GOC, gccgo, gccgo, false)
+fi
+])#m4_defun
+])#m4_ifndef
+
+
+# _LT_LANG_DEFAULT_CONFIG
+# -----------------------
+m4_defun([_LT_LANG_DEFAULT_CONFIG],
+[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [LT_LANG(CXX)],
+ [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_F77],
+ [LT_LANG(F77)],
+ [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_FC],
+ [LT_LANG(FC)],
+ [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+
+dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+dnl pulling things in needlessly.
+AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [m4_ifdef([AC_PROG_GCJ],
+ [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+ m4_ifdef([A][M_PROG_GCJ],
+ [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+ m4_ifdef([LT_PROG_GCJ],
+ [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+
+AC_PROVIDE_IFELSE([AC_PROG_GO],
+ [LT_LANG(GO)],
+ [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
+
+AC_PROVIDE_IFELSE([LT_PROG_RC],
+ [LT_LANG(RC)],
+ [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+])# _LT_LANG_DEFAULT_CONFIG
+
+# Obsolete macros:
+AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+dnl AC_DEFUN([AC_LIBTOOL_RC], [])
+
+
+# _LT_TAG_COMPILER
+# ----------------
+m4_defun([_LT_TAG_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_TAG_COMPILER
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+m4_defun([_LT_COMPILER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+m4_defun([_LT_LINKER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# -------------------------
+m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+ case $host_os in
+ rhapsody* | darwin*)
+ AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+ AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+ AC_CHECK_TOOL([LIPO], [lipo], [:])
+ AC_CHECK_TOOL([OTOOL], [otool], [:])
+ AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+ _LT_DECL([], [DSYMUTIL], [1],
+ [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+ _LT_DECL([], [NMEDIT], [1],
+ [Tool to change global to local symbols on Mac OS X])
+ _LT_DECL([], [LIPO], [1],
+ [Tool to manipulate fat objects and archives on Mac OS X])
+ _LT_DECL([], [OTOOL], [1],
+ [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+ _LT_DECL([], [OTOOL64], [1],
+ [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+
+ AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+ [lt_cv_apple_cc_single_mod=no
+ if test -z "$LT_MULTI_MODULE"; then
+ # By default we will add the -single_module flag. You can override
+ # by either setting the environment variable LT_MULTI_MODULE
+ # non-empty at configure time, or by adding -multi_module to the
+ # link flags.
+ rm -rf libconftest.dylib*
+ echo "int foo(void){return 1;}" > conftest.c
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+ _lt_result=$?
+ # If there is a non-empty error log, and "single_module"
+ # appears in it, assume the flag caused a linker warning
+ if test -s conftest.err && $GREP single_module conftest.err; then
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ # Otherwise, if the output was created with a 0 exit code from
+ # the compiler, it worked.
+ elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
+ lt_cv_apple_cc_single_mod=yes
+ else
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ fi
+ rm -rf libconftest.dylib*
+ rm -f conftest.*
+ fi])
+
+ AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+ [lt_cv_ld_exported_symbols_list],
+ [lt_cv_ld_exported_symbols_list=no
+ save_LDFLAGS=$LDFLAGS
+ echo "_main" > conftest.sym
+ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [lt_cv_ld_exported_symbols_list=yes],
+ [lt_cv_ld_exported_symbols_list=no])
+ LDFLAGS=$save_LDFLAGS
+ ])
+
+ AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
+ [lt_cv_ld_force_load=no
+ cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
+ $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
+ echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
+ $AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
+ echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
+ $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
+ cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
+ $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+ _lt_result=$?
+ if test -s conftest.err && $GREP force_load conftest.err; then
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
+ lt_cv_ld_force_load=yes
+ else
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ fi
+ rm -f conftest.err libconftest.a conftest conftest.c
+ rm -rf conftest.dSYM
+ ])
+ case $host_os in
+ rhapsody* | darwin1.[[012]])
+ _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
+ darwin1.*)
+ _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+ darwin*)
+ case $MACOSX_DEPLOYMENT_TARGET,$host in
+ 10.[[012]],*|,*powerpc*-darwin[[5-8]]*)
+ _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+ *)
+ _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+ esac
+ ;;
+ esac
+ if test yes = "$lt_cv_apple_cc_single_mod"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test yes = "$lt_cv_ld_exported_symbols_list"; then
+ _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
+ else
+ _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
+ fi
+ if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
+ _lt_dsymutil='~$DSYMUTIL $lib || :'
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES([TAG])
+# ---------------------------------
+# Checks for linker and compiler features on darwin
+m4_defun([_LT_DARWIN_LINKER_FEATURES],
+[
+ m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ if test yes = "$lt_cv_ld_force_load"; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+ m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
+ [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes])
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+ fi
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined
+ case $cc_basename in
+ ifort*|nagfor*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test yes = "$_lt_dar_can_shared"; then
+ output_verbose_link_cmd=func_echo_all
+ _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
+ _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+ _LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+ m4_if([$1], [CXX],
+[ if test yes != "$lt_cv_apple_cc_single_mod"; then
+ _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
+ fi
+],[])
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+])
+
+# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
+# ----------------------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+# Store the results from the different compilers for each TAGNAME.
+# Allow to override them for all tags through lt_cv_aix_libpath.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+if test set = "${lt_cv_aix_libpath+set}"; then
+ aix_libpath=$lt_cv_aix_libpath
+else
+ AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM],[
+ lt_aix_libpath_sed='[
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\([^ ]*\) *$/\1/
+ p
+ }
+ }]'
+ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ # Check for a 64-bit object if we didn't find anything.
+ if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ fi],[])
+ if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib
+ fi
+ ])
+ aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
+fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[m4_divert_text([M4SH-INIT], [$1
+])])# _LT_SHELL_INIT
+
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Find how we can fake an echo command that does not interpret backslash.
+# In particular, with Autoconf 2.60 or later we add some code to the start
+# of the generated configure script that will find a shell with a builtin
+# printf (that we can use as an echo command).
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+AC_MSG_CHECKING([how to print strings])
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='printf %s\n'
+else
+ # Use this function as a fallback that always works.
+ func_fallback_echo ()
+ {
+ eval 'cat <<_LTECHO_EOF
+$[]1
+_LTECHO_EOF'
+ }
+ ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+ $ECHO "$*"
+}
+
+case $ECHO in
+ printf*) AC_MSG_RESULT([printf]) ;;
+ print*) AC_MSG_RESULT([print -r]) ;;
+ *) AC_MSG_RESULT([cat]) ;;
+esac
+
+m4_ifdef([_AS_DETECT_SUGGESTED],
+[_AS_DETECT_SUGGESTED([
+ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
+ ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+ PATH=/empty FPATH=/empty; export PATH FPATH
+ test "X`printf %s $ECHO`" = "X$ECHO" \
+ || test "X`print -r -- $ECHO`" = "X$ECHO" )])])
+
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _LT_WITH_SYSROOT
+# ----------------
+AC_DEFUN([_LT_WITH_SYSROOT],
+[m4_require([_LT_DECL_SED])dnl
+AC_MSG_CHECKING([for sysroot])
+AC_ARG_WITH([sysroot],
+[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
+ [Search for dependent libraries within DIR (or the compiler's sysroot
+ if not specified).])],
+[], [with_sysroot=no])
+
+dnl lt_sysroot will always be passed unquoted. We quote it here
+dnl in case the user passed a directory name.
+lt_sysroot=
+case $with_sysroot in #(
+ yes)
+ if test yes = "$GCC"; then
+ lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+ fi
+ ;; #(
+ /*)
+ lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
+ ;; #(
+ no|'')
+ ;; #(
+ *)
+ AC_MSG_RESULT([$with_sysroot])
+ AC_MSG_ERROR([The sysroot must be an absolute path.])
+ ;;
+esac
+
+ AC_MSG_RESULT([${lt_sysroot:-no}])
+_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
+[dependent libraries, and where our libraries should be installed.])])
+
+# _LT_ENABLE_LOCK
+# ---------------
+m4_defun([_LT_ENABLE_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+ [AS_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test no = "$enable_libtool_lock" || enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out what ABI is being produced by ac_compile, and set mode
+ # options accordingly.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `$FILECMD conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE=32
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE=64
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ if test yes = "$lt_cv_prog_gnu_ld"; then
+ case `$FILECMD conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `$FILECMD conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+mips64*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ emul=elf
+ case `$FILECMD conftest.$ac_objext` in
+ *32-bit*)
+ emul="${emul}32"
+ ;;
+ *64-bit*)
+ emul="${emul}64"
+ ;;
+ esac
+ case `$FILECMD conftest.$ac_objext` in
+ *MSB*)
+ emul="${emul}btsmip"
+ ;;
+ *LSB*)
+ emul="${emul}ltsmip"
+ ;;
+ esac
+ case `$FILECMD conftest.$ac_objext` in
+ *N32*)
+ emul="${emul}n32"
+ ;;
+ esac
+ LD="${LD-ld} -m $emul"
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly. Note that the listed cases only cover the
+ # situations where additional linker options are needed (such as when
+ # doing 32-bit compilation for a host where ld defaults to 64-bit, or
+ # vice versa); the common cases where no linker options are needed do
+ # not appear in the list.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `$FILECMD conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_i386_fbsd"
+ ;;
+ x86_64-*linux*)
+ case `$FILECMD conftest.o` in
+ *x86-64*)
+ LD="${LD-ld} -m elf32_x86_64"
+ ;;
+ *)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ esac
+ ;;
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_x86_64_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*|s390*-*tpf*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS -belf"
+ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+ [AC_LANG_PUSH(C)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+ AC_LANG_POP])
+ if test yes != "$lt_cv_cc_needs_belf"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS=$SAVE_CFLAGS
+ fi
+ ;;
+*-*solaris*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `$FILECMD conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*)
+ case $host in
+ i?86-*-solaris*|x86_64-*-solaris*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ sparc*-*-solaris*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ # GNU ld 2.21 introduced _sol2 emulations. Use them if available.
+ if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+ LD=${LD-ld}_sol2
+ fi
+ ;;
+ *)
+ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+ LD="${LD-ld} -64"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+esac
+
+need_locks=$enable_libtool_lock
+])# _LT_ENABLE_LOCK
+
+
+# _LT_PROG_AR
+# -----------
+m4_defun([_LT_PROG_AR],
+[AC_CHECK_TOOLS(AR, [ar], false)
+: ${AR=ar}
+_LT_DECL([], [AR], [1], [The archiver])
+
+# Use ARFLAGS variable as AR's operation code to sync the variable naming with
+# Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
+# higher priority because thats what people were doing historically (setting
+# ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS
+# variable obsoleted/removed.
+
+test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
+lt_ar_flags=$AR_FLAGS
+_LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)])
+
+# Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override
+# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
+_LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}],
+ [Flags to create an archive])
+
+AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
+ [lt_cv_ar_at_file=no
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
+ [echo conftest.$ac_objext > conftest.lst
+ lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
+ AC_TRY_EVAL([lt_ar_try])
+ if test 0 -eq "$ac_status"; then
+ # Ensure the archiver fails upon bogus file names.
+ rm -f conftest.$ac_objext libconftest.a
+ AC_TRY_EVAL([lt_ar_try])
+ if test 0 -ne "$ac_status"; then
+ lt_cv_ar_at_file=@
+ fi
+ fi
+ rm -f conftest.* libconftest.a
+ ])
+ ])
+
+if test no = "$lt_cv_ar_at_file"; then
+ archiver_list_spec=
+else
+ archiver_list_spec=$lt_cv_ar_at_file
+fi
+_LT_DECL([], [archiver_list_spec], [1],
+ [How to feed a file listing to the archiver])
+])# _LT_PROG_AR
+
+
+# _LT_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[_LT_PROG_AR
+
+AC_CHECK_TOOL(STRIP, strip, :)
+test -z "$STRIP" && STRIP=:
+_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+test -z "$RANLIB" && RANLIB=:
+_LT_DECL([], [RANLIB], [1],
+ [Commands used to install an old-style archive])
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ bitrig* | openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+ darwin*)
+ lock_old_archive_extraction=yes ;;
+ *)
+ lock_old_archive_extraction=no ;;
+esac
+_LT_DECL([], [old_postinstall_cmds], [2])
+_LT_DECL([], [old_postuninstall_cmds], [2])
+_LT_TAGDECL([], [old_archive_cmds], [2],
+ [Commands used to build an old-style archive])
+_LT_DECL([], [lock_old_archive_extraction], [0],
+ [Whether to use a lock for old archive extraction])
+])# _LT_CMD_OLD_ARCHIVE
+
+
+# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([_LT_COMPILER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ fi
+ $RM conftest*
+])
+
+if test yes = "[$]$2"; then
+ m4_if([$5], , :, [$5])
+else
+ m4_if([$6], , :, [$6])
+fi
+])# _LT_COMPILER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+
+
+# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------
+# Check whether the given linker option works
+AC_DEFUN([_LT_LINKER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS $3"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&AS_MESSAGE_LOG_FD
+ $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ else
+ $2=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS=$save_LDFLAGS
+])
+
+if test yes = "[$]$2"; then
+ m4_if([$4], , :, [$4])
+else
+ m4_if([$5], , :, [$5])
+fi
+])# _LT_LINKER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+
+
+# LT_CMD_MAX_LEN
+#---------------
+AC_DEFUN([LT_CMD_MAX_LEN],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+ i=0
+ teststring=ABCD
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw* | cegcc*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ mint*)
+ # On MiNT this can take a long time and run out of memory.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ os2*)
+ # The test takes a long time on OS/2.
+ lt_cv_sys_max_cmd_len=8192
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[[ ]]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+ if test -n "$lt_cv_sys_max_cmd_len" && \
+ test undefined != "$lt_cv_sys_max_cmd_len"; then
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ else
+ # Make teststring a little bigger before we do anything with it.
+ # a 1K string should be a reasonable start.
+ for i in 1 2 3 4 5 6 7 8; do
+ teststring=$teststring$teststring
+ done
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ while { test X`env echo "$teststring$teststring" 2>/dev/null` \
+ = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+ test 17 != "$i" # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ # Only check the string length outside the loop.
+ lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on
+ # massive amounts of additional arguments before passing them to the
+ # linker. It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ fi
+ ;;
+ esac
+])
+if test -n "$lt_cv_sys_max_cmd_len"; then
+ AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+ AC_MSG_RESULT(none)
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+_LT_DECL([], [max_cmd_len], [0],
+ [What is the maximum length of a command?])
+])# LT_CMD_MAX_LEN
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+
+
+# _LT_HEADER_DLFCN
+# ----------------
+m4_defun([_LT_HEADER_DLFCN],
+[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+])# _LT_HEADER_DLFCN
+
+
+# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ----------------------------------------------------------------
+m4_defun([_LT_TRY_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test yes = "$cross_compiling"; then :
+ [$4]
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+[#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include
+#endif
+
+#include
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+ correspondingly for the symbols needed. */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else
+ {
+ if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ else puts (dlerror ());
+ }
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}]
+_LT_EOF
+ if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then
+ (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) $1 ;;
+ x$lt_dlneed_uscore) $2 ;;
+ x$lt_dlunknown|x*) $3 ;;
+ esac
+ else :
+ # compilation failed
+ $3
+ fi
+fi
+rm -fr conftest*
+])# _LT_TRY_DLOPEN_SELF
+
+
+# LT_SYS_DLOPEN_SELF
+# ------------------
+AC_DEFUN([LT_SYS_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test yes != "$enable_dlopen"; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen=load_add_on
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32* | cegcc*)
+ lt_cv_dlopen=LoadLibrary
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen=dlopen
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[
+ lt_cv_dlopen=dyld
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ])
+ ;;
+
+ tpf*)
+ # Don't try to run any link tests for TPF. We know it's impossible
+ # because TPF is a cross-compiler, and we know how we open DSOs.
+ lt_cv_dlopen=dlopen
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=no
+ ;;
+
+ *)
+ AC_CHECK_FUNC([shl_load],
+ [lt_cv_dlopen=shl_load],
+ [AC_CHECK_LIB([dld], [shl_load],
+ [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld],
+ [AC_CHECK_FUNC([dlopen],
+ [lt_cv_dlopen=dlopen],
+ [AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],
+ [AC_CHECK_LIB([svld], [dlopen],
+ [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld],
+ [AC_CHECK_LIB([dld], [dld_link],
+ [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld])
+ ])
+ ])
+ ])
+ ])
+ ])
+ ;;
+ esac
+
+ if test no = "$lt_cv_dlopen"; then
+ enable_dlopen=no
+ else
+ enable_dlopen=yes
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS=$CPPFLAGS
+ test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS=$LDFLAGS
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS=$LIBS
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ AC_CACHE_CHECK([whether a program can dlopen itself],
+ lt_cv_dlopen_self, [dnl
+ _LT_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+ lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+ ])
+
+ if test yes = "$lt_cv_dlopen_self"; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+ lt_cv_dlopen_self_static, [dnl
+ _LT_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+ lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
+ ])
+ fi
+
+ CPPFLAGS=$save_CPPFLAGS
+ LDFLAGS=$save_LDFLAGS
+ LIBS=$save_LIBS
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+_LT_DECL([dlopen_support], [enable_dlopen], [0],
+ [Whether dlopen is supported])
+_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+ [Whether dlopen of programs is supported])
+_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+ [Whether dlopen of statically linked programs is supported])
+])# LT_SYS_DLOPEN_SELF
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+
+
+# _LT_COMPILER_C_O([TAGNAME])
+# ---------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler.
+# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+m4_defun([_LT_COMPILER_C_O],
+[m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+ [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+ [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+ fi
+ fi
+ chmod u+w . 2>&AS_MESSAGE_LOG_FD
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+])
+_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+ [Does compiler simultaneously support -c and -o options?])
+])# _LT_COMPILER_C_O
+
+
+# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+# ----------------------------------
+# Check to see if we can do hard links to lock some files if needed
+m4_defun([_LT_COMPILER_FILE_LOCKS],
+[m4_require([_LT_ENABLE_LOCK])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_COMPILER_C_O([$1])
+
+hard_links=nottested
+if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then
+ # do not overwrite the value of need_locks provided by the user
+ AC_MSG_CHECKING([if we can lock with hard links])
+ hard_links=yes
+ $RM conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ AC_MSG_RESULT([$hard_links])
+ if test no = "$hard_links"; then
+ AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe])
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+])# _LT_COMPILER_FILE_LOCKS
+
+
+# _LT_CHECK_OBJDIR
+# ----------------
+m4_defun([_LT_CHECK_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+_LT_DECL([], [objdir], [0],
+ [The name of the directory that contains temporary libtool files])dnl
+m4_pattern_allow([LT_OBJDIR])dnl
+AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/",
+ [Define to the sub-directory where libtool stores uninstalled libraries.])
+])# _LT_CHECK_OBJDIR
+
+
+# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+# --------------------------------------
+# Check hardcoding attributes.
+m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+ test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+ test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then
+
+ # We can hardcode non-existent directories.
+ if test no != "$_LT_TAGVAR(hardcode_direct, $1)" &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" &&
+ test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then
+ # Linking always hardcodes the temporary library directory.
+ _LT_TAGVAR(hardcode_action, $1)=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ _LT_TAGVAR(hardcode_action, $1)=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ _LT_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+
+if test relink = "$_LT_TAGVAR(hardcode_action, $1)" ||
+ test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test yes = "$shlibpath_overrides_runpath" ||
+ test no = "$enable_shared"; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+_LT_TAGDECL([], [hardcode_action], [0],
+ [How to hardcode a shared library path into an executable])
+])# _LT_LINKER_HARDCODE_LIBPATH
+
+
+# _LT_CMD_STRIPLIB
+# ----------------
+m4_defun([_LT_CMD_STRIPLIB],
+[m4_require([_LT_DECL_EGREP])
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -z "$STRIP"; then
+ AC_MSG_RESULT([no])
+else
+ if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+ old_striplib="$STRIP --strip-debug"
+ striplib="$STRIP --strip-unneeded"
+ AC_MSG_RESULT([yes])
+ else
+ case $host_os in
+ darwin*)
+ # FIXME - insert some real tests, host_os isn't really good enough
+ striplib="$STRIP -x"
+ old_striplib="$STRIP -S"
+ AC_MSG_RESULT([yes])
+ ;;
+ freebsd*)
+ if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
+ old_striplib="$STRIP --strip-debug"
+ striplib="$STRIP --strip-unneeded"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ ;;
+ *)
+ AC_MSG_RESULT([no])
+ ;;
+ esac
+ fi
+fi
+_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+_LT_DECL([], [striplib], [1])
+])# _LT_CMD_STRIPLIB
+
+
+# _LT_PREPARE_MUNGE_PATH_LIST
+# ---------------------------
+# Make sure func_munge_path_list() is defined correctly.
+m4_defun([_LT_PREPARE_MUNGE_PATH_LIST],
+[[# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+# string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+# string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+# "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+# VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+ case x@S|@2 in
+ x)
+ ;;
+ *:)
+ eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\"
+ ;;
+ x:*)
+ eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\"
+ ;;
+ *::*)
+ eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+ eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\"
+ ;;
+ *)
+ eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\"
+ ;;
+ esac
+}
+]])# _LT_PREPARE_PATH_LIST
+
+
+# _LT_SYS_DYNAMIC_LINKER([TAG])
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+m4_defun([_LT_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_OBJDUMP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+ [], [
+if test yes = "$GCC"; then
+ case $host_os in
+ darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
+ *) lt_awk_arg='/^libraries:/' ;;
+ esac
+ case $host_os in
+ mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;;
+ *) lt_sed_strip_eq='s|=/|/|g' ;;
+ esac
+ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+ case $lt_search_path_spec in
+ *\;*)
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+ ;;
+ *)
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ esac
+ # Ok, now we have the path, separated by spaces, we can step through it
+ # and add multilib dir if necessary...
+ lt_tmp_lt_search_path_spec=
+ lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+ # ...but if some path component already ends with the multilib dir we assume
+ # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
+ case "$lt_multi_os_dir; $lt_search_path_spec " in
+ "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
+ lt_multi_os_dir=
+ ;;
+ esac
+ for lt_sys_path in $lt_search_path_spec; do
+ if test -d "$lt_sys_path$lt_multi_os_dir"; then
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
+ elif test -n "$lt_multi_os_dir"; then
+ test -d "$lt_sys_path" && \
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+ fi
+ done
+ lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS = " "; FS = "/|\n";} {
+ lt_foo = "";
+ lt_count = 0;
+ for (lt_i = NF; lt_i > 0; lt_i--) {
+ if ($lt_i != "" && $lt_i != ".") {
+ if ($lt_i == "..") {
+ lt_count++;
+ } else {
+ if (lt_count == 0) {
+ lt_foo = "/" $lt_i lt_foo;
+ } else {
+ lt_count--;
+ }
+ }
+ }
+ }
+ if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+ if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+ # AWK program above erroneously prepends '/' to C:/dos/paths
+ # for these hosts.
+ case $host_os in
+ mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;;
+ esac
+ sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=.so
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+AC_ARG_VAR([LT_SYS_LIBRARY_PATH],
+[User-defined run-time library search path.])
+
+case $host_os in
+aix3*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+
+aix[[4-9]]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 supports IA64
+ library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line '#! .'. This would cause the generated library to
+ # depend on '.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[[01]] | aix4.[[01]].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # Using Import Files as archive members, it is possible to support
+ # filename-based versioning of shared library archives on AIX. While
+ # this would work for both with and without runtime linking, it will
+ # prevent static linking of such archives. So we do filename-based
+ # shared library versioning with .so extension only, which is used
+ # when both runtime linking and shared linking is enabled.
+ # Unfortunately, runtime linking may impact performance, so we do
+ # not want this to be the default eventually. Also, we use the
+ # versioned .so libs for executables only if there is the -brtl
+ # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+ # To allow for filename-based versioning support, we need to create
+ # libNAME.so.V as an archive file, containing:
+ # *) an Import File, referring to the versioned filename of the
+ # archive as well as the shared archive member, telling the
+ # bitwidth (32 or 64) of that shared object, and providing the
+ # list of exported symbols of that shared object, eventually
+ # decorated with the 'weak' keyword
+ # *) the shared object with the F_LOADONLY flag set, to really avoid
+ # it being seen by the linker.
+ # At run time we better use the real file rather than another symlink,
+ # but for link time we create the symlink libNAME.so -> libNAME.so.V
+
+ case $with_aix_soname,$aix_use_runtimelinking in
+ # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ aix,yes) # traditional libtool
+ dynamic_linker='AIX unversionable lib.so'
+ # If using run time linking (on AIX 4.2 or later) use lib.so
+ # instead of lib.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ ;;
+ aix,no) # traditional AIX only
+ dynamic_linker='AIX lib.a[(]lib.so.V[)]'
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='$libname$release.a $libname.a'
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+ svr4,*) # full svr4 only
+ dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,yes) # both, prefer svr4
+ dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # unpreferred sharedlib libNAME.a needs extra handling
+ postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+ postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,no) # both, prefer aix
+ dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]"
+ library_names_spec='$libname$release.a $libname.a'
+ soname_spec='$libname$release$shared_ext$major'
+ # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+ postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+ postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+ ;;
+ esac
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ case $host_cpu in
+ powerpc)
+ # Since July 2007 AmigaOS4 officially supports .so libraries.
+ # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ ;;
+ m68k)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+ esac
+ ;;
+
+beos*)
+ library_names_spec='$libname$shared_ext'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[[45]]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+ version_type=windows
+ shrext_cmds=.dll
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$cc_basename in
+ yes,*)
+ # gcc
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+m4_if([$1], [],[
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ ;;
+
+ *,cl* | *,icl*)
+ # Native MSVC or ICC
+ libname_spec='$name'
+ soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+ library_names_spec='$libname.dll.lib'
+
+ case $build_os in
+ mingw*)
+ sys_lib_search_path_spec=
+ lt_save_ifs=$IFS
+ IFS=';'
+ for lt_path in $LIB
+ do
+ IFS=$lt_save_ifs
+ # Let DOS variable expansion print the short 8.3 style file name.
+ lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+ sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+ done
+ IFS=$lt_save_ifs
+ # Convert to MSYS style.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
+ ;;
+ cygwin*)
+ # Convert to unix form, then to dos form, then back to unix form
+ # but this time dos style (no spaces!) so that the unix form looks
+ # like /cygdrive/c/PROGRA~1:/cygdr...
+ sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+ sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+ sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ *)
+ sys_lib_search_path_spec=$LIB
+ if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+ # It is most probably a Windows format PATH.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ # FIXME: find the short name or the path components, as spaces are
+ # common. (e.g. "Program Files" -> "PROGRA~1")
+ ;;
+ esac
+
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+ dynamic_linker='Win32 link.exe'
+ ;;
+
+ *)
+ # Assume MSVC and ICC wrapper
+ library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
+ dynamic_linker='Win32 ld.exe'
+ ;;
+ esac
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
+ soname_spec='$libname$release$major$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+m4_if([$1], [],[
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd* | dragonfly* | midnightbsd*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[[23]].*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2.*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ *) # from 4.6 on, and DragonFly
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+haiku*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ dynamic_linker="$host_os runtime_loader"
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ if test 32 = "$HPUX_IA64_MODE"; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+ fi
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+ postinstall_cmds='chmod 555 $lib'
+ # or fails outright, so override atomically:
+ install_override_mode=555
+ ;;
+
+interix[[3-9]]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test yes = "$lt_cv_prog_gnu_ld"; then
+ version_type=linux # correct to gnu/linux during the next big refactor
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='$libname$release$shared_ext$major'
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
+ sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+linux*android*)
+ version_type=none # Android doesn't support versioned libraries.
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext'
+ soname_spec='$libname$release$shared_ext'
+ finish_cmds=
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ dynamic_linker='Android linker'
+ # Don't embed -rpath directories since the linker doesn't support them.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+
+ # Some binutils ld are patched to set DT_RUNPATH
+ AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
+ [lt_cv_shlibpath_overrides_runpath=no
+ save_LDFLAGS=$LDFLAGS
+ save_libdir=$libdir
+ eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+ [lt_cv_shlibpath_overrides_runpath=yes])])
+ LDFLAGS=$save_LDFLAGS
+ libdir=$save_libdir
+ ])
+ shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Ideally, we could use ldconfig to report *all* directores which are
+ # searched for libraries, however this is still not possible. Aside from not
+ # being certain /sbin/ldconfig is available, command
+ # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+ # even though it is searched at run-time. Try to do the best guess by
+ # appending ld.so.conf contents (and includes) to the search path.
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsdelf*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='NetBSD ld.elf_so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+*nto* | *qnx*)
+ version_type=qnx
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='ldqnx.so'
+ ;;
+
+openbsd* | bitrig*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec=/usr/lib
+ need_lib_prefix=no
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ need_version=no
+ else
+ need_version=yes
+ fi
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+os2*)
+ libname_spec='$name'
+ version_type=windows
+ shrext_cmds=.dll
+ need_version=no
+ need_lib_prefix=no
+ # OS/2 can only load a DLL with a base name of 8 characters or less.
+ soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+ v=$($ECHO $release$versuffix | tr -d .-);
+ n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+ $ECHO $n$v`$shared_ext'
+ library_names_spec='${libname}_dll.$libext'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=BEGINLIBPATH
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='$libname$release$shared_ext$major'
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+
+rdos*)
+ dynamic_linker=no
+ ;;
+
+solaris*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test yes = "$with_gnu_ld"; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec; then
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
+ soname_spec='$libname$shared_ext.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=sco
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ if test yes = "$with_gnu_ld"; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+tpf*)
+ # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+uts4*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test no = "$dynamic_linker" && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test yes = "$GCC"; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+ sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
+fi
+
+if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+ sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
+fi
+
+# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+
+# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+
+# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+
+_LT_DECL([], [variables_saved_for_relink], [1],
+ [Variables whose values should be saved in libtool wrapper scripts and
+ restored at link time])
+_LT_DECL([], [need_lib_prefix], [0],
+ [Do we need the "lib" prefix for modules?])
+_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+_LT_DECL([], [version_type], [0], [Library versioning type])
+_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable])
+_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+_LT_DECL([], [shlibpath_overrides_runpath], [0],
+ [Is shlibpath searched before the hard-coded library search path?])
+_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+_LT_DECL([], [library_names_spec], [1],
+ [[List of archive names. First name is the real one, the rest are links.
+ The last name is the one that the linker finds with -lNAME]])
+_LT_DECL([], [soname_spec], [1],
+ [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [install_override_mode], [1],
+ [Permission mode override for installation of shared libraries])
+_LT_DECL([], [postinstall_cmds], [2],
+ [Command to use after installation of a shared archive])
+_LT_DECL([], [postuninstall_cmds], [2],
+ [Command to use after uninstallation of a shared archive])
+_LT_DECL([], [finish_cmds], [2],
+ [Commands used to finish a libtool library installation in a directory])
+_LT_DECL([], [finish_eval], [1],
+ [[As "finish_cmds", except a single script fragment to be evaled but
+ not shown]])
+_LT_DECL([], [hardcode_into_libs], [0],
+ [Whether we should hardcode library paths into libraries])
+_LT_DECL([], [sys_lib_search_path_spec], [2],
+ [Compile-time system search path for libraries])
+_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2],
+ [Detected run-time system search path for libraries])
+_LT_DECL([], [configure_time_lt_sys_library_path], [2],
+ [Explicit LT_SYS_LIBRARY_PATH set during ./configure time])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program that can recognize shared library
+AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+[m4_require([_LT_DECL_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] | ?:[\\/]*])
+ lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD=$MAGIC_CMD
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word. This closes a longstanding sh security hole.
+ ac_dummy="m4_if([$2], , $PATH, [$2])"
+ for ac_dir in $ac_dummy; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$1"; then
+ lt_cv_path_MAGIC_CMD=$ac_dir/"$1"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS=$lt_save_ifs
+ MAGIC_CMD=$lt_save_MAGIC_CMD
+ ;;
+esac])
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+ AC_MSG_RESULT($MAGIC_CMD)
+else
+ AC_MSG_RESULT(no)
+fi
+_LT_DECL([], [MAGIC_CMD], [0],
+ [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+])# _LT_PATH_TOOL_PREFIX
+
+# Old name:
+AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+
+
+# _LT_PATH_MAGIC
+# --------------
+# find a file program that can recognize a shared library
+m4_defun([_LT_PATH_MAGIC],
+[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+ else
+ MAGIC_CMD=:
+ fi
+fi
+])# _LT_PATH_MAGIC
+
+
+# LT_PATH_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([LT_PATH_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
+
+AC_ARG_WITH([gnu-ld],
+ [AS_HELP_STRING([--with-gnu-ld],
+ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+ [test no = "$withval" || with_gnu_ld=yes],
+ [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test yes = "$GCC"; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by $CC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return, which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]]* | ?:[[\\/]]*)
+ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD=$ac_prog
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test yes = "$with_gnu_ld"; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD=$ac_dir/$ac_prog
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i
+cat conftest.i conftest.i >conftest2.i
+: ${lt_DD:=$DD}
+AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd],
+[if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
+fi])
+rm -f conftest.i conftest2.i conftest.out])
+])# _LT_PATH_DD
+
+
+# _LT_CMD_TRUNCATE
+# ----------------
+# find command to truncate a binary pipe
+m4_defun([_LT_CMD_TRUNCATE],
+[m4_require([_LT_PATH_DD])
+AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin],
+[printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+lt_cv_truncate_bin=
+if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
+fi
+rm -f conftest.i conftest2.i conftest.out
+test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"])
+_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1],
+ [Command to truncate a binary pipe])
+])# _LT_CMD_TRUNCATE
+
+
+# _LT_CHECK_MAGIC_METHOD
+# ----------------------
+# how to check for library dependencies
+# -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_MAGIC_METHOD],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# 'unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# that responds to the $file_magic_cmd with a given extended regex.
+# If you have 'file' or equivalent on your system and you're not sure
+# whether 'pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[[45]]*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='$FILECMD -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump',
+ # unless we find 'file', for example because we are cross-compiling.
+ if ( file / ) >/dev/null 2>&1; then
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ else
+ # Keep this pattern in sync with the one in func_win32_libid.
+ lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ fi
+ ;;
+
+cegcc*)
+ # use the weaker test based on 'objdump'. See mingw*.
+ lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | dragonfly* | midnightbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=$FILECMD
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+haiku*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=$FILECMD
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix[[3-9]]*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=$FILECMD
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+*nto* | *qnx*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+openbsd* | bitrig*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+rdos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+tpf*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+os2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+])
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+ case $host_os in
+ mingw* | pw32*)
+ if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+ want_nocaseglob=yes
+ else
+ file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
+ fi
+ ;;
+ esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+_LT_DECL([], [deplibs_check_method], [1],
+ [Method to check whether dependent libraries are shared objects])
+_LT_DECL([], [file_magic_cmd], [1],
+ [Command to use when deplibs_check_method = "file_magic"])
+_LT_DECL([], [file_magic_glob], [1],
+ [How to find potential files when deplibs_check_method = "file_magic"])
+_LT_DECL([], [want_nocaseglob], [1],
+ [Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
+])# _LT_CHECK_MAGIC_METHOD
+
+
+# LT_PATH_NM
+# ----------
+# find the pathname to a BSD- or MS-compatible name lister
+AC_DEFUN([LT_PATH_NM],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+[if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM=$NM
+else
+ lt_nm_to_check=${ac_tool_prefix}nm
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm=$ac_dir/$lt_tmp_nm
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the 'sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
+ case $build_os in
+ mingw*) lt_bad_file=conftest.nm/nofile ;;
+ *) lt_bad_file=/dev/null ;;
+ esac
+ case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
+ *$lt_bad_file* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break 2
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break 2
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS=$lt_save_ifs
+ done
+ : ${lt_cv_path_NM=no}
+fi])
+if test no != "$lt_cv_path_NM"; then
+ NM=$lt_cv_path_NM
+else
+ # Didn't find any BSD compatible name lister, look for dumpbin.
+ if test -n "$DUMPBIN"; then :
+ # Let the user override the test.
+ else
+ AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
+ case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
+ *COFF*)
+ DUMPBIN="$DUMPBIN -symbols -headers"
+ ;;
+ *)
+ DUMPBIN=:
+ ;;
+ esac
+ fi
+ AC_SUBST([DUMPBIN])
+ if test : != "$DUMPBIN"; then
+ NM=$DUMPBIN
+ fi
+fi
+test -z "$NM" && NM=nm
+AC_SUBST([NM])
+_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+
+AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+ [lt_cv_nm_interface="BSD nm"
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$ac_compile" 2>conftest.err)
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
+ cat conftest.out >&AS_MESSAGE_LOG_FD
+ if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+ lt_cv_nm_interface="MS dumpbin"
+ fi
+ rm -f conftest*])
+])# LT_PATH_NM
+
+# Old names:
+AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_NM], [])
+dnl AC_DEFUN([AC_PROG_NM], [])
+
+# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+# --------------------------------
+# how to determine the name of the shared library
+# associated with a specific link library.
+# -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+m4_require([_LT_DECL_DLLTOOL])
+AC_CACHE_CHECK([how to associate runtime and link libraries],
+lt_cv_sharedlib_from_linklib_cmd,
+[lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+ # two different shell functions defined in ltmain.sh;
+ # decide which one to use based on capabilities of $DLLTOOL
+ case `$DLLTOOL --help 2>&1` in
+ *--identify-strict*)
+ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+ ;;
+ *)
+ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+ ;;
+ esac
+ ;;
+*)
+ # fallback: assume linklib IS sharedlib
+ lt_cv_sharedlib_from_linklib_cmd=$ECHO
+ ;;
+esac
+])
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
+ [Command to associate shared and link libraries])
+])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+
+
+# _LT_PATH_MANIFEST_TOOL
+# ----------------------
+# locate the manifest tool
+m4_defun([_LT_PATH_MANIFEST_TOOL],
+[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
+ [lt_cv_path_mainfest_tool=no
+ echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
+ $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+ lt_cv_path_mainfest_tool=yes
+ fi
+ rm -f conftest*])
+if test yes != "$lt_cv_path_mainfest_tool"; then
+ MANIFEST_TOOL=:
+fi
+_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
+])# _LT_PATH_MANIFEST_TOOL
+
+
+# _LT_DLL_DEF_P([FILE])
+# ---------------------
+# True iff FILE is a Windows DLL '.def' file.
+# Keep in sync with func_dll_def_p in the libtool script
+AC_DEFUN([_LT_DLL_DEF_P],
+[dnl
+ test DEF = "`$SED -n dnl
+ -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace
+ -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments
+ -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl
+ -e q dnl Only consider the first "real" line
+ $1`" dnl
+])# _LT_DLL_DEF_P
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw)
+ AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+ ;;
+*)
+ AC_CHECK_LIB(m, cos, LIBM=-lm)
+ ;;
+esac
+AC_SUBST([LIBM])
+])# LT_LIB_M
+
+# Old name:
+AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_CHECK_LIBM], [])
+
+
+# _LT_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------
+m4_defun([_LT_COMPILER_NO_RTTI],
+[m4_require([_LT_TAG_COMPILER])dnl
+
+_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test yes = "$GCC"; then
+ case $cc_basename in
+ nvcc*)
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
+ esac
+
+ _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+ lt_cv_prog_compiler_rtti_exceptions,
+ [-fno-rtti -fno-exceptions], [],
+ [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+ [Compiler flag to turn off builtin functions])
+])# _LT_COMPILER_NO_RTTI
+
+
+# _LT_CMD_GLOBAL_SYMBOLS
+# ----------------------
+m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[[BCDT]]'
+ ;;
+cygwin* | mingw* | pw32* | cegcc*)
+ symcode='[[ABCDGISTW]]'
+ ;;
+hpux*)
+ if test ia64 = "$host_cpu"; then
+ symcode='[[ABCDEGRST]]'
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[[BCDEGRST]]'
+ ;;
+osf*)
+ symcode='[[BCDEGQRST]]'
+ ;;
+solaris*)
+ symcode='[[BDRT]]'
+ ;;
+sco3.2v5*)
+ symcode='[[DT]]'
+ ;;
+sysv4.2uw2*)
+ symcode='[[DT]]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[[ABDT]]'
+ ;;
+sysv4)
+ symcode='[[DFNSTU]]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Gets list of data symbols to import.
+ lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
+ # Adjust the below global symbol transforms to fixup imported variables.
+ lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+ lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'"
+ lt_c_name_lib_hook="\
+ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\
+ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'"
+else
+ # Disable hooks by default.
+ lt_cv_sys_global_symbol_to_import=
+ lt_cdecl_hook=
+ lt_c_name_hook=
+ lt_c_name_lib_hook=
+fi
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
+$lt_cdecl_hook\
+" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
+$lt_c_name_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'"
+
+# Transform an extracted symbol line into symbol name with lib prefix and
+# symbol address.
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
+$lt_c_name_lib_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Fake it for dumpbin and say T for any non-static function,
+ # D for any global variable and I for any imported variable.
+ # Also find C++ and __fastcall symbols from MSVC++ or ICC,
+ # which start with @ or ?.
+ lt_cv_sys_global_symbol_pipe="$AWK ['"\
+" {last_section=section; section=\$ 3};"\
+" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
+" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
+" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
+" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
+" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
+" ' prfx=^$ac_symprfx]"
+ else
+ lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+ fi
+ lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+ if AC_TRY_EVAL(ac_compile); then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD
+ if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+ if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
+#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+/* DATA imports from DLLs on WIN32 can't be const, because runtime
+ relocations are performed -- see ld's documentation on pseudo-relocs. */
+# define LT@&t@_DLSYM_CONST
+#elif defined __osf__
+/* This system does not cope well with relocations in const data. */
+# define LT@&t@_DLSYM_CONST
+#else
+# define LT@&t@_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+ cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols. */
+LT@&t@_DLSYM_CONST struct {
+ const char *name;
+ void *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+ { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+ $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+ cat <<\_LT_EOF >> conftest.$ac_ext
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_globsym_save_LIBS=$LIBS
+ lt_globsym_save_CFLAGS=$CFLAGS
+ LIBS=conftstm.$ac_objext
+ CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+ if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then
+ pipe_works=yes
+ fi
+ LIBS=$lt_globsym_save_LIBS
+ CFLAGS=$lt_globsym_save_CFLAGS
+ else
+ echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+ cat conftest.$ac_ext >&5
+ fi
+ rm -rf conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test yes = "$pipe_works"; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ AC_MSG_RESULT(failed)
+else
+ AC_MSG_RESULT(ok)
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
+ nm_file_list_spec='@'
+fi
+
+_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+ [Take the output of nm and produce a listing of raw symbols and C names])
+_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+ [Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1],
+ [Transform the output of nm into a list of symbols to manually relocate])
+_LT_DECL([global_symbol_to_c_name_address],
+ [lt_cv_sys_global_symbol_to_c_name_address], [1],
+ [Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+ [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+ [Transform the output of nm in a C name address pair when lib prefix is needed])
+_LT_DECL([nm_interface], [lt_cv_nm_interface], [1],
+ [The name lister interface])
+_LT_DECL([], [nm_file_list_spec], [1],
+ [Specify filename containing input files for $NM])
+]) # _LT_CMD_GLOBAL_SYMBOLS
+
+
+# _LT_COMPILER_PIC([TAGNAME])
+# ---------------------------
+m4_defun([_LT_COMPILER_PIC],
+[m4_require([_LT_TAG_COMPILER])dnl
+_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_TAGVAR(lt_prog_compiler_static, $1)=
+
+m4_if([$1], [CXX], [
+ # C++ specific cases for pic, static, wl, etc.
+ if test yes = "$GXX"; then
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the '-m68020' flag to GCC prevents building anything better,
+ # like '-m68040'.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | cygwin* | os2* | pw32* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ case $host_os in
+ os2*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+ ;;
+ esac
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ haiku*)
+ # PIC is the default for Haiku.
+ # The "-static" flag exists, but is broken.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)=
+ ;;
+ interix[[3-9]]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix[[4-9]]*)
+ # All AIX code is PIC.
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ mingw* | cygwin* | os2* | pw32* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | dragonfly* | midnightbsd*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+ if test ia64 != "$host_cpu"; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ fi
+ ;;
+ aCC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ ecpc* )
+ # old Intel C++ for x86_64, which still supported -KPIC.
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ icpc* )
+ # Intel C++, used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
+ # IBM XL 8.0, 9.0 on PPC and BlueGene
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | $SED 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd* | netbsdelf*-gnu)
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC* | sunCC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+],
+[
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the '-m68020' flag to GCC prevents building anything better,
+ # like '-m68040'.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ case $host_os in
+ os2*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+ ;;
+ esac
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+
+ haiku*)
+ # PIC is the default for Haiku.
+ # The "-static" flag exists, but is broken.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)=
+ ;;
+
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+
+ interix[[3-9]]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ enable_shared=no
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+
+ case $cc_basename in
+ nvcc*) # Cuda Compiler Driver 2.2
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
+ if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
+ fi
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ case $cc_basename in
+ nagfor*)
+ # NAG Fortran compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ case $host_os in
+ os2*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+ ;;
+ esac
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC (with -KPIC) is the default.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ case $cc_basename in
+ # old Intel for x86_64, which still supported -KPIC.
+ ecc*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ # flang / f18. f95 an alias for gfortran or flang on Debian
+ flang* | f18* | f95*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ # icc used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ icc* | ifort*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ # Lahey Fortran 8.1.
+ lf95*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
+ ;;
+ nagfor*)
+ # NAG Fortran compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ ccc*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All Alpha code is PIC.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ xl* | bgxl* | bgf* | mpixl*)
+ # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | $SED 5q` in
+ *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
+ # Sun Fortran 8.3 passes all unrecognized flags to the linker
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+ ;;
+ *Sun\ F* | *Sun*Fortran*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ *Sun\ C*)
+ # Sun C 5.9
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ *Intel*\ [[CF]]*Compiler*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ *Portland\ Group*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ newsos6)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+
+ osf3* | osf4* | osf5*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All OSF/1 code is PIC.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ rdos*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ solaris*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ unicos*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+
+ uts4*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *)
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+])
+case $host_os in
+ # For platforms that do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+ ;;
+esac
+
+AC_CACHE_CHECK([for $compiler option to produce PIC],
+ [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
+ [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+ [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+ [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+ [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+ "" | " "*) ;;
+ *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+ esac],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+ [Additional compiler flags for building library objects])
+
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+ [How to pass a linker flag through the compiler])
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+ _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+ $lt_tmp_static_flag,
+ [],
+ [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+ [Compiler flag to prevent dynamic linking])
+])# _LT_COMPILER_PIC
+
+
+# _LT_LINKER_SHLIBS([TAGNAME])
+# ----------------------------
+# See if the linker supports building shared libraries.
+m4_defun([_LT_LINKER_SHLIBS],
+[AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+m4_if([$1], [CXX], [
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+ case $host_os in
+ aix[[4-9]]*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+ # Without the "-l" option, or with the "-B" option, AIX nm treats
+ # weak defined symbols like other global defined symbols, whereas
+ # GNU nm marks them as "W".
+ # While the 'weak' keyword is ignored in the Export File, we need
+ # it in the Import File for the 'aix-soname' feature, so we have
+ # to replace the "-B" option with "-P" for AIX nm.
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds
+ ;;
+ cygwin* | mingw* | cegcc*)
+ case $cc_basename in
+ cl* | icl*)
+ _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+ ;;
+ *)
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+ ;;
+ esac
+ ;;
+ linux* | k*bsd*-gnu | gnu*)
+ _LT_TAGVAR(link_all_deplibs, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+], [
+ runpath_var=
+ _LT_TAGVAR(allow_undefined_flag, $1)=
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(archive_cmds, $1)=
+ _LT_TAGVAR(archive_expsym_cmds, $1)=
+ _LT_TAGVAR(compiler_needs_object, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(hardcode_automatic, $1)=no
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ _LT_TAGVAR(hardcode_minus_L, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_TAGVAR(inherit_rpath, $1)=no
+ _LT_TAGVAR(link_all_deplibs, $1)=unknown
+ _LT_TAGVAR(module_cmds, $1)=
+ _LT_TAGVAR(module_expsym_cmds, $1)=
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+ _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+ _LT_TAGVAR(thread_safe_flag_spec, $1)=
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ _LT_TAGVAR(include_expsyms, $1)=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ' (' and ')$', so one must not match beginning or
+ # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
+ # as well as any symbol that contains 'd'.
+ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++ or Intel C++ Compiler.
+ if test yes != "$GCC"; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
+ with_gnu_ld=yes
+ ;;
+ openbsd* | bitrig*)
+ with_gnu_ld=no
+ ;;
+ linux* | k*bsd*-gnu | gnu*)
+ _LT_TAGVAR(link_all_deplibs, $1)=no
+ ;;
+ esac
+
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+
+ # On some targets, GNU ld is compatible enough with the native linker
+ # that we're better off using the native interface for both.
+ lt_use_gnu_ld_interface=no
+ if test yes = "$with_gnu_ld"; then
+ case $host_os in
+ aix*)
+ # The AIX port of GNU ld has always aspired to compatibility
+ # with the native linker. However, as the warning in the GNU ld
+ # block says, versions before 2.19.5* couldn't really create working
+ # shared libraries, regardless of the interface used.
+ case `$LD -v 2>&1` in
+ *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+ *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
+ *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ fi
+
+ if test yes = "$lt_use_gnu_ld_interface"; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='$wl'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v | $SED -e 's/([[^)]]\+)\s\+//' 2>&1` in
+ *GNU\ gold*) supports_anon_versioning=yes ;;
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix[[3-9]]*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test ia64 != "$host_cpu"; then
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)=''
+ ;;
+ m68k)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file, use it as
+ # is; otherwise, prepend EXPORTS...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ haiku*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ os2*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ shrext_cmds=.dll
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='@'
+ ;;
+
+ interix[[3-9]]*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+ tmp_diet=no
+ if test linux-dietlibc = "$host_os"; then
+ case $cc_basename in
+ diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
+ esac
+ fi
+ if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+ && test no = "$tmp_diet"
+ then
+ tmp_addflag=' $pic_flag'
+ tmp_sharedflag='-shared'
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group f77 and f90 compilers
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ lf95*) # Lahey Fortran 8.1
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ tmp_sharedflag='--shared' ;;
+ nagfor*) # NAGFOR 5.3
+ tmp_sharedflag='-Wl,-shared' ;;
+ xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+ tmp_sharedflag='-qmkshrobj'
+ tmp_addflag= ;;
+ nvcc*) # Cuda Compiler Driver 2.2
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+ ;;
+ esac
+ case `$CC -V 2>&1 | $SED 5q` in
+ *Sun\ C*) # Sun C 5.9
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+ tmp_sharedflag='-G' ;;
+ *Sun\ F*) # Sun Fortran 8.3
+ tmp_sharedflag='-G' ;;
+ esac
+ _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+
+ if test yes = "$supports_anon_versioning"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+ fi
+
+ case $cc_basename in
+ tcc*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
+ ;;
+ xlf* | bgf* | bgxlf* | mpixlf*)
+ # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+ if test yes = "$supports_anon_versioning"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ esac
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+
+ if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then
+ runpath_var=
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test ia64 = "$host_cpu"; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+ # Without the "-l" option, or with the "-B" option, AIX nm treats
+ # weak defined symbols like other global defined symbols, whereas
+ # GNU nm marks them as "W".
+ # While the 'weak' keyword is ignored in the Export File, we need
+ # it in the Import File for the 'aix-soname' feature, so we have
+ # to replace the "-B" option with "-P" for AIX nm.
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # have runtime linking enabled, and use it for executables.
+ # For shared libraries, we enable/disable runtime linking
+ # depending on the kind of the shared library created -
+ # when "with_aix_soname,aix_use_runtimelinking" is:
+ # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
+ # "aix,yes" lib.so shared, rtl:yes, for executables
+ # lib.a static archive
+ # "both,no" lib.so.V(shr.o) shared, rtl:yes
+ # lib.a(lib.so.V) shared, rtl:no, for executables
+ # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a(lib.so.V) shared, rtl:no
+ # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a static archive
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # With aix-soname=svr4, we create the lib.so.V shared archives only,
+ # so we don't have lib.a shared libs to link our executables.
+ # We have to force runtime linking in this case.
+ aix_use_runtimelinking=yes
+ LDFLAGS="$LDFLAGS -Wl,-brtl"
+ fi
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_TAGVAR(archive_cmds, $1)=''
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
+ case $with_aix_soname,$aix_use_runtimelinking in
+ aix,*) ;; # traditional, no import file
+ svr4,* | *,yes) # use import file
+ # The Import File defines what to hardcode.
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+ ;;
+ esac
+
+ if test yes = "$GCC"; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`$CC -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag="$shared_flag "'$wl-G'
+ fi
+ # Need to ensure runtime linking is disabled for the traditional
+ # shared library, or the linker may eventually find shared libraries
+ # /with/ Import File - we do not want to mix them.
+ shared_flag_aix='-shared'
+ shared_flag_svr4='-shared $wl-G'
+ else
+ # not using gcc
+ if test ia64 = "$host_cpu"; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag='$wl-G'
+ else
+ shared_flag='$wl-bM:SRE'
+ fi
+ shared_flag_aix='$wl-bM:SRE'
+ shared_flag_svr4='$wl-G'
+ fi
+ fi
+
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+ else
+ if test ia64 = "$host_cpu"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
+ _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
+ if test yes = "$with_gnu_ld"; then
+ # We only use this code for GNU lds that support --whole-archive.
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+ else
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+ # -brtl affects multiple linker settings, -berok does not and is overridden later
+ compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
+ if test svr4 != "$with_aix_soname"; then
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+ fi
+ if test aix != "$with_aix_soname"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+ else
+ # used by -dlpreopen to get the symbols
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
+ fi
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)=''
+ ;;
+ m68k)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ ;;
+
+ bsdi[[45]]*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++ or Intel C++ Compiler.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ case $cc_basename in
+ cl* | icl*)
+ # Native MSVC or ICC
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='@'
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+ cp "$export_symbols" "$output_objdir/$soname.def";
+ echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+ else
+ $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+ fi~
+ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+ linknames='
+ # The linker will not automatically build a static lib if we build a DLL.
+ # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+ # Don't use ranlib
+ _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+ _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+ lt_tool_outputfile="@TOOL_OUTPUT@"~
+ case $lt_outputfile in
+ *.exe|*.EXE) ;;
+ *)
+ lt_outputfile=$lt_outputfile.exe
+ lt_tool_outputfile=$lt_tool_outputfile.exe
+ ;;
+ esac~
+ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+ $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+ $RM "$lt_outputfile.manifest";
+ fi'
+ ;;
+ *)
+ # Assume MSVC and ICC wrapper
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+ # FIXME: Should let the user specify the lib program.
+ _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+ esac
+ ;;
+
+ darwin* | rhapsody*)
+ _LT_DARWIN_LINKER_FEATURES($1)
+ ;;
+
+ dgux*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2.*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | dragonfly* | midnightbsd*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ hpux9*)
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ ;;
+
+ hpux10*)
+ if test yes,no = "$GCC,$with_gnu_ld"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test no = "$with_gnu_ld"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test yes,no = "$GCC,$with_gnu_ld"; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ m4_if($1, [], [
+ # Older versions of the 11.00 compiler do not understand -b yet
+ # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+ _LT_LINKER_OPTION([if $CC understands -b],
+ _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
+ [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
+ [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
+ [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
+ ;;
+ esac
+ fi
+ if test no = "$with_gnu_ld"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ # Try to use the -exported_symbol ld option, if it does not
+ # work, assume that -exports_file does not work either and
+ # implicitly export all symbols.
+ # This should be the same for all languages, so no per-tag cache variable.
+ AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
+ [lt_cv_irix_exported_symbol],
+ [save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
+ AC_LINK_IFELSE(
+ [AC_LANG_SOURCE(
+ [AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
+ [C++], [[int foo (void) { return 0; }]],
+ [Fortran 77], [[
+ subroutine foo
+ end]],
+ [Fortran], [[
+ subroutine foo
+ end]])])],
+ [lt_cv_irix_exported_symbol=yes],
+ [lt_cv_irix_exported_symbol=no])
+ LDFLAGS=$save_LDFLAGS])
+ if test yes = "$lt_cv_irix_exported_symbol"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
+ fi
+ _LT_TAGVAR(link_all_deplibs, $1)=no
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(inherit_rpath, $1)=yes
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ linux*)
+ case $cc_basename in
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ ;;
+ esac
+ ;;
+
+ netbsd* | netbsdelf*-gnu)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ newsos6)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *nto* | *qnx*)
+ ;;
+
+ openbsd* | bitrig*)
+ if test -f /usr/libexec/ld.so; then
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ fi
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ os2*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ shrext_cmds=.dll
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='@'
+ ;;
+
+ osf3*)
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ else
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ else
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ solaris*)
+ _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+ if test yes = "$GCC"; then
+ wlarc='$wl'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ else
+ case `$CC -V 2>&1` in
+ *"Compilers 5.0"*)
+ wlarc=''
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+ ;;
+ *)
+ wlarc='$wl'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ ;;
+ esac
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands '-z linker_flag'. GCC discards it without '$wl',
+ # but is careful enough not to reorder.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+ fi
+ ;;
+ esac
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ sunos4*)
+ if test sequent = "$host_vendor"; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ ;;
+ motorola)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4.3*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We CANNOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+ _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+
+ if test sni = "$host_vendor"; then
+ case $host in
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym'
+ ;;
+ esac
+ fi
+ fi
+])
+AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
+
+_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+
+_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+_LT_DECL([], [extract_expsyms_cmds], [2],
+ [The commands to extract the exported symbol list from a shared archive])
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+ # Assume -lc should be added
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+ if test yes,yes = "$GCC,$enable_shared"; then
+ case $_LT_TAGVAR(archive_cmds, $1) in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ AC_CACHE_CHECK([whether -lc should be explicitly linked in],
+ [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
+ [$RM conftest*
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+ pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+ _LT_TAGVAR(allow_undefined_flag, $1)=
+ if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+ then
+ lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ else
+ lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ fi
+ _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $RM conftest*
+ ])
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+ [Whether or not to add -lc for building shared libraries])
+_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+ [enable_shared_with_static_runtimes], [0],
+ [Whether or not to disallow shared libs when runtime libs are static])
+_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+ [Compiler flag to allow reflexive dlopens])
+_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+ [Compiler flag to generate shared objects directly from archives])
+_LT_TAGDECL([], [compiler_needs_object], [1],
+ [Whether the compiler copes with passing no objects directly])
+_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+ [Create an old-style archive from a shared archive])
+_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+ [Create a temporary old-style archive to link instead of a shared archive])
+_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+_LT_TAGDECL([], [archive_expsym_cmds], [2])
+_LT_TAGDECL([], [module_cmds], [2],
+ [Commands used to build a loadable module if different from building
+ a shared archive.])
+_LT_TAGDECL([], [module_expsym_cmds], [2])
+_LT_TAGDECL([], [with_gnu_ld], [1],
+ [Whether we are building with GNU ld or not])
+_LT_TAGDECL([], [allow_undefined_flag], [1],
+ [Flag that allows shared libraries with undefined symbols to be built])
+_LT_TAGDECL([], [no_undefined_flag], [1],
+ [Flag that enforces no undefined symbols])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+ [Flag to hardcode $libdir into a binary during linking.
+ This must work even if $libdir does not exist])
+_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+ [Whether we need a single "-rpath" flag with a separated argument])
+_LT_TAGDECL([], [hardcode_direct], [0],
+ [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
+ DIR into the resulting binary])
+_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+ [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
+ DIR into the resulting binary and the resulting library dependency is
+ "absolute", i.e impossible to change by setting $shlibpath_var if the
+ library is relocated])
+_LT_TAGDECL([], [hardcode_minus_L], [0],
+ [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+ into the resulting binary])
+_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+ [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+ into the resulting binary])
+_LT_TAGDECL([], [hardcode_automatic], [0],
+ [Set to "yes" if building a shared library automatically hardcodes DIR
+ into the library and all subsequent libraries and executables linked
+ against it])
+_LT_TAGDECL([], [inherit_rpath], [0],
+ [Set to yes if linker adds runtime paths of dependent libraries
+ to runtime path list])
+_LT_TAGDECL([], [link_all_deplibs], [0],
+ [Whether libtool must link a program against all its dependency libraries])
+_LT_TAGDECL([], [always_export_symbols], [0],
+ [Set to "yes" if exported symbols are required])
+_LT_TAGDECL([], [export_symbols_cmds], [2],
+ [The commands to list exported symbols])
+_LT_TAGDECL([], [exclude_expsyms], [1],
+ [Symbols that should not be listed in the preloaded symbols])
+_LT_TAGDECL([], [include_expsyms], [1],
+ [Symbols that must always be exported])
+_LT_TAGDECL([], [prelink_cmds], [2],
+ [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [postlink_cmds], [2],
+ [Commands necessary for finishing linking programs])
+_LT_TAGDECL([], [file_list_spec], [1],
+ [Specify filename containing input files])
+dnl FIXME: Not yet implemented
+dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+dnl [Compiler flag to generate thread safe objects])
+])# _LT_LINKER_SHLIBS
+
+
+# _LT_LANG_C_CONFIG([TAG])
+# ------------------------
+# Ensure that the configuration variables for a C compiler are suitably
+# defined. These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_C_CONFIG],
+[m4_require([_LT_DECL_EGREP])dnl
+lt_save_CC=$CC
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_TAG_COMPILER
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+ LT_SYS_DLOPEN_SELF
+ _LT_CMD_STRIPLIB
+
+ # Report what library types will actually be built
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test no = "$can_build_shared" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test yes = "$enable_shared" || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC=$lt_save_CC
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_LANG_CXX_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a C++ compiler are suitably
+# defined. These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_CXX_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+if test -n "$CXX" && ( test no != "$CXX" &&
+ ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
+ (test g++ != "$CXX"))); then
+ AC_PROG_CXXCPP
+else
+ _lt_caught_CXX_error=yes
+fi
+
+AC_LANG_PUSH(C++)
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(compiler_needs_object, $1)=no
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_caught_CXX_error"; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="int some_variable = 0;"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC=$CC
+ lt_save_CFLAGS=$CFLAGS
+ lt_save_LD=$LD
+ lt_save_GCC=$GCC
+ GCC=$GXX
+ lt_save_with_gnu_ld=$with_gnu_ld
+ lt_save_path_LD=$lt_cv_path_LD
+ if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+ else
+ $as_unset lt_cv_prog_gnu_ld
+ fi
+ if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+ else
+ $as_unset lt_cv_path_LD
+ fi
+ test -z "${LDCXX+set}" || LD=$LDCXX
+ CC=${CXX-"c++"}
+ CFLAGS=$CXXFLAGS
+ compiler=$CC
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+
+ if test -n "$compiler"; then
+ # We don't want -fno-exception when compiling C++ code, so set the
+ # no_builtin_flag separately
+ if test yes = "$GXX"; then
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+ else
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+ fi
+
+ if test yes = "$GXX"; then
+ # Set up default GNU C++ configuration
+
+ LT_PATH_LD
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test yes = "$with_gnu_ld"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='$wl'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+ $GREP 'no-whole-archive' > /dev/null; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+
+ else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+ fi
+
+ # PORTME: fill in a description of your system's C++ link characteristics
+ AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aix[[4-9]]*)
+ if test ia64 = "$host_cpu"; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # have runtime linking enabled, and use it for executables.
+ # For shared libraries, we enable/disable runtime linking
+ # depending on the kind of the shared library created -
+ # when "with_aix_soname,aix_use_runtimelinking" is:
+ # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
+ # "aix,yes" lib.so shared, rtl:yes, for executables
+ # lib.a static archive
+ # "both,no" lib.so.V(shr.o) shared, rtl:yes
+ # lib.a(lib.so.V) shared, rtl:no, for executables
+ # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a(lib.so.V) shared, rtl:no
+ # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a static archive
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # With aix-soname=svr4, we create the lib.so.V shared archives only,
+ # so we don't have lib.a shared libs to link our executables.
+ # We have to force runtime linking in this case.
+ aix_use_runtimelinking=yes
+ LDFLAGS="$LDFLAGS -Wl,-brtl"
+ fi
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_TAGVAR(archive_cmds, $1)=''
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
+ case $with_aix_soname,$aix_use_runtimelinking in
+ aix,*) ;; # no import file
+ svr4,* | *,yes) # use import file
+ # The Import File defines what to hardcode.
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+ ;;
+ esac
+
+ if test yes = "$GXX"; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`$CC -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ esac
+ shared_flag='-shared'
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag=$shared_flag' $wl-G'
+ fi
+ # Need to ensure runtime linking is disabled for the traditional
+ # shared library, or the linker may eventually find shared libraries
+ # /with/ Import File - we do not want to mix them.
+ shared_flag_aix='-shared'
+ shared_flag_svr4='-shared $wl-G'
+ else
+ # not using gcc
+ if test ia64 = "$host_cpu"; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag='$wl-G'
+ else
+ shared_flag='$wl-bM:SRE'
+ fi
+ shared_flag_aix='$wl-bM:SRE'
+ shared_flag_svr4='$wl-G'
+ fi
+ fi
+
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to
+ # export.
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ # The "-G" linker flag allows undefined symbols.
+ _LT_TAGVAR(no_undefined_flag, $1)='-bernotok'
+ # Determine the default libpath from the value encoded in an empty
+ # executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+ else
+ if test ia64 = "$host_cpu"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
+ _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
+ if test yes = "$with_gnu_ld"; then
+ # We only use this code for GNU lds that support --whole-archive.
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+ else
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+ # -brtl affects multiple linker settings, -berok does not and is overridden later
+ compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
+ if test svr4 != "$with_aix_soname"; then
+ # This is similar to how AIX traditionally builds its shared
+ # libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+ fi
+ if test aix != "$with_aix_soname"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+ else
+ # used by -dlpreopen to get the symbols
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
+ fi
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ case $GXX,$cc_basename in
+ ,cl* | no,cl* | ,icl* | no,icl*)
+ # Native MSVC or ICC
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='@'
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+ cp "$export_symbols" "$output_objdir/$soname.def";
+ echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+ else
+ $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+ fi~
+ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+ linknames='
+ # The linker will not automatically build a static lib if we build a DLL.
+ # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ # Don't use ranlib
+ _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+ _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+ lt_tool_outputfile="@TOOL_OUTPUT@"~
+ case $lt_outputfile in
+ *.exe|*.EXE) ;;
+ *)
+ lt_outputfile=$lt_outputfile.exe
+ lt_tool_outputfile=$lt_tool_outputfile.exe
+ ;;
+ esac~
+ func_to_tool_file "$lt_outputfile"~
+ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+ $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+ $RM "$lt_outputfile.manifest";
+ fi'
+ ;;
+ *)
+ # g++
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file, use it as
+ # is; otherwise, prepend EXPORTS...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ darwin* | rhapsody*)
+ _LT_DARWIN_LINKER_FEATURES($1)
+ ;;
+
+ os2*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ shrext_cmds=.dll
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='@'
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ freebsd2.*)
+ # C++ shared libraries reported to be fairly broken before
+ # switch to ELF
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ freebsd-elf*)
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ ;;
+
+ freebsd* | dragonfly* | midnightbsd*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+
+ haiku*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ hpux9*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test yes = "$GXX"; then
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ hpux10*|hpux11*)
+ if test no = "$with_gnu_ld"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test yes = "$GXX"; then
+ if test no = "$with_gnu_ld"; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ interix[[3-9]]*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test yes = "$GXX"; then
+ if test no = "$with_gnu_ld"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
+ fi
+ fi
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+ esac
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(inherit_rpath, $1)=yes
+ ;;
+
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc* | ecpc* )
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ case `$CC -V` in
+ *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
+ _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
+ _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
+ $RANLIB $oldlib'
+ _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 6 and above use weak symbols
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
+ ;;
+ xl* | mpixl* | bgxl*)
+ # IBM XL 8.0 on PPC, with GNU ld
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ if test yes = "$supports_anon_versioning"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ *)
+ case `$CC -V 2>&1 | $SED 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+
+ # Not sure whether something based on
+ # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+ # would be better.
+ output_verbose_link_cmd='func_echo_all'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ m88k*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+
+ *nto* | *qnx*)
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+
+ openbsd* | bitrig*)
+ if test -f /usr/libexec/ld.so; then
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+ fi
+ output_verbose_link_cmd=func_echo_all
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ case $host in
+ osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+ *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+ esac
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx*)
+ case $host in
+ osf3*)
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ ;;
+ *)
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~
+ $RM $lib.exp'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test yes,no = "$GXX,$with_gnu_ld"; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+ case $host in
+ osf3*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ psos*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ solaris*)
+ case $cc_basename in
+ CC* | sunCC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+ _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands '-z linker_flag'.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+ ;;
+ esac
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+
+ output_verbose_link_cmd='func_echo_all'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test yes,no = "$GXX,$with_gnu_ld"; then
+ _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs'
+ if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+ else
+ # g++ 2.7 appears to require '-G' NOT '-shared' on this
+ # platform.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
+ fi
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We CANNOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+ _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
+ '"$_LT_TAGVAR(old_archive_cmds, $1)"
+ _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
+ '"$_LT_TAGVAR(reload_cmds, $1)"
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+
+ AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+ test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
+
+ _LT_TAGVAR(GCC, $1)=$GXX
+ _LT_TAGVAR(LD, $1)=$LD
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_SYS_HIDDEN_LIBDEPS($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ CC=$lt_save_CC
+ CFLAGS=$lt_save_CFLAGS
+ LDCXX=$LD
+ LD=$lt_save_LD
+ GCC=$lt_save_GCC
+ with_gnu_ld=$lt_save_with_gnu_ld
+ lt_cv_path_LDCXX=$lt_cv_path_LD
+ lt_cv_path_LD=$lt_save_path_LD
+ lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+ lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test yes != "$_lt_caught_CXX_error"
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _LT_FUNC_STRIPNAME_CNF
+# ----------------------
+# func_stripname_cnf prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+#
+# This function is identical to the (non-XSI) version of func_stripname,
+# except this one can be used by m4 code that may be executed by configure,
+# rather than the libtool script.
+m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
+AC_REQUIRE([_LT_DECL_SED])
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
+func_stripname_cnf ()
+{
+ case @S|@2 in
+ .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;;
+ *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;;
+ esac
+} # func_stripname_cnf
+])# _LT_FUNC_STRIPNAME_CNF
+
+
+# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+# ---------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
+# Dependencies to place before and after the object being linked:
+_LT_TAGVAR(predep_objects, $1)=
+_LT_TAGVAR(postdep_objects, $1)=
+_LT_TAGVAR(predeps, $1)=
+_LT_TAGVAR(postdeps, $1)=
+_LT_TAGVAR(compiler_lib_search_path, $1)=
+
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library. It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+int a;
+void foo (void) { a = 0; }
+_LT_EOF
+], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+_LT_EOF
+], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+ subroutine foo
+ implicit none
+ integer*4 a
+ a=0
+ return
+ end
+_LT_EOF
+], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+ subroutine foo
+ implicit none
+ integer a
+ a=0
+ return
+ end
+_LT_EOF
+], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+public class foo {
+ private int a;
+ public void bar (void) {
+ a = 0;
+ }
+};
+_LT_EOF
+], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
+package foo
+func foo() {
+}
+_LT_EOF
+])
+
+_lt_libdeps_save_CFLAGS=$CFLAGS
+case "$CC $CFLAGS " in #(
+*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
+*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
+*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
+esac
+
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ for p in `eval "$output_verbose_link_cmd"`; do
+ case $prev$p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test x-L = "$p" ||
+ test x-R = "$p"; then
+ prev=$p
+ continue
+ fi
+
+ # Expand the sysroot to ease extracting the directories later.
+ if test -z "$prev"; then
+ case $p in
+ -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
+ -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
+ -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
+ esac
+ fi
+ case $p in
+ =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
+ esac
+ if test no = "$pre_test_object_deps_done"; then
+ case $prev in
+ -L | -R)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+ _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p
+ else
+ _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+ _LT_TAGVAR(postdeps, $1)=$prev$p
+ else
+ _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p"
+ fi
+ fi
+ prev=
+ ;;
+
+ *.lto.$objext) ;; # Ignore GCC LTO objects
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test no = "$pre_test_object_deps_done"; then
+ if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+ _LT_TAGVAR(predep_objects, $1)=$p
+ else
+ _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+ fi
+ else
+ if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+ _LT_TAGVAR(postdep_objects, $1)=$p
+ else
+ _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$RM -f confest.$objext
+CFLAGS=$_lt_libdeps_save_CFLAGS
+
+# PORTME: override above test on systems where it is broken
+m4_if([$1], [CXX],
+[case $host_os in
+interix[[3-9]]*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ _LT_TAGVAR(predep_objects,$1)=
+ _LT_TAGVAR(postdep_objects,$1)=
+ _LT_TAGVAR(postdeps,$1)=
+ ;;
+esac
+])
+
+case " $_LT_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'`
+fi
+_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+ [The directories searched by this compiler when creating a shared library])
+_LT_TAGDECL([], [predep_objects], [1],
+ [Dependencies to place before and after the objects being linked to
+ create a shared library])
+_LT_TAGDECL([], [postdep_objects], [1])
+_LT_TAGDECL([], [predeps], [1])
+_LT_TAGDECL([], [postdeps], [1])
+_LT_TAGDECL([], [compiler_lib_search_path], [1],
+ [The library search path used internally by the compiler when linking
+ a shared library])
+])# _LT_SYS_HIDDEN_LIBDEPS
+
+
+# _LT_LANG_F77_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a Fortran 77 compiler are
+# suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_F77_CONFIG],
+[AC_LANG_PUSH(Fortran 77)
+if test -z "$F77" || test no = "$F77"; then
+ _lt_disable_F77=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the F77 compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_disable_F77"; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="\
+ subroutine t
+ return
+ end
+"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code="\
+ program t
+ end
+"
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC=$CC
+ lt_save_GCC=$GCC
+ lt_save_CFLAGS=$CFLAGS
+ CC=${F77-"f77"}
+ CFLAGS=$FFLAGS
+ compiler=$CC
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+ GCC=$G77
+ if test -n "$compiler"; then
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test no = "$can_build_shared" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test yes = "$enable_shared" || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_TAGVAR(GCC, $1)=$G77
+ _LT_TAGVAR(LD, $1)=$LD
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ GCC=$lt_save_GCC
+ CC=$lt_save_CC
+ CFLAGS=$lt_save_CFLAGS
+fi # test yes != "$_lt_disable_F77"
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_LANG_FC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for a Fortran compiler are
+# suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_FC_CONFIG],
+[AC_LANG_PUSH(Fortran)
+
+if test -z "$FC" || test no = "$FC"; then
+ _lt_disable_FC=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for fc test sources.
+ac_ext=${ac_fc_srcext-f}
+
+# Object file extension for compiled fc test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the FC compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_disable_FC"; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="\
+ subroutine t
+ return
+ end
+"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code="\
+ program t
+ end
+"
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC=$CC
+ lt_save_GCC=$GCC
+ lt_save_CFLAGS=$CFLAGS
+ CC=${FC-"f95"}
+ CFLAGS=$FCFLAGS
+ compiler=$CC
+ GCC=$ac_cv_fc_compiler_gnu
+
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+
+ if test -n "$compiler"; then
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test no = "$can_build_shared" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test yes = "$enable_shared" || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu
+ _LT_TAGVAR(LD, $1)=$LD
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_SYS_HIDDEN_LIBDEPS($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ GCC=$lt_save_GCC
+ CC=$lt_save_CC
+ CFLAGS=$lt_save_CFLAGS
+fi # test yes != "$_lt_disable_FC"
+
+AC_LANG_POP
+])# _LT_LANG_FC_CONFIG
+
+
+# _LT_LANG_GCJ_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Java Compiler compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_GCJ_CONFIG],
+[AC_REQUIRE([LT_PROG_GCJ])dnl
+AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+CFLAGS=$GCJFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)=$LD
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GCJ_CONFIG
+
+
+# _LT_LANG_GO_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Go compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_GO_CONFIG],
+[AC_REQUIRE([LT_PROG_GO])dnl
+AC_LANG_SAVE
+
+# Source file extension for Go test sources.
+ac_ext=go
+
+# Object file extension for compiled Go test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="package main; func main() { }"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='package main; func main() { }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GOC-"gccgo"}
+CFLAGS=$GOFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)=$LD
+_LT_CC_BASENAME([$compiler])
+
+# Go did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GO_CONFIG
+
+
+# _LT_LANG_RC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for the Windows resource compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_RC_CONFIG],
+[AC_REQUIRE([LT_PROG_RC])dnl
+AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code=$lt_simple_compile_test_code
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+CFLAGS=
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+if test -n "$compiler"; then
+ :
+ _LT_CONFIG($1)
+fi
+
+GCC=$lt_save_GCC
+AC_LANG_RESTORE
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_RC_CONFIG
+
+
+# LT_PROG_GCJ
+# -----------
+AC_DEFUN([LT_PROG_GCJ],
+[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+ [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+ [AC_CHECK_TOOL(GCJ, gcj,)
+ test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2"
+ AC_SUBST(GCJFLAGS)])])[]dnl
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+
+
+# LT_PROG_GO
+# ----------
+AC_DEFUN([LT_PROG_GO],
+[AC_CHECK_TOOL(GOC, gccgo,)
+])
+
+
+# LT_PROG_RC
+# ----------
+AC_DEFUN([LT_PROG_RC],
+[AC_CHECK_TOOL(RC, windres,)
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_RC], [])
+
+
+# _LT_DECL_EGREP
+# --------------
+# If we don't have a new enough Autoconf to choose the best grep
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_EGREP],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_REQUIRE([AC_PROG_FGREP])dnl
+test -z "$GREP" && GREP=grep
+_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+_LT_DECL([], [EGREP], [1], [An ERE matcher])
+_LT_DECL([], [FGREP], [1], [A literal string matcher])
+dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+AC_SUBST([GREP])
+])
+
+
+# _LT_DECL_OBJDUMP
+# --------------
+# If we don't have a new enough Autoconf to choose the best objdump
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_OBJDUMP],
+[AC_CHECK_TOOL(OBJDUMP, objdump, false)
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
+AC_SUBST([OBJDUMP])
+])
+
+# _LT_DECL_DLLTOOL
+# ----------------
+# Ensure DLLTOOL variable is set.
+m4_defun([_LT_DECL_DLLTOOL],
+[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
+AC_SUBST([DLLTOOL])
+])
+
+# _LT_DECL_FILECMD
+# ----------------
+# Check for a file(cmd) program that can be used to detect file type and magic
+m4_defun([_LT_DECL_FILECMD],
+[AC_CHECK_TOOL([FILECMD], [file], [:])
+_LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types])
+])# _LD_DECL_FILECMD
+
+# _LT_DECL_SED
+# ------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible. Prefer GNU sed if found.
+m4_defun([_LT_DECL_SED],
+[AC_PROG_SED
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+ [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+])# _LT_DECL_SED
+
+m4_ifndef([AC_PROG_SED], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_SED. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+############################################################
+
+m4_defun([AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f "$lt_ac_sed" && continue
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test 10 -lt "$lt_ac_count" && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test "$lt_ac_count" -gt "$lt_ac_max"; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])#AC_PROG_SED
+])#m4_ifndef
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_SED], [])
+
+
+# _LT_CHECK_SHELL_FEATURES
+# ------------------------
+# Find out whether the shell is Bourne or XSI compatible,
+# or has some other useful features.
+m4_defun([_LT_CHECK_SHELL_FEATURES],
+[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ lt_unset=unset
+else
+ lt_unset=false
+fi
+_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ lt_SP2NL='tr \040 \012'
+ lt_NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ lt_SP2NL='tr \100 \n'
+ lt_NL2SP='tr \r\n \100\100'
+ ;;
+esac
+_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+])# _LT_CHECK_SHELL_FEATURES
+
+
+# _LT_PATH_CONVERSION_FUNCTIONS
+# -----------------------------
+# Determine what file name conversion functions should be used by
+# func_to_host_file (and, implicitly, by func_to_host_path). These are needed
+# for certain cross-compile configurations and native mingw.
+m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_MSG_CHECKING([how to convert $build file names to $host format])
+AC_CACHE_VAL(lt_cv_to_host_file_cmd,
+[case $host in
+ *-*-mingw* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+ ;;
+ *-*-cygwin* )
+ lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+ ;;
+ * ) # otherwise, assume *nix
+ lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+ ;;
+ esac
+ ;;
+ *-*-cygwin* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+ ;;
+ *-*-cygwin* )
+ lt_cv_to_host_file_cmd=func_convert_file_noop
+ ;;
+ * ) # otherwise, assume *nix
+ lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+ ;;
+ esac
+ ;;
+ * ) # unhandled hosts (and "normal" native builds)
+ lt_cv_to_host_file_cmd=func_convert_file_noop
+ ;;
+esac
+])
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
+_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
+ [0], [convert $build file names to $host format])dnl
+
+AC_MSG_CHECKING([how to convert $build file names to toolchain format])
+AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
+[#assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+ *-*-mingw* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+ ;;
+ esac
+ ;;
+esac
+])
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
+_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
+ [0], [convert $build files to toolchain format])dnl
+])# _LT_PATH_CONVERSION_FUNCTIONS
diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4
new file mode 100644
index 0000000..b0b5e9c
--- /dev/null
+++ b/m4/ltoptions.m4
@@ -0,0 +1,437 @@
+# Helper functions for option handling. -*- Autoconf -*-
+#
+# Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 Free
+# Software Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 8 ltoptions.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+
+
+# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+# ------------------------------------------
+m4_define([_LT_MANGLE_OPTION],
+[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+
+
+# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+# ---------------------------------------
+# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+# matching handler defined, dispatch to it. Other OPTION-NAMEs are
+# saved as a flag.
+m4_define([_LT_SET_OPTION],
+[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+ _LT_MANGLE_DEFUN([$1], [$2]),
+ [m4_warning([Unknown $1 option '$2'])])[]dnl
+])
+
+
+# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+# ------------------------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+m4_define([_LT_IF_OPTION],
+[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+
+
+# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+# -------------------------------------------------------
+# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+# are set.
+m4_define([_LT_UNLESS_OPTIONS],
+[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+ [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+ [m4_define([$0_found])])])[]dnl
+m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+])[]dnl
+])
+
+
+# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+# ----------------------------------------
+# OPTION-LIST is a space-separated list of Libtool options associated
+# with MACRO-NAME. If any OPTION has a matching handler declared with
+# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+# the unknown option and exit.
+m4_defun([_LT_SET_OPTIONS],
+[# Set options
+m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+ [_LT_SET_OPTION([$1], _LT_Option)])
+
+m4_if([$1],[LT_INIT],[
+ dnl
+ dnl Simply set some default values (i.e off) if boolean options were not
+ dnl specified:
+ _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+ ])
+ _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+ ])
+ dnl
+ dnl If no reference was made to various pairs of opposing options, then
+ dnl we run the default mode handler for the pair. For example, if neither
+ dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
+ dnl archives by default:
+ _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+ _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+ _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+ _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+ [_LT_ENABLE_FAST_INSTALL])
+ _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
+ [_LT_WITH_AIX_SONAME([aix])])
+ ])
+])# _LT_SET_OPTIONS
+
+
+## --------------------------------- ##
+## Macros to handle LT_INIT options. ##
+## --------------------------------- ##
+
+# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+# -----------------------------------------
+m4_define([_LT_MANGLE_DEFUN],
+[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+
+
+# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+# -----------------------------------------------
+m4_define([LT_OPTION_DEFINE],
+[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+])# LT_OPTION_DEFINE
+
+
+# dlopen
+# ------
+LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+])
+
+AU_DEFUN([AC_LIBTOOL_DLOPEN],
+[_LT_SET_OPTION([LT_INIT], [dlopen])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'dlopen' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+
+
+# win32-dll
+# ---------
+# Declare package support for building win32 dll's.
+LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+[enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
+ AC_CHECK_TOOL(AS, as, false)
+ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+ AC_CHECK_TOOL(OBJDUMP, objdump, false)
+ ;;
+esac
+
+test -z "$AS" && AS=as
+_LT_DECL([], [AS], [1], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
+])# win32-dll
+
+AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+_LT_SET_OPTION([LT_INIT], [win32-dll])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'win32-dll' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+
+
+# _LT_ENABLE_SHARED([DEFAULT])
+# ----------------------------
+# implement the --enable-shared flag, and supports the 'shared' and
+# 'disable-shared' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_SHARED],
+[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([shared],
+ [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+ [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac],
+ [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+
+ _LT_DECL([build_libtool_libs], [enable_shared], [0],
+ [Whether or not to build shared libraries])
+])# _LT_ENABLE_SHARED
+
+LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+])
+
+AC_DEFUN([AC_DISABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], [disable-shared])
+])
+
+AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+
+
+
+# _LT_ENABLE_STATIC([DEFAULT])
+# ----------------------------
+# implement the --enable-static flag, and support the 'static' and
+# 'disable-static' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_STATIC],
+[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([static],
+ [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+ [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac],
+ [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+
+ _LT_DECL([build_old_libs], [enable_static], [0],
+ [Whether or not to build static libraries])
+])# _LT_ENABLE_STATIC
+
+LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+])
+
+AC_DEFUN([AC_DISABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], [disable-static])
+])
+
+AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+
+
+
+# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+# ----------------------------------
+# implement the --enable-fast-install flag, and support the 'fast-install'
+# and 'disable-fast-install' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_FAST_INSTALL],
+[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([fast-install],
+ [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+ [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac],
+ [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+
+_LT_DECL([fast_install], [enable_fast_install], [0],
+ [Whether or not to optimize for fast installation])dnl
+])# _LT_ENABLE_FAST_INSTALL
+
+LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+
+# Old names:
+AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the 'fast-install' option into LT_INIT's first parameter.])
+])
+
+AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the 'disable-fast-install' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+
+
+# _LT_WITH_AIX_SONAME([DEFAULT])
+# ----------------------------------
+# implement the --with-aix-soname flag, and support the `aix-soname=aix'
+# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
+# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'.
+m4_define([_LT_WITH_AIX_SONAME],
+[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
+shared_archive_member_spec=
+case $host,$enable_shared in
+power*-*-aix[[5-9]]*,yes)
+ AC_MSG_CHECKING([which variant of shared library versioning to provide])
+ AC_ARG_WITH([aix-soname],
+ [AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
+ [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
+ [case $withval in
+ aix|svr4|both)
+ ;;
+ *)
+ AC_MSG_ERROR([Unknown argument to --with-aix-soname])
+ ;;
+ esac
+ lt_cv_with_aix_soname=$with_aix_soname],
+ [AC_CACHE_VAL([lt_cv_with_aix_soname],
+ [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
+ with_aix_soname=$lt_cv_with_aix_soname])
+ AC_MSG_RESULT([$with_aix_soname])
+ if test aix != "$with_aix_soname"; then
+ # For the AIX way of multilib, we name the shared archive member
+ # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
+ # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
+ # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
+ # the AIX toolchain works better with OBJECT_MODE set (default 32).
+ if test 64 = "${OBJECT_MODE-32}"; then
+ shared_archive_member_spec=shr_64
+ else
+ shared_archive_member_spec=shr
+ fi
+ fi
+ ;;
+*)
+ with_aix_soname=aix
+ ;;
+esac
+
+_LT_DECL([], [shared_archive_member_spec], [0],
+ [Shared archive member basename, for filename based shared library versioning on AIX])dnl
+])# _LT_WITH_AIX_SONAME
+
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
+
+
+# _LT_WITH_PIC([MODE])
+# --------------------
+# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
+# LT_INIT options.
+# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'.
+m4_define([_LT_WITH_PIC],
+[AC_ARG_WITH([pic],
+ [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
+ [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+ [lt_p=${PACKAGE-default}
+ case $withval in
+ yes|no) pic_mode=$withval ;;
+ *)
+ pic_mode=default
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for lt_pkg in $withval; do
+ IFS=$lt_save_ifs
+ if test "X$lt_pkg" = "X$lt_p"; then
+ pic_mode=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac],
+ [pic_mode=m4_default([$1], [default])])
+
+_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+])# _LT_WITH_PIC
+
+LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+
+# Old name:
+AU_DEFUN([AC_LIBTOOL_PICMODE],
+[_LT_SET_OPTION([LT_INIT], [pic-only])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'pic-only' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+
+## ----------------- ##
+## LTDL_INIT Options ##
+## ----------------- ##
+
+m4_define([_LTDL_MODE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+ [m4_define([_LTDL_MODE], [nonrecursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+ [m4_define([_LTDL_MODE], [recursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+ [m4_define([_LTDL_MODE], [subproject])])
+
+m4_define([_LTDL_TYPE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [installable],
+ [m4_define([_LTDL_TYPE], [installable])])
+LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+ [m4_define([_LTDL_TYPE], [convenience])])
diff --git a/m4/ltsugar.m4 b/m4/ltsugar.m4
new file mode 100644
index 0000000..902508b
--- /dev/null
+++ b/m4/ltsugar.m4
@@ -0,0 +1,124 @@
+# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
+#
+# Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 Free Software
+# Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltsugar.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+
+
+# lt_join(SEP, ARG1, [ARG2...])
+# -----------------------------
+# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+# associated separator.
+# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+# versions in m4sugar had bugs.
+m4_define([lt_join],
+[m4_if([$#], [1], [],
+ [$#], [2], [[$2]],
+ [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+m4_define([_lt_join],
+[m4_if([$#$2], [2], [],
+ [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+
+
+# lt_car(LIST)
+# lt_cdr(LIST)
+# ------------
+# Manipulate m4 lists.
+# These macros are necessary as long as will still need to support
+# Autoconf-2.59, which quotes differently.
+m4_define([lt_car], [[$1]])
+m4_define([lt_cdr],
+[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+ [$#], 1, [],
+ [m4_dquote(m4_shift($@))])])
+m4_define([lt_unquote], $1)
+
+
+# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+# ------------------------------------------
+# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
+# Note that neither SEPARATOR nor STRING are expanded; they are appended
+# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+# than defined and empty).
+#
+# This macro is needed until we can rely on Autoconf 2.62, since earlier
+# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+m4_define([lt_append],
+[m4_define([$1],
+ m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+
+
+
+# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+# ----------------------------------------------------------
+# Produce a SEP delimited list of all paired combinations of elements of
+# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
+# has the form PREFIXmINFIXSUFFIXn.
+# Needed until we can rely on m4_combine added in Autoconf 2.62.
+m4_define([lt_combine],
+[m4_if(m4_eval([$# > 3]), [1],
+ [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
+[[m4_foreach([_Lt_prefix], [$2],
+ [m4_foreach([_Lt_suffix],
+ ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
+ [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
+
+
+# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+# -----------------------------------------------------------------------
+# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+m4_define([lt_if_append_uniq],
+[m4_ifdef([$1],
+ [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+ [lt_append([$1], [$2], [$3])$4],
+ [$5])],
+ [lt_append([$1], [$2], [$3])$4])])
+
+
+# lt_dict_add(DICT, KEY, VALUE)
+# -----------------------------
+m4_define([lt_dict_add],
+[m4_define([$1($2)], [$3])])
+
+
+# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+# --------------------------------------------
+m4_define([lt_dict_add_subkey],
+[m4_define([$1($2:$3)], [$4])])
+
+
+# lt_dict_fetch(DICT, KEY, [SUBKEY])
+# ----------------------------------
+m4_define([lt_dict_fetch],
+[m4_ifval([$3],
+ m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+ m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+
+
+# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+# -----------------------------------------------------------------
+m4_define([lt_if_dict_fetch],
+[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+ [$5],
+ [$6])])
+
+
+# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+# --------------------------------------------------------------
+m4_define([lt_dict_filter],
+[m4_if([$5], [], [],
+ [lt_join(m4_quote(m4_default([$4], [[, ]])),
+ lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+ [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+])
diff --git a/m4/ltversion.m4 b/m4/ltversion.m4
new file mode 100644
index 0000000..b155d0a
--- /dev/null
+++ b/m4/ltversion.m4
@@ -0,0 +1,24 @@
+# ltversion.m4 -- version numbers -*- Autoconf -*-
+#
+# Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation,
+# Inc.
+# Written by Scott James Remnant, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# @configure_input@
+
+# serial 4245 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.4.7])
+m4_define([LT_PACKAGE_REVISION], [2.4.7])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.4.7'
+macro_revision='2.4.7'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4
new file mode 100644
index 0000000..0f7a875
--- /dev/null
+++ b/m4/lt~obsolete.m4
@@ -0,0 +1,99 @@
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
+#
+# Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 Free
+# Software Foundation, Inc.
+# Written by Scott James Remnant, 2004.
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 5 lt~obsolete.m4
+
+# These exist entirely to fool aclocal when bootstrapping libtool.
+#
+# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
+# which have later been changed to m4_define as they aren't part of the
+# exported API, or moved to Autoconf or Automake where they belong.
+#
+# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
+# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+# using a macro with the same name in our local m4/libtool.m4 it'll
+# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+# and doesn't know about Autoconf macros at all.)
+#
+# So we provide this file, which has a silly filename so it's always
+# included after everything else. This provides aclocal with the
+# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+# because those macros already exist, or will be overwritten later.
+# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
+#
+# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+# Yes, that means every name once taken will need to remain here until
+# we give up compatibility with versions before 1.7, at which point
+# we need to keep only those names which we still refer to.
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+
+m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
+m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
+m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
+m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
+m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
+m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
+m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
+m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
+m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
+m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
+m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
+m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
+m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
+m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
+m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
+m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
+m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
+m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
+m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
+m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
+m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
+m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
+m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
+m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
+m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
+m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
diff --git a/m4/pcre2_check_vscript.m4 b/m4/pcre2_check_vscript.m4
new file mode 100644
index 0000000..cfe67e4
--- /dev/null
+++ b/m4/pcre2_check_vscript.m4
@@ -0,0 +1,118 @@
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_check_vscript.html
+# ===========================================================================
+#
+# Our pcre2_check_vscript.m4 is derived from the upstream ax_check_vscript.m4,
+# with several modifications.
+#
+# The original upstream file requires the following notice:
+#
+# LICENSE
+#
+# Copyright (c) 2014 Kevin Cernekee
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 2.99 PCRE2
+
+# _PCRE2_CHECK_VSCRIPT_SHLIB(flag, map-contents, action-if-link-succeeds)
+# Build a shared library with the given linker flag and map file contents.
+# This properly tests version script support by building a shared library
+# rather than an executable, avoiding issues with executable-specific symbols
+# (e.g. FreeBSD's crt1.o symbols, Solaris linker symbols in values-Xc.o).
+# Uses libtool for portability across different platforms.
+AC_DEFUN([_PCRE2_CHECK_VSCRIPT_SHLIB], [
+ rm -rf conftest.vscript
+ mkdir conftest.vscript
+ cat > conftest.vscript/conftest.c <<_ACEOF
+int hidethis(void) { return 0; }
+int exposethis(void) { return hidethis(); }
+_ACEOF
+ echo "$2" > conftest.vscript/conftest.map
+ _pcre2_abs_top_builddir="$ac_pwd"
+ _pcre2_vscript_libtool="$SHELL $_pcre2_abs_top_builddir/libtool"
+ _pcre2_vscript_cc="$CC"
+ _pcre2_vscript_compile_flags="$CFLAGS $CPPFLAGS"
+ _pcre2_vscript_ld_flags="$CFLAGS $LDFLAGS"
+ _pcre2_vscript_script_flag="$1"
+ export _pcre2_vscript_libtool
+ export _pcre2_vscript_cc
+ export _pcre2_vscript_compile_flags
+ export _pcre2_vscript_ld_flags
+ export _pcre2_vscript_script_flag
+ AS_IF([(cd conftest.vscript && \
+ $_pcre2_vscript_libtool --tag=CC --mode=compile $_pcre2_vscript_cc $_pcre2_vscript_compile_flags -c -o conftest.lo conftest.c && \
+ $_pcre2_vscript_libtool --tag=CC --mode=link $_pcre2_vscript_cc $_pcre2_vscript_ld_flags -o libconftest.la conftest.lo -rpath /usr/lib -Wl,$_pcre2_vscript_script_flag,conftest.map) >&AS_MESSAGE_LOG_FD 2>&1], [$3])
+ unset _pcre2_vscript_libtool
+ unset _pcre2_vscript_cc
+ unset _pcre2_vscript_compile_flags
+ unset _pcre2_vscript_ld_flags
+ unset _pcre2_vscript_script_flag
+ rm -rf conftest.vscript
+]) dnl _PCRE2_CHECK_VSCRIPT_SHLIB
+
+AC_DEFUN([PCRE2_CHECK_VSCRIPT], [
+
+ AC_ARG_ENABLE([symvers],
+ AS_HELP_STRING([--disable-symvers],
+ [disable library symbol versioning [default=auto]]),
+ [want_symvers=$enableval],
+ [want_symvers=yes]
+ )
+
+ AS_IF([test x$want_symvers = xyes], [
+
+ dnl First, test --version-script and -M with a simple wildcard.
+ AC_CACHE_CHECK([linker version script flag], pcre2_cv_check_vscript_flag, [
+ pcre2_cv_check_vscript_flag=unsupported
+
+ _PCRE2_CHECK_VSCRIPT_SHLIB([--version-script],
+ [PCRE2_10.00 { global: exposethis; local: *; };],
+ [pcre2_cv_check_vscript_flag=--version-script])
+ AS_IF([test x$pcre2_cv_check_vscript_flag = xunsupported], [
+ _PCRE2_CHECK_VSCRIPT_SHLIB([-M],
+ [PCRE2_10.00 { global: exposethis; local: *; };],
+ [pcre2_cv_check_vscript_flag=-M])
+ ])
+
+ dnl The linker may interpret -M (no argument) as "produce a load map."
+ dnl If "-M conftest.map" doesn't fail when conftest.map contains
+ dnl obvious syntax errors, assume this is the case.
+
+ AS_IF([test x$pcre2_cv_check_vscript_flag != xunsupported], [
+ _PCRE2_CHECK_VSCRIPT_SHLIB([$pcre2_cv_check_vscript_flag],
+ [PCRE2_10.00 { global: exposethis; local: *; }; {],
+ [pcre2_cv_check_vscript_flag=unsupported])
+ ])
+ ])
+
+ AS_IF([test x$pcre2_cv_check_vscript_flag != xunsupported], [
+
+ dnl Test without wildcard - for detecting Solaris, which requires the
+ dnl wildcard (or else a much more complex and brittle configuration).
+ AC_CACHE_CHECK([if version scripts work without wildcard],
+ pcre2_cv_check_vscript_no_star, [
+ pcre2_cv_check_vscript_no_star=no
+ _PCRE2_CHECK_VSCRIPT_SHLIB([$pcre2_cv_check_vscript_flag],
+ [PCRE2_10.00 { global: exposethis; local: hidethis; };],
+ [pcre2_cv_check_vscript_no_star=yes])
+ ])
+
+ pcre2_check_vscript_flag=$pcre2_cv_check_vscript_flag
+ pcre2_check_vscript_no_star=$pcre2_cv_check_vscript_no_star
+ ], [
+ pcre2_check_vscript_flag=
+ pcre2_check_vscript_no_star=no
+ ])
+ ], [
+ AC_MSG_CHECKING([linker version script flag])
+ AC_MSG_RESULT([disabled])
+
+ pcre2_check_vscript_flag=
+ pcre2_check_vscript_no_star=no
+ ])
+
+]) dnl PCRE2_CHECK_VSCRIPT
diff --git a/m4/pcre2_visibility.m4 b/m4/pcre2_visibility.m4
new file mode 100644
index 0000000..1e4e819
--- /dev/null
+++ b/m4/pcre2_visibility.m4
@@ -0,0 +1,85 @@
+# visibility.m4 serial 4 (gettext-0.18.2)
+dnl Copyright (C) 2005, 2008, 2010-2011 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Originally From Bruno Haible.
+
+dnl Tests whether the compiler supports the command-line option
+dnl -fvisibility=hidden and the function attribute
+dnl __attribute__((__visibility__("default"))).
+dnl
+dnl Set the variable VISIBILITY_CFLAGS.
+dnl Defines and sets the variable HAVE_VISIBILITY.
+dnl Defines and sets the variable WORKING_WERROR.
+
+dnl Modified to fit with PCRE build environment by Cristian RodrÃguez.
+dnl Adjusted for PCRE2 by PH.
+dnl Refactored to work with non GCC (but compatible) compilers.
+
+AC_DEFUN([PCRE2_VISIBILITY],
+[
+ AC_REQUIRE([AC_PROG_CC])
+ VISIBILITY_CFLAGS=
+ HAVE_VISIBILITY=0
+ dnl First, check whether -Werror can be added to the command line, or
+ dnl whether it leads to an error because of some other option that the
+ dnl user has put into $CC $CFLAGS $CPPFLAGS.
+ AC_MSG_CHECKING([whether the -Werror option is usable])
+ AC_CACHE_VAL([pcre2_cv_cc_vis_werror], [
+ pcre2_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror"
+ pcre2_cv_cc_vis_werror=no
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[]], [[]])],
+ [
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[]], [[ #warning e ]])],
+ [], [pcre2_cv_cc_vis_werror=yes]
+ )
+ ], [])
+ CFLAGS="$pcre2_save_CFLAGS"])
+ AC_MSG_RESULT([$pcre2_cv_cc_vis_werror])
+ if test -n "$pcre2_cv_cc_vis_werror" && test $pcre2_cv_cc_vis_werror = yes
+ then
+ WORKING_WERROR=1
+ else
+ WORKING_WERROR=0
+ fi
+ if test $pcre2_cv_cc_vis_werror = yes; then
+ dnl Now check whether GCC compatible visibility declarations are supported.
+ AC_MSG_CHECKING([for GCC compatible visibility declarations])
+ AC_CACHE_VAL([pcre2_cv_cc_visibility], [
+ pcre2_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+ dnl We use the option -Werror and a function dummyfunc, because on some
+ dnl platforms (Cygwin 1.7) the use of -fvisibility triggers a warning
+ dnl "visibility attribute not supported in this configuration; ignored"
+ dnl at the first function definition in every compilation unit, and we
+ dnl don't want to use the option in this case.
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void);
+ extern __attribute__((__visibility__("default"))) int exportedfunc (void);
+ void dummyfunc (void) {}
+ ]],
+ [[]])],
+ [pcre2_cv_cc_visibility=yes],
+ [pcre2_cv_cc_visibility=no])
+ CFLAGS="$pcre2_save_CFLAGS"])
+ AC_MSG_RESULT([$pcre2_cv_cc_visibility])
+ fi
+ if test -n "$pcre2_cv_cc_visibility" && test $pcre2_cv_cc_visibility = yes
+ then
+ VISIBILITY_CFLAGS="-fvisibility=hidden"
+ HAVE_VISIBILITY=1
+ AC_DEFINE(PCRE2_EXPORT, [__attribute__ ((visibility ("default")))], [Define to the annotation for making a symbol visible.])
+ else
+ AC_DEFINE(PCRE2_EXPORT, [], [Define to the annotation for making a symbol visible.])
+ fi
+ AC_SUBST([VISIBILITY_CFLAGS])
+ AC_SUBST([HAVE_VISIBILITY])
+ AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY],
+ [Define to 1 if the compiler supports GCC compatible visibility declarations.])
+])
diff --git a/m4/pcre2_zos.m4 b/m4/pcre2_zos.m4
new file mode 100644
index 0000000..2e5dbd4
--- /dev/null
+++ b/m4/pcre2_zos.m4
@@ -0,0 +1,50 @@
+dnl Tests whether the compiler requires an additional flag in order to fail on
+dnl undefined headers.
+
+dnl The concept of setting this commandline flag was learned from patches and
+dnl mailing list discussions of the gnulib and gawk projects (credit to
+dnl Bruno Haible).
+
+AC_DEFUN([PCRE2_ZOS_FIXES],
+[
+ AC_CACHE_CHECK([for OS/390 (z/OS)], [pcre2_cv_os390],
+ [if test "`uname`" = "OS/390"; then
+ pcre2_cv_os390=yes
+ else
+ pcre2_cv_os390=no
+ fi])
+ if test "$pcre2_cv_os390" = "yes"; then
+ AC_CACHE_CHECK([whether the compiler supports -qhaltonmsg=CCN3296], [pcre2_cv_xlc_qhaltonmsg_support],
+ [save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -qhaltonmsg=CCN3296"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
+ [pcre2_cv_xlc_qhaltonmsg_support=yes],
+ [pcre2_cv_xlc_qhaltonmsg_support=no])
+ CFLAGS="$save_CFLAGS"
+ ])
+
+ AC_CACHE_CHECK([whether non-existent headers fail the compile], [pcre2_cv_xlc_nonexistent_fatal],
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]])],
+ [pcre2_cv_xlc_nonexistent_fatal=no],
+ [pcre2_cv_xlc_nonexistent_fatal=yes])
+ ])
+
+ if test "$pcre2_cv_xlc_nonexistent_fatal" = "no" && test "$pcre2_cv_xlc_qhaltonmsg_support" = "yes"; then
+ AC_CACHE_CHECK([whether -qhaltonmsg=CCN3296 fixes the non-existent-header issue], [pcre2_cv_xlc_qhaltonmsg_fixes],
+ [save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -qhaltonmsg=CCN3296"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]])],
+ [pcre2_cv_xlc_qhaltonmsg_fixes=no],
+ [pcre2_cv_xlc_qhaltonmsg_fixes=yes])
+ CFLAGS="$save_CFLAGS"
+ ])
+
+ if test "$pcre2_cv_xlc_qhaltonmsg_fixes" = "no"; then
+ AC_MSG_ERROR([-qhaltonmsg=CCN3296 not effective on non-existent headers])
+ fi
+
+ CFLAGS="$CFLAGS -qhaltonmsg=CCN3296"
+ fi
+
+ fi
+])
diff --git a/missing b/missing
new file mode 100755
index 0000000..1fe1611
--- /dev/null
+++ b/missing
@@ -0,0 +1,215 @@
+#! /bin/sh
+# Common wrapper for a few potentially missing GNU programs.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1996-2021 Free Software Foundation, Inc.
+# Originally written by Fran,cois Pinard , 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try '$0 --help' for more information"
+ exit 1
+fi
+
+case $1 in
+
+ --is-lightweight)
+ # Used by our autoconf macros to check whether the available missing
+ # script is modern enough.
+ exit 0
+ ;;
+
+ --run)
+ # Back-compat with the calling convention used by older automake.
+ shift
+ ;;
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
+to PROGRAM being missing or too old.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+
+Supported PROGRAM values:
+ aclocal autoconf autoheader autom4te automake makeinfo
+ bison yacc flex lex help2man
+
+Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
+'g' are ignored when checking the name.
+
+Send bug reports to ."
+ exit $?
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing $scriptversion (GNU Automake)"
+ exit $?
+ ;;
+
+ -*)
+ echo 1>&2 "$0: unknown '$1' option"
+ echo 1>&2 "Try '$0 --help' for more information"
+ exit 1
+ ;;
+
+esac
+
+# Run the given program, remember its exit status.
+"$@"; st=$?
+
+# If it succeeded, we are done.
+test $st -eq 0 && exit 0
+
+# Also exit now if we it failed (or wasn't found), and '--version' was
+# passed; such an option is passed most likely to detect whether the
+# program is present and works.
+case $2 in --version|--help) exit $st;; esac
+
+# Exit code 63 means version mismatch. This often happens when the user
+# tries to use an ancient version of a tool on a file that requires a
+# minimum version.
+if test $st -eq 63; then
+ msg="probably too old"
+elif test $st -eq 127; then
+ # Program was missing.
+ msg="missing on your system"
+else
+ # Program was found and executed, but failed. Give up.
+ exit $st
+fi
+
+perl_URL=https://www.perl.org/
+flex_URL=https://github.com/westes/flex
+gnu_software_URL=https://www.gnu.org/software
+
+program_details ()
+{
+ case $1 in
+ aclocal|automake)
+ echo "The '$1' program is part of the GNU Automake package:"
+ echo "<$gnu_software_URL/automake>"
+ echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
+ echo "<$gnu_software_URL/autoconf>"
+ echo "<$gnu_software_URL/m4/>"
+ echo "<$perl_URL>"
+ ;;
+ autoconf|autom4te|autoheader)
+ echo "The '$1' program is part of the GNU Autoconf package:"
+ echo "<$gnu_software_URL/autoconf/>"
+ echo "It also requires GNU m4 and Perl in order to run:"
+ echo "<$gnu_software_URL/m4/>"
+ echo "<$perl_URL>"
+ ;;
+ esac
+}
+
+give_advice ()
+{
+ # Normalize program name to check for.
+ normalized_program=`echo "$1" | sed '
+ s/^gnu-//; t
+ s/^gnu//; t
+ s/^g//; t'`
+
+ printf '%s\n' "'$1' is $msg."
+
+ configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
+ case $normalized_program in
+ autoconf*)
+ echo "You should only need it if you modified 'configure.ac',"
+ echo "or m4 files included by it."
+ program_details 'autoconf'
+ ;;
+ autoheader*)
+ echo "You should only need it if you modified 'acconfig.h' or"
+ echo "$configure_deps."
+ program_details 'autoheader'
+ ;;
+ automake*)
+ echo "You should only need it if you modified 'Makefile.am' or"
+ echo "$configure_deps."
+ program_details 'automake'
+ ;;
+ aclocal*)
+ echo "You should only need it if you modified 'acinclude.m4' or"
+ echo "$configure_deps."
+ program_details 'aclocal'
+ ;;
+ autom4te*)
+ echo "You might have modified some maintainer files that require"
+ echo "the 'autom4te' program to be rebuilt."
+ program_details 'autom4te'
+ ;;
+ bison*|yacc*)
+ echo "You should only need it if you modified a '.y' file."
+ echo "You may want to install the GNU Bison package:"
+ echo "<$gnu_software_URL/bison/>"
+ ;;
+ lex*|flex*)
+ echo "You should only need it if you modified a '.l' file."
+ echo "You may want to install the Fast Lexical Analyzer package:"
+ echo "<$flex_URL>"
+ ;;
+ help2man*)
+ echo "You should only need it if you modified a dependency" \
+ "of a man page."
+ echo "You may want to install the GNU Help2man package:"
+ echo "<$gnu_software_URL/help2man/>"
+ ;;
+ makeinfo*)
+ echo "You should only need it if you modified a '.texi' file, or"
+ echo "any other file indirectly affecting the aspect of the manual."
+ echo "You might want to install the Texinfo package:"
+ echo "<$gnu_software_URL/texinfo/>"
+ echo "The spurious makeinfo call might also be the consequence of"
+ echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
+ echo "want to install GNU make:"
+ echo "<$gnu_software_URL/make/>"
+ ;;
+ *)
+ echo "You might have modified some files without having the proper"
+ echo "tools for further handling them. Check the 'README' file, it"
+ echo "often tells you about the needed prerequisites for installing"
+ echo "this package. You may also peek at any GNU archive site, in"
+ echo "case some other package contains this missing '$1' program."
+ ;;
+ esac
+}
+
+give_advice "$1" | sed -e '1s/^/WARNING: /' \
+ -e '2,$s/^/ /' >&2
+
+# Propagate the correct exit status (expected to be 127 for a program
+# not found, 63 for a program that failed due to version mismatch).
+exit $st
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/patches/pcre2-10.37-Remove-real-POSIX.patch b/patches/pcre2-10.37-Remove-real-POSIX.patch
new file mode 100644
index 0000000..a5f9d44
--- /dev/null
+++ b/patches/pcre2-10.37-Remove-real-POSIX.patch
@@ -0,0 +1,351 @@
+commit 080d7789eba00b570181dfe28809b01aa88c01f8
+Author: Philip.Hazel
+Date: Tue Apr 27 08:36:47 2021 +0000
+
+ Remove real POSIX function names from the pcre2-posix library.
+
+diff --git a/ChangeLog b/ChangeLog
+index 5d64b35d..6bc766dc 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -11,13 +11,13 @@ with binary zeros. This is from Bugzilla #2681. Patch from Jeremie
+ Courreges-Anglas via Nam Nguyen. This fixes RunGrepTest for OpenBSD. Later:
+ it broke it for at least one version of Solaris, where tr can't handle binary
+ zeros. However, that system had /usr/xpg4/bin/tr installed, which works OK, so
+-RunGrepTest now checks for that command and use it if found.
++RunGrepTest now checks for that command and uses it if found.
+
+ 2. Compiling with gcc 10.2's -fanalyzer option showed up a hypothetical problem
+ with a NULL dereference. I don't think this case could ever occur in practice,
+ but I have put in a check in order to get rid of the compiler error.
+
+-3. An alternative patch for CMakeLists.txt because 10.36 # 4 breaks CMake on
++3. An alternative patch for CMakeLists.txt because 10.36 #4 breaks CMake on
+ Windows. Patch from email@cs-ware.de fixes bugzilla #2688.
+
+ 4. Two bugs related to over-large numbers have been fixed so the behaviour is
+@@ -44,6 +44,14 @@ recursions such as /(a\K.(?1)*)/ did not have this problem.
+ 7. Restore single character repetition optimization in JIT. Currently fewer
+ character repetitions are optimized than in 10.34.
+
++8. When the names of the functions in the POSIX wrapper were changed to
++pcre2_regcomp() etc. (see change 10.33 #4 below), functions with the original
++names were left in the library so that pre-compiled programs would still work.
++However, this has proved troublesome when programs link with several libraries,
++some of which use PCRE2 via the POSIX interface while others use a native POSIX
++library. For this reason, the POSIX function names are removed in this release.
++The macros in pcre2posix.h should ensure that re-compiling fixes any programs
++that haven't been compiled since before 10.33.
+
+
+ Version 10.36 04-December-2020
+diff --git a/doc/html/pcre2posix.html b/doc/html/pcre2posix.html
+index 20a2009b..c54860f9 100644
+--- a/doc/html/pcre2posix.html
++++ b/doc/html/pcre2posix.html
+@@ -68,11 +68,14 @@ application. Because the POSIX functions call the native ones, it is also
+ necessary to add -lpcre2-8.
+
+
+-Although they are not defined as protypes in pcre2posix.h, the library
+-does contain functions with the POSIX names regcomp() etc. These simply
+-pass their arguments to the PCRE2 functions. These functions are provided for
+-backwards compatibility with earlier versions of PCRE2, so that existing
+-programs do not have to be recompiled.
++Although they were not defined as protypes in pcre2posix.h, releases
++10.33 to 10.36 of the library contained functions with the POSIX names
++regcomp() etc. These simply passed their arguments to the PCRE2
++functions. These functions were provided for backwards compatibility with
++earlier versions of PCRE2, which had only POSIX names. However, this has proved
++troublesome in situations where a program links with several libraries, some of
++which use PCRE2's POSIX interface while others use the real POSIX functions.
++For this reason, the POSIX names have been removed since release 10.37.
+
+
+ Calling the header file pcre2posix.h avoids any conflict with other POSIX
+@@ -344,9 +347,9 @@ Cambridge, England.
+
+
REVISION
+
+-Last updated: 30 January 2019
++Last updated: 26 April 2021
+
+-Copyright © 1997-2019 University of Cambridge.
++Copyright © 1997-2021 University of Cambridge.
+
+
+ Return to the PCRE2 index page.
+diff --git a/doc/pcre2.txt b/doc/pcre2.txt
+index 365ecc49..61855f19 100644
+--- a/doc/pcre2.txt
++++ b/doc/pcre2.txt
+@@ -180,8 +180,8 @@ REVISION
+ Last updated: 17 September 2018
+ Copyright (c) 1997-2018 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+ PCRE2API(3) Library Functions Manual PCRE2API(3)
+
+
+@@ -3829,8 +3829,8 @@ REVISION
+ Last updated: 04 November 2020
+ Copyright (c) 1997-2020 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+ PCRE2BUILD(3) Library Functions Manual PCRE2BUILD(3)
+
+
+@@ -4423,8 +4423,8 @@ REVISION
+ Last updated: 20 March 2020
+ Copyright (c) 1997-2020 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+ PCRE2CALLOUT(3) Library Functions Manual PCRE2CALLOUT(3)
+
+
+@@ -4853,8 +4853,8 @@ REVISION
+ Last updated: 03 February 2019
+ Copyright (c) 1997-2019 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+ PCRE2COMPAT(3) Library Functions Manual PCRE2COMPAT(3)
+
+
+@@ -5066,8 +5066,8 @@ REVISION
+ Last updated: 06 October 2020
+ Copyright (c) 1997-2019 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+ PCRE2JIT(3) Library Functions Manual PCRE2JIT(3)
+
+
+@@ -5491,8 +5491,8 @@ REVISION
+ Last updated: 23 May 2019
+ Copyright (c) 1997-2019 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+ PCRE2LIMITS(3) Library Functions Manual PCRE2LIMITS(3)
+
+
+@@ -5561,8 +5561,8 @@ REVISION
+ Last updated: 02 February 2019
+ Copyright (c) 1997-2019 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+ PCRE2MATCHING(3) Library Functions Manual PCRE2MATCHING(3)
+
+
+@@ -5785,8 +5785,8 @@ REVISION
+ Last updated: 23 May 2019
+ Copyright (c) 1997-2019 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+ PCRE2PARTIAL(3) Library Functions Manual PCRE2PARTIAL(3)
+
+
+@@ -6165,8 +6165,8 @@ REVISION
+ Last updated: 04 September 2019
+ Copyright (c) 1997-2019 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+ PCRE2PATTERN(3) Library Functions Manual PCRE2PATTERN(3)
+
+
+@@ -9613,8 +9613,8 @@ REVISION
+ Last updated: 06 October 2020
+ Copyright (c) 1997-2020 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+ PCRE2PERFORM(3) Library Functions Manual PCRE2PERFORM(3)
+
+
+@@ -9848,8 +9848,8 @@ REVISION
+ Last updated: 03 February 2019
+ Copyright (c) 1997-2019 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+ PCRE2POSIX(3) Library Functions Manual PCRE2POSIX(3)
+
+
+@@ -9895,11 +9895,15 @@ DESCRIPTION
+ an application. Because the POSIX functions call the native ones, it is
+ also necessary to add -lpcre2-8.
+
+- Although they are not defined as protypes in pcre2posix.h, the library
+- does contain functions with the POSIX names regcomp() etc. These simply
+- pass their arguments to the PCRE2 functions. These functions are pro-
+- vided for backwards compatibility with earlier versions of PCRE2, so
+- that existing programs do not have to be recompiled.
++ Although they were not defined as protypes in pcre2posix.h, releases
++ 10.33 to 10.36 of the library contained functions with the POSIX names
++ regcomp() etc. These simply passed their arguments to the PCRE2 func-
++ tions. These functions were provided for backwards compatibility with
++ earlier versions of PCRE2, which had only POSIX names. However, this
++ has proved troublesome in situations where a program links with several
++ libraries, some of which use PCRE2's POSIX interface while others use
++ the real POSIX functions. For this reason, the POSIX names have been
++ removed since release 10.37.
+
+ Calling the header file pcre2posix.h avoids any conflict with other
+ POSIX libraries. It can, of course, be renamed or aliased as regex.h,
+@@ -10175,11 +10179,11 @@ AUTHOR
+
+ REVISION
+
+- Last updated: 30 January 2019
+- Copyright (c) 1997-2019 University of Cambridge.
++ Last updated: 26 April 2021
++ Copyright (c) 1997-2021 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+ PCRE2SAMPLE(3) Library Functions Manual PCRE2SAMPLE(3)
+
+
+@@ -10457,8 +10461,8 @@ REVISION
+ Last updated: 27 June 2018
+ Copyright (c) 1997-2018 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+ PCRE2SYNTAX(3) Library Functions Manual PCRE2SYNTAX(3)
+
+
+@@ -10973,8 +10977,8 @@ REVISION
+ Last updated: 28 December 2019
+ Copyright (c) 1997-2019 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+ PCRE2UNICODE(3) Library Functions Manual PCRE2UNICODE(3)
+
+
+@@ -11408,5 +11412,5 @@ REVISION
+ Last updated: 23 February 2020
+ Copyright (c) 1997-2020 University of Cambridge.
+ ------------------------------------------------------------------------------
+-
+-
++
++
+diff --git a/doc/pcre2posix.3 b/doc/pcre2posix.3
+index 35e68e2d..a470c8f9 100644
+--- a/doc/pcre2posix.3
++++ b/doc/pcre2posix.3
+@@ -1,4 +1,4 @@
+-.TH PCRE2POSIX 3 "30 January 2019" "PCRE2 10.33"
++.TH PCRE2POSIX 3 "26 April 2021" "PCRE2 10.37"
+ .SH NAME
+ PCRE2 - Perl-compatible regular expressions (revised API)
+ .SH "SYNOPSIS"
+@@ -44,11 +44,14 @@ can be accessed by adding \fB-lpcre2-posix\fP to the command for linking an
+ application. Because the POSIX functions call the native ones, it is also
+ necessary to add \fB-lpcre2-8\fP.
+ .P
+-Although they are not defined as protypes in \fBpcre2posix.h\fP, the library
+-does contain functions with the POSIX names \fBregcomp()\fP etc. These simply
+-pass their arguments to the PCRE2 functions. These functions are provided for
+-backwards compatibility with earlier versions of PCRE2, so that existing
+-programs do not have to be recompiled.
++Although they were not defined as protypes in \fBpcre2posix.h\fP, releases
++10.33 to 10.36 of the library contained functions with the POSIX names
++\fBregcomp()\fP etc. These simply passed their arguments to the PCRE2
++functions. These functions were provided for backwards compatibility with
++earlier versions of PCRE2, which had only POSIX names. However, this has proved
++troublesome in situations where a program links with several libraries, some of
++which use PCRE2's POSIX interface while others use the real POSIX functions.
++For this reason, the POSIX names have been removed since release 10.37.
+ .P
+ Calling the header file \fBpcre2posix.h\fP avoids any conflict with other POSIX
+ libraries. It can, of course, be renamed or aliased as \fBregex.h\fP, which is
+@@ -321,6 +324,6 @@ Cambridge, England.
+ .rs
+ .sp
+ .nf
+-Last updated: 30 January 2019
+-Copyright (c) 1997-2019 University of Cambridge.
++Last updated: 26 April 2021
++Copyright (c) 1997-2021 University of Cambridge.
+ .fi
+diff --git a/src/pcre2posix.c b/src/pcre2posix.c
+index b24620a4..32c80c3f 100644
+--- a/src/pcre2posix.c
++++ b/src/pcre2posix.c
+@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+- New API code Copyright (c) 2016-2019 University of Cambridge
++ New API code Copyright (c) 2016-2021 University of Cambridge
+
+ -----------------------------------------------------------------------------
+ Redistribution and use in source and binary forms, with or without
+@@ -175,6 +175,20 @@ static const char *const pstring[] = {
+
+
+
++#if 0 /* REMOVE THIS CODE */
++
++The code below was created for 10.33 (see ChangeLog 10.33 #4) when the
++POSIX functions were given pcre2_... names instead of the traditional POSIX
++names. However, it has proved to be more troublesome than useful. There have
++been at least two cases where a program links with two others, one of which
++uses the POSIX library and the other uses the PCRE2 POSIX functions, thus
++causing two instances of the POSIX runctions to exist, leading to trouble. For
++10.37 this code is commented out. In due course it can be removed if there are
++no issues. The only small worry is the comment below about languages that do
++not include pcre2posix.h. If there are any such cases, they will have to use
++the PCRE2 names.
++
++
+ /*************************************************
+ * Wrappers with traditional POSIX names *
+ *************************************************/
+@@ -218,7 +232,7 @@ regexec(const regex_t *preg, const char *string, size_t nmatch,
+ {
+ return pcre2_regexec(preg, string, nmatch, pmatch, eflags);
+ }
+-
++#endif
+
+
+ /*************************************************
diff --git a/patches/pcre2-10.39-Fix-incorrect-detection.patch b/patches/pcre2-10.39-Fix-incorrect-detection.patch
new file mode 100644
index 0000000..6048a79
--- /dev/null
+++ b/patches/pcre2-10.39-Fix-incorrect-detection.patch
@@ -0,0 +1,73 @@
+commit 51ec2c9893e7dac762b70033b85f55801b01176c
+Author: Zoltan Herczeg
+Date: Tue Oct 5 16:40:57 2021 +0000
+
+ Fix incorrect detection of alternatives in first character search.
+
+diff --git a/ChangeLog b/ChangeLog
+index e0ac9b3b..05b317c2 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,6 +1,12 @@
+ Change Log for PCRE2
+ --------------------
+
++Version 10.39-RC1 xx-xxx-2021
++-----------------------------
++
++1. Fix incorrect detection of alternatives in first character search.
++
++
+ Version 10.38 01-October-2021
+ -----------------------------
+
+diff --git a/src/pcre2_jit_compile.c b/src/pcre2_jit_compile.c
+index 495920de..2c614065 100644
+--- a/src/pcre2_jit_compile.c
++++ b/src/pcre2_jit_compile.c
+@@ -1251,10 +1251,13 @@ SLJIT_ASSERT(*cc == OP_ONCE || *cc == OP_BRA || *cc == OP_CBRA);
+ SLJIT_ASSERT(*cc != OP_CBRA || common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] != 0);
+ SLJIT_ASSERT(start < EARLY_FAIL_ENHANCE_MAX);
+
++next_alt = cc + GET(cc, 1);
++if (*next_alt == OP_ALT)
++ fast_forward_allowed = FALSE;
++
+ do
+ {
+ count = start;
+- next_alt = cc + GET(cc, 1);
+ cc += 1 + LINK_SIZE + ((*cc == OP_CBRA) ? IMM2_SIZE : 0);
+
+ while (TRUE)
+@@ -1512,7 +1515,7 @@ do
+ {
+ count++;
+
+- if (fast_forward_allowed && *next_alt == OP_KET)
++ if (fast_forward_allowed)
+ {
+ common->fast_forward_bc_ptr = accelerated_start;
+ common->private_data_ptrs[(accelerated_start + 1) - common->start] = ((*private_data_start) << 3) | type_skip;
+@@ -1562,8 +1565,8 @@ do
+ else if (result < count)
+ result = count;
+
+- fast_forward_allowed = FALSE;
+ cc = next_alt;
++ next_alt = cc + GET(cc, 1);
+ }
+ while (*cc == OP_ALT);
+
+diff --git a/src/pcre2_jit_test.c b/src/pcre2_jit_test.c
+index f7480165..8dee16e5 100644
+--- a/src/pcre2_jit_test.c
++++ b/src/pcre2_jit_test.c
+@@ -352,6 +352,7 @@ static struct regression_test_case regression_test_cases[] = {
+ { MU, A, 0, 0, ".[ab]?.", "xx" },
+ { MU, A, 0, 0, "_[ab]+_*a", "_aa" },
+ { MU, A, 0, 0, "#(A+)#\\d+", "#A#A#0" },
++ { MU, A, 0, 0, "(?P\\d+)m|M", "4M" },
+
+ /* Bracket repeats with limit. */
+ { MU, A, 0, 0, "(?:(ab){2}){5}M", "abababababababababababM" },
diff --git a/patches/pcre2-10.40-A-Fixed-a-unicode.patch b/patches/pcre2-10.40-A-Fixed-a-unicode.patch
new file mode 100644
index 0000000..ade86ba
--- /dev/null
+++ b/patches/pcre2-10.40-A-Fixed-a-unicode.patch
@@ -0,0 +1,65 @@
+commit d4fa336fbcc388f89095b184ba6d99422cfc676c
+Author: Zoltan Herczeg
+Date: Thu Mar 24 05:34:42 2022 +0000
+
+ Fix incorrect value reading in JIT.
+
+diff --git a/src/pcre2_jit_compile.c b/src/pcre2_jit_compile.c
+index 94f6a588..7fcdac86 100644
+--- a/src/pcre2_jit_compile.c
++++ b/src/pcre2_jit_compile.c
+@@ -7489,7 +7489,7 @@ while (*cc != XCL_END)
+ {
+ SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
+ cc++;
+- if (*cc == PT_CLIST && *cc == XCL_PROP)
++ if (*cc == PT_CLIST && cc[-1] == XCL_PROP)
+ {
+ other_cases = PRIV(ucd_caseless_sets) + cc[1];
+ while (*other_cases != NOTACHAR)
+
+commit 50a51cb7e67268e6ad417eb07c9de9bfea5cc55a
+Author: Zoltan Herczeg
+Date: Wed Mar 23 07:53:25 2022 +0000
+
+ Fixed a unicode properrty matching issue in JIT
+
+diff --git a/ChangeLog b/ChangeLog
+index f0eab7ba..ffb08805 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -92,6 +92,9 @@ pattern, the optimizing "must be present for a match" character check was not
+ being flagged as caseless, causing some matches that should have succeeded to
+ fail.
+
++23. Fixed a unicode properrty matching issue in JIT. The character was not
++fully read in caseless matching.
++
+
+ Version 10.39 29-October-2021
+ -----------------------------
+diff --git a/src/pcre2_jit_compile.c b/src/pcre2_jit_compile.c
+index e7dd26c5..94f6a588 100644
+--- a/src/pcre2_jit_compile.c
++++ b/src/pcre2_jit_compile.c
+@@ -7489,7 +7489,7 @@ while (*cc != XCL_END)
+ {
+ SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
+ cc++;
+- if (*cc == PT_CLIST)
++ if (*cc == PT_CLIST && *cc == XCL_PROP)
+ {
+ other_cases = PRIV(ucd_caseless_sets) + cc[1];
+ while (*other_cases != NOTACHAR)
+diff --git a/src/pcre2_jit_test.c b/src/pcre2_jit_test.c
+index 3b57ce29..8450f0b6 100644
+--- a/src/pcre2_jit_test.c
++++ b/src/pcre2_jit_test.c
+@@ -415,6 +415,7 @@ static struct regression_test_case regression_test_cases[] = {
+ { MUP, 0, 0, 0 | F_NOMATCH, "[^\\p{Hangul}\\p{Z}]", " " },
+ { MUP, 0, 0, 0, "[\\p{Lu}\\P{Latin}]+", "c\xEA\xA4\xAE,A,b" },
+ { MUP, 0, 0, 0, "[\\x{a92e}\\p{Lu}\\P{Latin}]+", "c\xEA\xA4\xAE,A,b" },
++ { CMUP, 0, 0, 0, "[^S]\\B", "\xe2\x80\x8a" },
+
+ /* Possible empty brackets. */
+ { MU, A, 0, 0, "(?:|ab||bc|a)+d", "abcxabcabd" },
diff --git a/patches/pcre2-10.40-B-Fixed-an-issue-affecting.patch b/patches/pcre2-10.40-B-Fixed-an-issue-affecting.patch
new file mode 100644
index 0000000..c6bf2fd
--- /dev/null
+++ b/patches/pcre2-10.40-B-Fixed-an-issue-affecting.patch
@@ -0,0 +1,648 @@
+commit 03654e751e7f0700693526b67dfcadda6b42c9d0
+Author: Zoltan Herczeg